translations, minor refactoring, wgui: gradient intensity in globals, dash-frontend: remove unused window_list, process_list and window_options
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
<Button id="btn_close" sprite_src_builtin="dashboard/close.svg" color="#000000" border="2" border_color="~color_faded" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- left/right separator (menu and rest) -->
|
||||
<div flex_direction="row" gap="8" width="100%" height="100%" padding="4" interactable="0">
|
||||
<!-- LEFT MENU -->
|
||||
@@ -55,7 +55,6 @@
|
||||
<SideButton id="btn_side_apps" src_builtin="dashboard/apps.svg" tooltip="APPLICATIONS" tooltip_side="right" />
|
||||
<SideButton id="btn_side_games" src_builtin="dashboard/games.svg" tooltip="GAMES" tooltip_side="right" />
|
||||
<SideButton id="btn_side_monado" src_builtin="dashboard/monado.svg" tooltip="MONADO_RUNTIME" tooltip_side="right" />
|
||||
<!-- SideButton id="btn_side_processes" src_builtin="dashboard/window.svg" tooltip="PROCESSES" tooltip_side="right" /-->
|
||||
<rectangle height="2" color="#FFFFFF33" width="~side_sprite_size" />
|
||||
<SideButton id="btn_side_settings" src_builtin="dashboard/settings.svg" tooltip="SETTINGS" tooltip_side="right" />
|
||||
</rectangle>
|
||||
@@ -151,4 +150,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</elements>
|
||||
</layout>
|
||||
</layout>
|
||||
@@ -16,7 +16,6 @@
|
||||
<MenuButton id="btn_apps" icon="dashboard/apps.svg" translation="APPLICATIONS" />
|
||||
<MenuButton id="btn_games" icon="dashboard/games.svg" translation="GAMES" />
|
||||
<MenuButton id="btn_monado" icon="dashboard/monado.svg" text="Monado" />
|
||||
<!--MenuButton id="btn_processes" icon="dashboard/window.svg" translation="PROCESSES" /-->
|
||||
<MenuButton id="btn_settings" icon="dashboard/settings.svg" translation="SETTINGS" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<layout>
|
||||
<include src="t_tab_title.xml" />
|
||||
|
||||
<elements>
|
||||
<TabTitle translation="LIST_OF_WINDOWS" icon="dashboard/window.svg" />
|
||||
<div id="window_list_parent" />
|
||||
<TabTitle translation="LIST_OF_PROCESSES" icon="dashboard/cpu.svg" />
|
||||
<div id="process_list_parent" />
|
||||
</elements>
|
||||
</layout>
|
||||
@@ -1,9 +0,0 @@
|
||||
<layout>
|
||||
<include src="../t_group_box.xml" />
|
||||
|
||||
<elements>
|
||||
<rectangle macro="group_box" flex_direction="row" align_items="center">
|
||||
<div id="list_parent" gap="8" flex_direction="column" flex_wrap="wrap" flex_grow="1" />
|
||||
</rectangle>
|
||||
</elements>
|
||||
</layout>
|
||||
@@ -4,7 +4,6 @@
|
||||
"APPLICATIONS": "Anwendungen",
|
||||
"GAMES": "Spiele",
|
||||
"SETTINGS": "Einstellungen",
|
||||
"PROCESSES": "Prozesse",
|
||||
"HELLO_USER": "Hallo, {USER}!",
|
||||
"GENERAL_SETTINGS": "Allgemeine Einstellungen",
|
||||
"APPLICATION_LAUNCHER": "Anwendung Launcher",
|
||||
@@ -76,9 +75,14 @@
|
||||
"PIPEWIRE_HELP": "Schnelle GPU-Erfassung,\nStandard auf allen Desktops.",
|
||||
"PW_FALLBACK_HELP": "Langsame Methode mit hoher CPU-Auslastung.\nVersuchen Sie es, falls PipeWire GPU nicht funktioniert.",
|
||||
"SCREENCOPY_GPU_HELP": "Schnell, keine Bildschirmfreigabe-Popups.\nFunktioniert mit: Hyprland, Niri, River, Sway",
|
||||
"SCREENCOPY_HELP": "Langsam, keine Bildschirmfreigabe-Popups.\nFunktioniert mit: Hyprland, Niri, River, Sway"
|
||||
"SCREENCOPY_HELP": "Langsam, keine Bildschirmfreigabe-Popups.\nFunktioniert mit: Hyprland, Niri, River, Sway",
|
||||
"NONE": "Keine",
|
||||
"HMD_PINCH": "HMD + Kneifen",
|
||||
"EYE_PINCH": "Auge + Kneifen"
|
||||
},
|
||||
"AUTOSTART_APPS": "Anwendungen, die beim Start ausgeführt werden sollen"
|
||||
"AUTOSTART_APPS": "Anwendungen, die beim Start ausgeführt werden sollen",
|
||||
"HANDSFREE_POINTER": "Freihändige Modus",
|
||||
"HANDSFREE_POINTER_HELP": "Eingabe, die bei Bewegung\nder Controller verwendet wird, wenn diese nicht verfügbar sind.\nLinkes Kneifen greift, rechtes klickt."
|
||||
},
|
||||
"HELLO": "Hallo!",
|
||||
"AUDIO": {
|
||||
@@ -98,7 +102,6 @@
|
||||
"ACTIONS": {
|
||||
"RECENTER_PLAYSPACE": "Playspace neu zentrieren"
|
||||
},
|
||||
"LIST_OF_PROCESSES": "Prozessliste",
|
||||
"POPUP_ADD_DISPLAY": {
|
||||
"RESOLUTION": "Auflösung"
|
||||
},
|
||||
@@ -107,16 +110,9 @@
|
||||
"HIDE": "Verbergen",
|
||||
"REMOVE": "Entfernen",
|
||||
"SHOW": "Anzeigen",
|
||||
"PROCESS_LIST": {
|
||||
"NO_PROCESSES_FOUND": "Keine Prozesse gefunden",
|
||||
"LOCATED_ON": "auf",
|
||||
"TERMINATE_PROCESS_NAMED_X": "Prozess \"{PROCESS_NAME}\" beenden"
|
||||
},
|
||||
"PROCESS_LIST": {},
|
||||
"FAILED_TO_LAUNCH_APPLICATION": "Fehler beim Starten der Anwendung:",
|
||||
"NO_WINDOWS_FOUND": "Keine Fenster gefunden",
|
||||
"WINDOW_OPTIONS": "Fensteroptionen",
|
||||
"APPLICATION_STARTED": "Anwendung gestartet",
|
||||
"LIST_OF_WINDOWS": "Fensterliste",
|
||||
"CLOSE_WINDOW": "Fenster schließen",
|
||||
"GAME_LIST": {
|
||||
"NO_GAMES_FOUND": "Keine Spiele gefunden"
|
||||
|
||||
@@ -135,23 +135,13 @@
|
||||
"HELLO_USER": "Hello, {USER}!",
|
||||
"HIDE": "Hide",
|
||||
"HOME_SCREEN": "Home",
|
||||
"LIST_OF_PROCESSES": "Process list",
|
||||
"LIST_OF_WINDOWS": "Window list",
|
||||
"MONADO_RUNTIME": "Monado runtime",
|
||||
"NO_WINDOWS_FOUND": "No windows found",
|
||||
"POPUP_ADD_DISPLAY": {
|
||||
"RESOLUTION": "Resolution"
|
||||
},
|
||||
"PROCESS_LIST": {
|
||||
"LOCATED_ON": "on",
|
||||
"NO_PROCESSES_FOUND": "No processes found",
|
||||
"TERMINATE_PROCESS_NAMED_X": "Terminate process \"{PROCESS_NAME}\""
|
||||
},
|
||||
"PROCESSES": "Processes",
|
||||
"REMOVE": "Remove",
|
||||
"SETTINGS": "Settings",
|
||||
"SHOW": "Show",
|
||||
"TERMINATE_PROCESS": "Terminate process",
|
||||
"WIDTH": "Width",
|
||||
"WINDOW_OPTIONS": "Window options"
|
||||
"WIDTH": "Width"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
"APPLICATIONS": "Aplicaciones",
|
||||
"GAMES": "Juegos",
|
||||
"SETTINGS": "Ajustes",
|
||||
"PROCESSES": "Procesos",
|
||||
"HELLO_USER": "¡Hola, {USER}!",
|
||||
"GENERAL_SETTINGS": "Ajustes generales",
|
||||
"APPLICATION_LAUNCHER": "Lanzador de aplicaciones",
|
||||
@@ -76,9 +75,14 @@
|
||||
"PIPEWIRE_HELP": "Captura de GPU rápida,\nestándar en todos los escritorios.",
|
||||
"PW_FALLBACK_HELP": "Método lento con alto uso de CPU.\nPruébalo si PipeWire GPU no funciona",
|
||||
"SCREENCOPY_GPU_HELP": "Rápido, sin ventanas emergentes de uso compartido de pantalla.\nFunciona en: Hyprland, Niri, River, Sway",
|
||||
"SCREENCOPY_HELP": "Lento, sin ventanas emergentes de uso compartido de pantalla.\nFunciona en: Hyprland, Niri, River, Sway"
|
||||
"SCREENCOPY_HELP": "Lento, sin ventanas emergentes de uso compartido de pantalla.\nFunciona en: Hyprland, Niri, River, Sway",
|
||||
"NONE": "Ninguno",
|
||||
"HMD_PINCH": "HMD + pellizco",
|
||||
"EYE_PINCH": "Ojo + pellizco"
|
||||
},
|
||||
"AUTOSTART_APPS": "Aplicaciones a ejecutar al inicio"
|
||||
"AUTOSTART_APPS": "Aplicaciones a ejecutar al inicio",
|
||||
"HANDSFREE_POINTER": "Modo manos libres",
|
||||
"HANDSFREE_POINTER_HELP": "Entrada a utilizar cuando no\nestén disponibles los mandos de movimiento.\nPellizco con la izquierda para agarrar, con la derecha para hacer clic."
|
||||
},
|
||||
"HELLO": "¡Hola!",
|
||||
"AUDIO": {
|
||||
@@ -98,7 +102,6 @@
|
||||
"ACTIONS": {
|
||||
"RECENTER_PLAYSPACE": "Re-centrar espacio de juego"
|
||||
},
|
||||
"LIST_OF_PROCESSES": "Lista de procesos",
|
||||
"POPUP_ADD_DISPLAY": {
|
||||
"RESOLUTION": "Resolución"
|
||||
},
|
||||
@@ -107,16 +110,9 @@
|
||||
"HIDE": "Ocultar",
|
||||
"REMOVE": "Eliminar",
|
||||
"SHOW": "Mostrar",
|
||||
"PROCESS_LIST": {
|
||||
"NO_PROCESSES_FOUND": "No se encontraron procesos",
|
||||
"LOCATED_ON": "en",
|
||||
"TERMINATE_PROCESS_NAMED_X": "Terminar proceso \"{PROCESS_NAME}\""
|
||||
},
|
||||
"PROCESS_LIST": {},
|
||||
"FAILED_TO_LAUNCH_APPLICATION": "No se pudo iniciar la aplicación:",
|
||||
"NO_WINDOWS_FOUND": "No se encontraron ventanas",
|
||||
"WINDOW_OPTIONS": "Opciones de ventana",
|
||||
"APPLICATION_STARTED": "Aplicación iniciada",
|
||||
"LIST_OF_WINDOWS": "Lista de ventanas",
|
||||
"CLOSE_WINDOW": "Cerrar ventana",
|
||||
"GAME_LIST": {
|
||||
"NO_GAMES_FOUND": "No se encontraron juegos"
|
||||
|
||||
@@ -72,7 +72,10 @@
|
||||
"PIPEWIRE_HELP": "Acquisizione GPU veloce,\nstandard su tutti i desktop.",
|
||||
"PW_FALLBACK_HELP": "Metodo lento con elevato utilizzo della CPU.\nProva in caso PipeWire GPU non funzioni",
|
||||
"SCREENCOPY_GPU_HELP": "Veloce, senza popup di condivisione schermo.\nFunziona su: Hyprland, Niri, River, Sway",
|
||||
"SCREENCOPY_HELP": "Lento, nessuna finestra pop-up per la condivisione dello schermo.\nFunziona su: Hyprland, Niri, River, Sway"
|
||||
"SCREENCOPY_HELP": "Lento, nessuna finestra pop-up per la condivisione dello schermo.\nFunziona su: Hyprland, Niri, River, Sway",
|
||||
"NONE": "Nessuno",
|
||||
"HMD_PINCH": "HMD + pizzico",
|
||||
"EYE_PINCH": "Occhio + pizzico"
|
||||
},
|
||||
"POINTER_LERP_FACTOR": "Smussamento puntatore",
|
||||
"RESTART_SOFTWARE": "Riavvia il software",
|
||||
@@ -97,7 +100,9 @@
|
||||
"XR_CLICK_SENSITIVITY_RELEASE": "Sensibilità di rilascio XR",
|
||||
"XR_CLICK_SENSITIVITY_RELEASE_HELP": "Deve essere inferiore al clic",
|
||||
"XWAYLAND_BY_DEFAULT": "Esegui le app in modalità Compatibilità per impostazione predefinita",
|
||||
"AUTOSTART_APPS": "App da avviare all'avvio"
|
||||
"AUTOSTART_APPS": "App da avviare all'avvio",
|
||||
"HANDSFREE_POINTER": "Modalità a mani libere",
|
||||
"HANDSFREE_POINTER_HELP": "Input da usare quando i\ncontroller di movimento non sono disponibili.\nPizzico sinistro per afferrare, destro per cliccare."
|
||||
},
|
||||
"APPLICATION_LAUNCHER": "Lanciatore applicazioni",
|
||||
"APPLICATION_STARTED": "Applicazione avviata",
|
||||
@@ -130,23 +135,14 @@
|
||||
"HELLO_USER": "Ciao, {USER}!",
|
||||
"HIDE": "Nascondi",
|
||||
"HOME_SCREEN": "Home",
|
||||
"LIST_OF_PROCESSES": "Lista dei processi",
|
||||
"LIST_OF_WINDOWS": "Elenco finestre",
|
||||
"MONADO_RUNTIME": "Runtime Monado",
|
||||
"NO_WINDOWS_FOUND": "Nessuna finestra trovata",
|
||||
"POPUP_ADD_DISPLAY": {
|
||||
"RESOLUTION": "Risoluzione"
|
||||
},
|
||||
"PROCESS_LIST": {
|
||||
"LOCATED_ON": "su",
|
||||
"NO_PROCESSES_FOUND": "Nessun processo trovato",
|
||||
"TERMINATE_PROCESS_NAMED_X": "Termina processo \"{PROCESS_NAME}\""
|
||||
},
|
||||
"PROCESSES": "Processi",
|
||||
"PROCESS_LIST": {},
|
||||
"REMOVE": "Rimuovi",
|
||||
"SETTINGS": "Impostazioni",
|
||||
"SHOW": "Mostra",
|
||||
"TERMINATE_PROCESS": "Termina processo",
|
||||
"WIDTH": "Larghezza",
|
||||
"WINDOW_OPTIONS": "Opzioni finestra"
|
||||
"WIDTH": "Larghezza"
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
"APPLICATIONS": "アプリ",
|
||||
"GAMES": "ゲーム",
|
||||
"SETTINGS": "設定",
|
||||
"PROCESSES": "プロセス",
|
||||
"HELLO_USER": "こんにちは、{USER}!",
|
||||
"GENERAL_SETTINGS": "全般設定",
|
||||
"APPLICATION_LAUNCHER": "アプリケーションランチャー",
|
||||
@@ -76,9 +75,14 @@
|
||||
"PIPEWIRE_HELP": "GPU高速キャプチャ。\nすべてのデスクトップで標準です。",
|
||||
"PW_FALLBACK_HELP": "CPU使用量が多い低速な方法です。\nPipeWire GPUが動作しない場合に試してください。",
|
||||
"SCREENCOPY_GPU_HELP": "高速で、スクリーン共有ポップアップはありません。\n動作する環境: Hyprland, Niri, River, Sway",
|
||||
"SCREENCOPY_HELP": "遅延あり、画面共有ポップアップなし。\n動作する環境: Hyprland, Niri, River, Sway"
|
||||
"SCREENCOPY_HELP": "遅延あり、画面共有ポップアップなし。\n動作する環境: Hyprland, Niri, River, Sway",
|
||||
"NONE": "なし",
|
||||
"HMD_PINCH": "HMD + ピンチ",
|
||||
"EYE_PINCH": "つまんで目を合わせる"
|
||||
},
|
||||
"AUTOSTART_APPS": "起動時に実行するアプリ"
|
||||
"AUTOSTART_APPS": "起動時に実行するアプリ",
|
||||
"HANDSFREE_POINTER": "ハンズフリーモード",
|
||||
"HANDSFREE_POINTER_HELP": "モーションコントローラーが利用できない場合の入力方法。\n左手のピンチは掴み、右手のピンチはクリックです。"
|
||||
},
|
||||
"HELLO": "こんにちは!",
|
||||
"AUDIO": {
|
||||
@@ -98,7 +102,6 @@
|
||||
"ACTIONS": {
|
||||
"RECENTER_PLAYSPACE": "プレイスペースを再中央"
|
||||
},
|
||||
"LIST_OF_PROCESSES": "プロセスのリスト",
|
||||
"POPUP_ADD_DISPLAY": {
|
||||
"RESOLUTION": "解像度"
|
||||
},
|
||||
@@ -107,16 +110,9 @@
|
||||
"HIDE": "隠す",
|
||||
"REMOVE": "削除",
|
||||
"SHOW": "表示",
|
||||
"PROCESS_LIST": {
|
||||
"NO_PROCESSES_FOUND": "プロセスが見つかりませんでした",
|
||||
"LOCATED_ON": "に",
|
||||
"TERMINATE_PROCESS_NAMED_X": "プロセス \"{PROCESS_NAME}\" を終了します"
|
||||
},
|
||||
"PROCESS_LIST": {},
|
||||
"FAILED_TO_LAUNCH_APPLICATION": "アプリケーションの起動に失敗しました:",
|
||||
"NO_WINDOWS_FOUND": "ウィンドウが見つかりませんでした",
|
||||
"WINDOW_OPTIONS": "ウィンドウオプション",
|
||||
"APPLICATION_STARTED": "アプリケーションが起動しました",
|
||||
"LIST_OF_WINDOWS": "ウィンドウ一覧",
|
||||
"CLOSE_WINDOW": "ウィンドウを閉じる",
|
||||
"GAME_LIST": {
|
||||
"NO_GAMES_FOUND": "ゲームが見つかりませんでした"
|
||||
|
||||
@@ -70,9 +70,14 @@
|
||||
"PIPEWIRE_HELP": "Szybkie przechwytywanie GPU,\nstandard na wszystkich komputerach.",
|
||||
"PW_FALLBACK_HELP": "Powolna metoda z wysokim użyciem procesora.\nWypróbuj w przypadku, gdy PipeWire GPU nie działa",
|
||||
"SCREENCOPY_GPU_HELP": "Szybkie działanie, brak wyskakujących okien z informacją o udostępnianiu ekranu.\nDziała na: Hyprland, Niri, River, Sway",
|
||||
"SCREENCOPY_HELP": "Wolne, bez wyskakujących okienek udostępniania ekranu.\nDziała na: Hyprland, Niri, River, Sway"
|
||||
"SCREENCOPY_HELP": "Wolne, bez wyskakujących okienek udostępniania ekranu.\nDziała na: Hyprland, Niri, River, Sway",
|
||||
"NONE": "Brak",
|
||||
"HMD_PINCH": "HMD + szczyknięcie",
|
||||
"EYE_PINCH": "Ściśnięcie palcami + oko"
|
||||
},
|
||||
"AUTOSTART_APPS": "Aplikacje do uruchomienia przy starcie"
|
||||
"AUTOSTART_APPS": "Aplikacje do uruchomienia przy starcie",
|
||||
"HANDSFREE_POINTER": "Tryb bez użycia rąk",
|
||||
"HANDSFREE_POINTER_HELP": "Wejście do użycia, gdy kontrolery ruchu\nsą niedostępne. Lewy szczyptak to chwyt,\nprawy to kliknięcie."
|
||||
},
|
||||
"APPLICATION_LAUNCHER": "Uruchamiacz aplikacji",
|
||||
"APPLICATIONS": "Aplikacje",
|
||||
@@ -97,7 +102,6 @@
|
||||
"HELLO_USER": "Witaj, {USER}!",
|
||||
"HIDE": "Ukryj",
|
||||
"HOME_SCREEN": "Ekran główny",
|
||||
"LIST_OF_PROCESSES": "Lista procesów",
|
||||
"MONADO_RUNTIME": "Środowisko Monado",
|
||||
"POPUP_ADD_DISPLAY": {
|
||||
"RESOLUTION": "Rozdzielczość"
|
||||
@@ -106,17 +110,9 @@
|
||||
"SETTINGS": "Ustawienia",
|
||||
"SHOW": "Pokaż",
|
||||
"WIDTH": "Szerokość",
|
||||
"PROCESSES": "Procesy",
|
||||
"PROCESS_LIST": {
|
||||
"NO_PROCESSES_FOUND": "Nie znaleziono procesów",
|
||||
"LOCATED_ON": "na",
|
||||
"TERMINATE_PROCESS_NAMED_X": "Zakończ proces \"{PROCESS_NAME}\""
|
||||
},
|
||||
"PROCESS_LIST": {},
|
||||
"FAILED_TO_LAUNCH_APPLICATION": "Nie udało się uruchomić aplikacji:",
|
||||
"NO_WINDOWS_FOUND": "Nie znaleziono okien",
|
||||
"WINDOW_OPTIONS": "Opcje okna",
|
||||
"APPLICATION_STARTED": "Aplikacja uruchomiona",
|
||||
"LIST_OF_WINDOWS": "Lista okien",
|
||||
"CLOSE_WINDOW": "Zamknij okno",
|
||||
"GAME_LIST": {
|
||||
"NO_GAMES_FOUND": "Nie znaleziono gier"
|
||||
|
||||
@@ -72,7 +72,10 @@
|
||||
"PIPEWIRE_HELP": "快速 GPU 采集,\n所有桌面环境的标准方式。",
|
||||
"PW_FALLBACK_HELP": "高 CPU 占用的慢速方法。\n在 PipeWire GPU 不起作用时尝试。",
|
||||
"SCREENCOPY_GPU_HELP": "快速,无屏幕共享弹窗。\n支持:Hyprland, Niri, River, Sway",
|
||||
"SCREENCOPY_HELP": "慢速,无屏幕共享弹窗。\n支持:Hyprland, Niri, River, Sway"
|
||||
"SCREENCOPY_HELP": "慢速,无屏幕共享弹窗。\n支持:Hyprland, Niri, River, Sway",
|
||||
"NONE": "无",
|
||||
"HMD_PINCH": "HMD + 捏合",
|
||||
"EYE_PINCH": "眼睛 + 捏合"
|
||||
},
|
||||
"POINTER_LERP_FACTOR": "指针平滑",
|
||||
"RESTART_SOFTWARE": "重启软件",
|
||||
@@ -97,7 +100,9 @@
|
||||
"XR_CLICK_SENSITIVITY_RELEASE": "XR 释放灵敏度",
|
||||
"XR_CLICK_SENSITIVITY_RELEASE_HELP": "必须低于点击灵敏度",
|
||||
"XWAYLAND_BY_DEFAULT": "默认以兼容模式运行应用",
|
||||
"AUTOSTART_APPS": "开机启动应用"
|
||||
"AUTOSTART_APPS": "开机启动应用",
|
||||
"HANDSFREE_POINTER": "免提模式",
|
||||
"HANDSFREE_POINTER_HELP": "当运动控制器不可用时使用的输入。\n左手捏合为抓取,右手为点击。"
|
||||
},
|
||||
"APPLICATION_LAUNCHER": "应用启动器",
|
||||
"APPLICATION_STARTED": "应用已启动",
|
||||
@@ -130,23 +135,14 @@
|
||||
"HELLO_USER": "你好,{USER}!",
|
||||
"HIDE": "隐藏",
|
||||
"HOME_SCREEN": "主页",
|
||||
"LIST_OF_PROCESSES": "进程列表",
|
||||
"LIST_OF_WINDOWS": "窗口列表",
|
||||
"MONADO_RUNTIME": "Monado 运行时",
|
||||
"NO_WINDOWS_FOUND": "未找到窗口",
|
||||
"POPUP_ADD_DISPLAY": {
|
||||
"RESOLUTION": "分辨率"
|
||||
},
|
||||
"PROCESS_LIST": {
|
||||
"LOCATED_ON": "位于",
|
||||
"NO_PROCESSES_FOUND": "未找到进程",
|
||||
"TERMINATE_PROCESS_NAMED_X": "终止名为 \"{PROCESS_NAME}\" 的进程"
|
||||
},
|
||||
"PROCESSES": "进程",
|
||||
"PROCESS_LIST": {},
|
||||
"REMOVE": "移除",
|
||||
"SETTINGS": "设置",
|
||||
"SHOW": "显示",
|
||||
"TERMINATE_PROCESS": "终止进程",
|
||||
"WIDTH": "宽度",
|
||||
"WINDOW_OPTIONS": "窗口选项"
|
||||
"WIDTH": "宽度"
|
||||
}
|
||||
@@ -18,10 +18,7 @@ use wlx_common::{audio, dash_interface::BoxDashInterface, timestep::Timestep};
|
||||
|
||||
use crate::{
|
||||
assets,
|
||||
tab::{
|
||||
Tab, TabType, apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, processes::TabProcesses,
|
||||
settings::TabSettings,
|
||||
},
|
||||
tab::{Tab, TabType, apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, settings::TabSettings},
|
||||
util::{
|
||||
popup_manager::{MountPopupParams, PopupManager, PopupManagerParams},
|
||||
toast_manager::ToastManager,
|
||||
@@ -358,7 +355,6 @@ impl<T: 'static> Frontend<T> {
|
||||
TabType::Apps => Box::new(TabApps::new(self, widget_content.id, data)?),
|
||||
TabType::Games => Box::new(TabGames::new(self, widget_content.id)?),
|
||||
TabType::Monado => Box::new(TabMonado::new(self, widget_content.id)?),
|
||||
TabType::Processes => Box::new(TabProcesses::new(self, widget_content.id)?),
|
||||
TabType::Settings => Box::new(TabSettings::new(self, widget_content.id, data)?),
|
||||
};
|
||||
|
||||
@@ -402,12 +398,6 @@ impl<T: 'static> Frontend<T> {
|
||||
FrontendTask::SetTab(TabType::Monado),
|
||||
);
|
||||
|
||||
// "Processes" side button
|
||||
// self.tasks.handle_button(
|
||||
// &self.state.fetch_component_as::<ComponentButton>("btn_side_processes")?,
|
||||
// FrontendTask::SetTab(TabType::Processes),
|
||||
// );
|
||||
|
||||
// "Settings" side button
|
||||
self.tasks.handle_button(
|
||||
&self.state.fetch_component_as::<ComponentButton>("btn_side_settings")?,
|
||||
|
||||
@@ -4,7 +4,6 @@ pub mod apps;
|
||||
pub mod games;
|
||||
pub mod home;
|
||||
pub mod monado;
|
||||
pub mod processes;
|
||||
pub mod settings;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
@@ -13,7 +12,6 @@ pub enum TabType {
|
||||
Apps,
|
||||
Games,
|
||||
Monado,
|
||||
Processes,
|
||||
Settings,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
layout::WidgetID,
|
||||
parser::{Fetchable, ParseDocumentParams, ParserState},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
frontend::Frontend,
|
||||
tab::{Tab, TabType},
|
||||
views::{process_list, window_list},
|
||||
};
|
||||
|
||||
pub struct TabProcesses<T> {
|
||||
#[allow(dead_code)]
|
||||
pub state: ParserState,
|
||||
|
||||
view_window_list: window_list::View,
|
||||
view_process_list: process_list::View,
|
||||
marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Tab<T> for TabProcesses<T> {
|
||||
fn get_type(&self) -> TabType {
|
||||
TabType::Games
|
||||
}
|
||||
|
||||
fn update(&mut self, frontend: &mut Frontend<T>, data: &mut T) -> anyhow::Result<()> {
|
||||
self
|
||||
.view_window_list
|
||||
.update(&mut frontend.layout, &mut frontend.interface, data)?;
|
||||
self
|
||||
.view_process_list
|
||||
.update(&mut frontend.layout, &mut frontend.interface, data)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> TabProcesses<T> {
|
||||
pub fn new(frontend: &mut Frontend<T>, parent_id: WidgetID) -> anyhow::Result<Self> {
|
||||
let globals = frontend.layout.state.globals.clone();
|
||||
let state = wgui::parser::parse_from_assets(
|
||||
&ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/tab/processes.xml"),
|
||||
extra: Default::default(),
|
||||
},
|
||||
&mut frontend.layout,
|
||||
parent_id,
|
||||
)?;
|
||||
|
||||
Ok(Self {
|
||||
view_window_list: window_list::View::new(window_list::Params {
|
||||
layout: &mut frontend.layout,
|
||||
parent_id: state.get_widget_id("window_list_parent")?,
|
||||
globals: globals.clone(),
|
||||
frontend_tasks: frontend.tasks.clone(),
|
||||
on_click: None,
|
||||
})?,
|
||||
view_process_list: process_list::View::new(process_list::Params {
|
||||
layout: &mut frontend.layout,
|
||||
parent_id: state.get_widget_id("process_list_parent")?,
|
||||
globals,
|
||||
})?,
|
||||
state,
|
||||
marker: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,8 @@ pub struct AppManifest {
|
||||
pub last_played: Option<u64>, // unix timestamp
|
||||
}
|
||||
|
||||
// TODO @oo8dev: game sort methods
|
||||
#[allow(dead_code)]
|
||||
pub enum GameSortMethod {
|
||||
NameAsc,
|
||||
NameDesc,
|
||||
@@ -119,6 +121,15 @@ struct AppEntry {
|
||||
pub app_id: AppID,
|
||||
}
|
||||
|
||||
pub fn launch(app_id: &AppID) -> anyhow::Result<()> {
|
||||
log::info!("Launching Steam game with AppID {}", app_id);
|
||||
call_steam(&format!("steam://rungameid/{}", app_id))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TODO @oo8dev: running games list (#398)
|
||||
/*
|
||||
|
||||
pub fn stop(app_id: AppID, force_kill: bool) -> anyhow::Result<()> {
|
||||
log::info!("Stopping Steam game with AppID {}", app_id);
|
||||
|
||||
@@ -137,12 +148,6 @@ pub fn stop(app_id: AppID, force_kill: bool) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn launch(app_id: &AppID) -> anyhow::Result<()> {
|
||||
log::info!("Launching Steam game with AppID {}", app_id);
|
||||
call_steam(&format!("steam://rungameid/{}", app_id))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct RunningGame {
|
||||
pub app_id: AppID,
|
||||
@@ -215,7 +220,7 @@ pub fn list_running_games() -> anyhow::Result<Vec<RunningGame>> {
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
} */
|
||||
|
||||
fn call_steam(arg: &str) -> anyhow::Result<()> {
|
||||
match std::process::Command::new("xdg-open").arg(arg).spawn() {
|
||||
|
||||
@@ -1,77 +1,3 @@
|
||||
use std::{path::PathBuf, rc::Rc, str::FromStr};
|
||||
use wgui::{
|
||||
assets::{AssetPath, AssetPathOwned},
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::{Layout, WidgetID},
|
||||
renderer_vk::text::custom_glyph::CustomGlyphData,
|
||||
taffy::{self, prelude::length},
|
||||
widget::{
|
||||
label::{WidgetLabel, WidgetLabelParams},
|
||||
sprite::{WidgetSprite, WidgetSpriteParams},
|
||||
},
|
||||
};
|
||||
use wlx_common::desktop_finder;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub type AsyncExecutor = Rc<smol::LocalExecutor<'static>>;
|
||||
|
||||
// the compiler wants to scream
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
pub fn get_desktop_file_icon_path(desktop_file: &desktop_finder::DesktopEntry) -> AssetPathOwned {
|
||||
/*
|
||||
FIXME: why is the compiler complaining about trailing irrefutable patterns there?!?!
|
||||
looking at the PathBuf::from_str implementation, it always returns Ok() and it's inline, maybe that's why.
|
||||
*/
|
||||
if let Some(icon) = &desktop_file.icon_path
|
||||
&& let Ok(path) = PathBuf::from_str(icon)
|
||||
{
|
||||
return AssetPathOwned::File(path);
|
||||
}
|
||||
|
||||
AssetPathOwned::BuiltIn(PathBuf::from_str("dashboard/terminal.svg").unwrap())
|
||||
}
|
||||
|
||||
pub fn mount_simple_label(
|
||||
globals: &WguiGlobals,
|
||||
layout: &mut Layout,
|
||||
parent_id: WidgetID,
|
||||
translation: Translation,
|
||||
) -> anyhow::Result<()> {
|
||||
layout.add_child(
|
||||
parent_id,
|
||||
WidgetLabel::create(
|
||||
&mut globals.get(),
|
||||
WidgetLabelParams {
|
||||
content: translation,
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
taffy::Style::default(),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn mount_simple_sprite_square(
|
||||
globals: &WguiGlobals,
|
||||
layout: &mut Layout,
|
||||
parent_id: WidgetID,
|
||||
size_px: f32,
|
||||
path: AssetPath,
|
||||
) -> anyhow::Result<()> {
|
||||
layout.add_child(
|
||||
parent_id,
|
||||
WidgetSprite::create(WidgetSpriteParams {
|
||||
glyph_data: Some(CustomGlyphData::from_assets(globals, path)?),
|
||||
..Default::default()
|
||||
}),
|
||||
taffy::Style {
|
||||
size: taffy::Size {
|
||||
width: length(size_px),
|
||||
height: length(size_px),
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ enum CompositorMode {
|
||||
enum Task {
|
||||
SetCompositor(CompositorMode),
|
||||
SetRes(ResMode),
|
||||
SetPos(PosMode),
|
||||
SetPos(PosMode), // TODO?
|
||||
SetOrientation(OrientationMode),
|
||||
SetAutoStart(bool),
|
||||
Launch,
|
||||
|
||||
@@ -111,7 +111,7 @@ struct MultiSelectorParams<'a> {
|
||||
|
||||
fn mount_multi_selector(params: MultiSelectorParams) -> anyhow::Result<()> {
|
||||
let globals = params.ess.layout.state.globals.clone();
|
||||
let accent_color = globals.get().defaults.accent_color;
|
||||
let accent_color = globals.defaults().accent_color;
|
||||
|
||||
for cell in params.cells {
|
||||
let highlighted = cell.key == params.def_cell;
|
||||
|
||||
@@ -10,7 +10,7 @@ use wgui::{
|
||||
drawing::{self, GradientMode},
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::{Layout, WidgetID, WidgetPair},
|
||||
layout::{Layout, WidgetID},
|
||||
renderer_vk::text::{FontWeight, HorizontalAlign, TextShadow, TextStyle, custom_glyph::CustomGlyphData},
|
||||
taffy::{
|
||||
self, AlignItems, AlignSelf, JustifyContent, JustifySelf,
|
||||
@@ -47,7 +47,6 @@ pub struct Params<'a, 'b> {
|
||||
|
||||
pub struct View {
|
||||
pub button: Rc<ComponentButton>,
|
||||
pair: WidgetPair,
|
||||
id_image_parent: WidgetID,
|
||||
app_name: String,
|
||||
app_id: AppID,
|
||||
@@ -289,7 +288,6 @@ impl View {
|
||||
.detach();
|
||||
|
||||
Ok(View {
|
||||
pair: widget_button,
|
||||
button,
|
||||
id_image_parent: image_parent.id,
|
||||
app_name: params.manifest.name.clone(),
|
||||
|
||||
@@ -18,7 +18,7 @@ use crate::{
|
||||
util::{
|
||||
cached_fetcher::CoverArt,
|
||||
popup_manager::{MountPopupParams, PopupHandle},
|
||||
steam_utils::{self, AppID, AppManifest, SteamUtils},
|
||||
steam_utils::{self, AppID, SteamUtils},
|
||||
various::AsyncExecutor,
|
||||
},
|
||||
views::{self, game_cover, game_launcher},
|
||||
@@ -42,7 +42,6 @@ pub struct Params<'a> {
|
||||
|
||||
pub struct Cell {
|
||||
view_cover: game_cover::View,
|
||||
manifest: AppManifest,
|
||||
}
|
||||
|
||||
struct State {
|
||||
@@ -156,13 +155,7 @@ fn fill_game_list(
|
||||
})
|
||||
});
|
||||
|
||||
cells.insert(
|
||||
manifest.app_id.clone(),
|
||||
Cell {
|
||||
view_cover,
|
||||
manifest: manifest.clone(),
|
||||
},
|
||||
);
|
||||
cells.insert(manifest.app_id.clone(), Cell { view_cover });
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -3,6 +3,3 @@ pub mod audio_settings;
|
||||
pub mod game_cover;
|
||||
pub mod game_launcher;
|
||||
pub mod game_list;
|
||||
pub mod process_list;
|
||||
pub mod window_list;
|
||||
pub mod window_options;
|
||||
|
||||
@@ -1,255 +0,0 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use wayvr_ipc::packet_server::{self};
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
components::{
|
||||
self,
|
||||
button::ComponentButton,
|
||||
tooltip::{TooltipInfo, TooltipSide},
|
||||
},
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::{Layout, WidgetID},
|
||||
parser::{Fetchable, ParseDocumentParams, ParserState},
|
||||
taffy::{self, prelude::length},
|
||||
task::Tasks,
|
||||
widget::{
|
||||
ConstructEssentials,
|
||||
div::WidgetDiv,
|
||||
label::{WidgetLabel, WidgetLabelParams},
|
||||
},
|
||||
};
|
||||
use wlx_common::{dash_interface::BoxDashInterface, desktop_finder::DesktopEntry};
|
||||
|
||||
use crate::util::{self, various::get_desktop_file_icon_path};
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Task {
|
||||
Refresh,
|
||||
TerminateProcess(packet_server::WvrProcess),
|
||||
}
|
||||
|
||||
pub struct Params<'a> {
|
||||
pub globals: WguiGlobals,
|
||||
pub layout: &'a mut Layout,
|
||||
pub parent_id: WidgetID,
|
||||
}
|
||||
|
||||
pub struct View {
|
||||
#[allow(dead_code)]
|
||||
pub parser_state: ParserState,
|
||||
tasks: Tasks<Task>,
|
||||
globals: WguiGlobals,
|
||||
id_list_parent: WidgetID,
|
||||
}
|
||||
|
||||
impl View {
|
||||
pub fn new(params: Params) -> anyhow::Result<Self> {
|
||||
let doc_params = &ParseDocumentParams {
|
||||
globals: params.globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/view/process_list.xml"),
|
||||
extra: Default::default(),
|
||||
};
|
||||
|
||||
let parser_state = wgui::parser::parse_from_assets(doc_params, params.layout, params.parent_id)?;
|
||||
let list_parent = parser_state.fetch_widget(¶ms.layout.state, "list_parent")?;
|
||||
|
||||
let tasks = Tasks::new();
|
||||
|
||||
tasks.push(Task::Refresh);
|
||||
|
||||
Ok(Self {
|
||||
parser_state,
|
||||
tasks,
|
||||
globals: params.globals,
|
||||
id_list_parent: list_parent.id,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update<T>(
|
||||
&mut self,
|
||||
layout: &mut Layout,
|
||||
interface: &mut BoxDashInterface<T>,
|
||||
data: &mut T,
|
||||
) -> anyhow::Result<()> {
|
||||
loop {
|
||||
let tasks = self.tasks.drain();
|
||||
if tasks.is_empty() {
|
||||
break;
|
||||
}
|
||||
for task in tasks {
|
||||
match task {
|
||||
Task::Refresh => self.refresh(layout, interface, data)?,
|
||||
Task::TerminateProcess(process) => self.action_terminate_process(interface, data, process)?,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_desktop_entry_from_process(process: &packet_server::WvrProcess) -> Option<DesktopEntry> {
|
||||
// TODO: refactor this after we ditch old wayvr-dashboard completely
|
||||
let Some(dfile_str) = process.userdata.get("desktop-entry") else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let Ok(desktop_file) = serde_json::from_str::<DesktopEntry>(dfile_str) else {
|
||||
debug_assert!(false); // invalid json???
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(desktop_file)
|
||||
}
|
||||
|
||||
struct ProcessEntryResult {
|
||||
btn_terminate: Rc<ComponentButton>,
|
||||
}
|
||||
|
||||
fn construct_process_entry(
|
||||
ess: &mut ConstructEssentials,
|
||||
globals: &WguiGlobals,
|
||||
process: &packet_server::WvrProcess,
|
||||
) -> anyhow::Result<ProcessEntryResult> {
|
||||
let (cell, _) = ess.layout.add_child(
|
||||
ess.parent,
|
||||
WidgetDiv::create(),
|
||||
taffy::Style {
|
||||
flex_direction: taffy::FlexDirection::Row,
|
||||
align_items: Some(taffy::AlignItems::Center),
|
||||
gap: length(8.0),
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
let text_terminate_process = Translation::from_raw_text_string(globals.i18n().translate_and_replace(
|
||||
"PROCESS_LIST.TERMINATE_PROCESS_NAMED_X",
|
||||
("{PROCESS_NAME}", &process.name),
|
||||
));
|
||||
|
||||
//"Terminate process" button
|
||||
let (_, btn_terminate) = components::button::construct(
|
||||
&mut ConstructEssentials {
|
||||
layout: ess.layout,
|
||||
parent: cell.id,
|
||||
},
|
||||
components::button::Params {
|
||||
sprite_src: Some(AssetPath::BuiltIn("dashboard/remove_circle.svg")),
|
||||
tooltip: Some(TooltipInfo {
|
||||
text: text_terminate_process,
|
||||
side: TooltipSide::Right,
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
if let Some(desktop_file) = get_desktop_entry_from_process(process) {
|
||||
// desktop file icon and process name
|
||||
util::various::mount_simple_sprite_square(
|
||||
globals,
|
||||
ess.layout,
|
||||
cell.id,
|
||||
24.0,
|
||||
get_desktop_file_icon_path(&desktop_file).as_ref(),
|
||||
)?;
|
||||
|
||||
util::various::mount_simple_label(
|
||||
globals,
|
||||
ess.layout,
|
||||
cell.id,
|
||||
Translation::from_raw_text_rc(desktop_file.app_name.clone()),
|
||||
)?;
|
||||
} else {
|
||||
// just show a process name
|
||||
util::various::mount_simple_label(
|
||||
globals,
|
||||
ess.layout,
|
||||
cell.id,
|
||||
Translation::from_raw_text_string(process.name.clone()),
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(ProcessEntryResult { btn_terminate })
|
||||
}
|
||||
|
||||
fn fill_process_list(
|
||||
globals: &WguiGlobals,
|
||||
ess: &mut ConstructEssentials,
|
||||
tasks: &Tasks<Task>,
|
||||
list: &Vec<packet_server::WvrProcess>,
|
||||
) -> anyhow::Result<()> {
|
||||
for process_entry in list {
|
||||
let entry_res = construct_process_entry(ess, globals, process_entry)?;
|
||||
|
||||
entry_res.btn_terminate.on_click({
|
||||
let tasks = tasks.clone();
|
||||
let entry = process_entry.clone();
|
||||
Rc::new(move |_, _| {
|
||||
tasks.push(Task::TerminateProcess(entry.clone()));
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl View {
|
||||
fn refresh<T>(
|
||||
&mut self,
|
||||
layout: &mut Layout,
|
||||
interface: &mut BoxDashInterface<T>,
|
||||
data: &mut T,
|
||||
) -> anyhow::Result<()> {
|
||||
layout.remove_children(self.id_list_parent);
|
||||
|
||||
let mut text: Option<Translation> = None;
|
||||
match interface.process_list(data) {
|
||||
Ok(list) => {
|
||||
if list.is_empty() {
|
||||
text = Some(Translation::from_translation_key("PROCESS_LIST.NO_PROCESSES_FOUND"))
|
||||
} else {
|
||||
fill_process_list(
|
||||
&self.globals,
|
||||
&mut ConstructEssentials {
|
||||
layout,
|
||||
parent: self.id_list_parent,
|
||||
},
|
||||
&self.tasks,
|
||||
&list,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Err(e) => text = Some(Translation::from_raw_text(&format!("Error: {:?}", e))),
|
||||
}
|
||||
|
||||
if let Some(text) = text.take() {
|
||||
layout.add_child(
|
||||
self.id_list_parent,
|
||||
WidgetLabel::create(
|
||||
&mut self.globals.get(),
|
||||
WidgetLabelParams {
|
||||
content: text,
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
Default::default(),
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn action_terminate_process<T>(
|
||||
&mut self,
|
||||
interface: &mut BoxDashInterface<T>,
|
||||
data: &mut T,
|
||||
process: packet_server::WvrProcess,
|
||||
) -> anyhow::Result<()> {
|
||||
interface.process_terminate(data, process.handle)?;
|
||||
self.tasks.push(Task::Refresh);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,290 +0,0 @@
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use wayvr_ipc::packet_server::{self, WvrWindowHandle};
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
components::{self, button::ComponentButton},
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::{Layout, WidgetID, WidgetPair},
|
||||
parser::{Fetchable, ParseDocumentParams, ParserState},
|
||||
renderer_vk::text::{FontWeight, HorizontalAlign, TextStyle},
|
||||
taffy::{self, prelude::length},
|
||||
task::Tasks,
|
||||
widget::{
|
||||
ConstructEssentials,
|
||||
label::{WidgetLabel, WidgetLabelParams},
|
||||
},
|
||||
};
|
||||
use wlx_common::dash_interface::BoxDashInterface;
|
||||
|
||||
use crate::{
|
||||
frontend::{FrontendTask, FrontendTasks},
|
||||
util::popup_manager::{MountPopupParams, PopupHandle},
|
||||
views::window_options,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Task {
|
||||
WindowClicked(packet_server::WvrWindow),
|
||||
WindowOptionsFinish,
|
||||
Refresh,
|
||||
}
|
||||
|
||||
pub struct Params<'a> {
|
||||
pub globals: WguiGlobals,
|
||||
pub frontend_tasks: FrontendTasks,
|
||||
pub layout: &'a mut Layout,
|
||||
pub parent_id: WidgetID,
|
||||
pub on_click: Option<Box<dyn Fn(WvrWindowHandle)>>,
|
||||
}
|
||||
|
||||
struct State {
|
||||
view_window_options: Option<(PopupHandle, window_options::View)>,
|
||||
}
|
||||
|
||||
pub struct View {
|
||||
#[allow(dead_code)]
|
||||
pub parser_state: ParserState,
|
||||
tasks: Tasks<Task>,
|
||||
frontend_tasks: FrontendTasks,
|
||||
globals: WguiGlobals,
|
||||
state: Rc<RefCell<State>>,
|
||||
id_list_parent: WidgetID,
|
||||
on_click: Option<Box<dyn Fn(WvrWindowHandle)>>,
|
||||
}
|
||||
|
||||
impl View {
|
||||
pub fn new(params: Params) -> anyhow::Result<Self> {
|
||||
let doc_params = &ParseDocumentParams {
|
||||
globals: params.globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/view/window_list.xml"),
|
||||
extra: Default::default(),
|
||||
};
|
||||
|
||||
let parser_state = wgui::parser::parse_from_assets(doc_params, params.layout, params.parent_id)?;
|
||||
let list_parent = parser_state.fetch_widget(¶ms.layout.state, "list_parent")?;
|
||||
|
||||
let tasks = Tasks::new();
|
||||
|
||||
tasks.push(Task::Refresh);
|
||||
|
||||
let state = Rc::new(RefCell::new(State {
|
||||
view_window_options: None,
|
||||
}));
|
||||
|
||||
Ok(Self {
|
||||
parser_state,
|
||||
tasks,
|
||||
frontend_tasks: params.frontend_tasks,
|
||||
globals: params.globals.clone(),
|
||||
state,
|
||||
id_list_parent: list_parent.id,
|
||||
on_click: params.on_click,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update<T>(
|
||||
&mut self,
|
||||
layout: &mut Layout,
|
||||
interface: &mut BoxDashInterface<T>,
|
||||
data: &mut T,
|
||||
) -> anyhow::Result<()> {
|
||||
loop {
|
||||
let tasks = self.tasks.drain();
|
||||
if tasks.is_empty() {
|
||||
break;
|
||||
}
|
||||
for task in tasks {
|
||||
match task {
|
||||
Task::WindowClicked(display) => self.action_window_clicked(display)?,
|
||||
Task::WindowOptionsFinish => self.action_window_options_finish(),
|
||||
Task::Refresh => self.refresh(layout, interface, data)?,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut state = self.state.borrow_mut();
|
||||
if let Some((_, view)) = &mut state.view_window_options {
|
||||
view.update(layout, interface, data)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn construct_window_button<T>(
|
||||
ess: &mut ConstructEssentials,
|
||||
interface: &mut BoxDashInterface<T>,
|
||||
data: &mut T,
|
||||
globals: &WguiGlobals,
|
||||
window: &packet_server::WvrWindow,
|
||||
) -> anyhow::Result<(WidgetPair, Rc<ComponentButton>)> {
|
||||
let aspect = window.size_x as f32 / window.size_y as f32;
|
||||
let height = 96.0;
|
||||
let width = height * aspect;
|
||||
let accent_color = globals.defaults().accent_color;
|
||||
|
||||
let (widget_button, button) = components::button::construct(
|
||||
ess,
|
||||
components::button::Params {
|
||||
color: Some(accent_color.with_alpha(0.2)),
|
||||
border_color: Some(accent_color),
|
||||
style: taffy::Style {
|
||||
align_items: Some(taffy::AlignItems::Center),
|
||||
justify_content: Some(taffy::JustifyContent::Center),
|
||||
size: taffy::Size {
|
||||
width: length(width),
|
||||
height: length(height),
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
let process_name = match interface.process_get(data, window.process_handle.clone()) {
|
||||
Some(process) => process.name.clone(),
|
||||
None => String::from("Unknown"),
|
||||
};
|
||||
|
||||
let label_name = WidgetLabel::create(
|
||||
&mut globals.get(),
|
||||
WidgetLabelParams {
|
||||
content: Translation::from_raw_text(&process_name),
|
||||
style: TextStyle {
|
||||
weight: Some(FontWeight::Bold),
|
||||
wrap: true,
|
||||
align: Some(HorizontalAlign::Center),
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
let label_resolution = WidgetLabel::create(
|
||||
&mut globals.get(),
|
||||
WidgetLabelParams {
|
||||
content: Translation::from_raw_text(""),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
ess.layout.add_child(widget_button.id, label_name, Default::default())?;
|
||||
ess
|
||||
.layout
|
||||
.add_child(widget_button.id, label_resolution, Default::default())?;
|
||||
|
||||
Ok((widget_button, button))
|
||||
}
|
||||
|
||||
fn fill_window_list<T>(
|
||||
globals: &WguiGlobals,
|
||||
ess: &mut ConstructEssentials,
|
||||
interface: &mut BoxDashInterface<T>,
|
||||
data: &mut T,
|
||||
list: Vec<packet_server::WvrWindow>,
|
||||
tasks: &Tasks<Task>,
|
||||
) -> anyhow::Result<()> {
|
||||
for entry in list {
|
||||
let (_, button) = construct_window_button(ess, interface, data, globals, &entry)?;
|
||||
|
||||
button.on_click({
|
||||
let tasks = tasks.clone();
|
||||
Rc::new(move |_, _| {
|
||||
tasks.push(Task::WindowClicked(entry.clone()));
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl View {
|
||||
fn action_window_options_finish(&mut self) {
|
||||
self.state.borrow_mut().view_window_options = None;
|
||||
self.tasks.push(Task::Refresh);
|
||||
}
|
||||
|
||||
fn refresh<T>(
|
||||
&mut self,
|
||||
layout: &mut Layout,
|
||||
interface: &mut BoxDashInterface<T>,
|
||||
data: &mut T,
|
||||
) -> anyhow::Result<()> {
|
||||
layout.remove_children(self.id_list_parent);
|
||||
|
||||
let mut text: Option<Translation> = None;
|
||||
match interface.window_list(data) {
|
||||
Ok(list) => {
|
||||
if list.is_empty() {
|
||||
text = Some(Translation::from_translation_key("NO_WINDOWS_FOUND"))
|
||||
} else {
|
||||
fill_window_list(
|
||||
&self.globals,
|
||||
&mut ConstructEssentials {
|
||||
layout,
|
||||
parent: self.id_list_parent,
|
||||
},
|
||||
interface,
|
||||
data,
|
||||
list,
|
||||
&self.tasks,
|
||||
)?
|
||||
}
|
||||
}
|
||||
Err(e) => text = Some(Translation::from_raw_text(&format!("Error: {:?}", e))),
|
||||
}
|
||||
|
||||
if let Some(text) = text.take() {
|
||||
layout.add_child(
|
||||
self.id_list_parent,
|
||||
WidgetLabel::create(
|
||||
&mut self.globals.get(),
|
||||
WidgetLabelParams {
|
||||
content: text,
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
Default::default(),
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn action_window_clicked(&mut self, window: packet_server::WvrWindow) -> anyhow::Result<()> {
|
||||
if let Some(on_click) = &mut self.on_click {
|
||||
(*on_click)(window.handle);
|
||||
} else {
|
||||
self.frontend_tasks.push(FrontendTask::MountPopup(MountPopupParams {
|
||||
title: Translation::from_translation_key("WINDOW_OPTIONS"),
|
||||
on_content: {
|
||||
let _frontend_tasks = self.frontend_tasks.clone();
|
||||
let _globals = self.globals.clone();
|
||||
let _state = self.state.clone();
|
||||
let _tasks = self.tasks.clone();
|
||||
|
||||
//TODO
|
||||
|
||||
Rc::new(move |_data| {
|
||||
// state.borrow_mut().view_window_options = Some((
|
||||
// data.handle,
|
||||
// window_options::View::new(window_options::Params {
|
||||
// globals: globals.clone(),
|
||||
// layout: data.layout,
|
||||
// parent_id: data.id_content,
|
||||
// on_submit: tasks.make_callback(Task::WindowOptionsFinish),
|
||||
// window: window.clone(),
|
||||
// frontend_tasks: frontend_tasks.clone(),
|
||||
// })?,
|
||||
// ));
|
||||
Ok(())
|
||||
})
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
use anyhow::Context;
|
||||
use std::rc::Rc;
|
||||
use wayvr_ipc::packet_server;
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
components::button::ComponentButton,
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::{Layout, WidgetID},
|
||||
parser::{Fetchable, ParseDocumentParams, ParserState},
|
||||
task::Tasks,
|
||||
widget::ConstructEssentials,
|
||||
};
|
||||
use wlx_common::dash_interface::BoxDashInterface;
|
||||
|
||||
use crate::{
|
||||
frontend::{FrontendTask, FrontendTasks},
|
||||
views::window_list::construct_window_button,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Task {
|
||||
SetVisible(bool),
|
||||
Kill,
|
||||
Close,
|
||||
}
|
||||
|
||||
pub struct View {
|
||||
#[allow(dead_code)]
|
||||
pub state: ParserState,
|
||||
tasks: Tasks<Task>,
|
||||
frontend_tasks: FrontendTasks,
|
||||
window: packet_server::WvrWindow,
|
||||
on_submit: Rc<dyn Fn()>,
|
||||
}
|
||||
|
||||
pub struct Params<'a, T> {
|
||||
pub globals: WguiGlobals,
|
||||
pub frontend_tasks: FrontendTasks,
|
||||
pub layout: &'a mut Layout,
|
||||
pub parent_id: WidgetID,
|
||||
pub on_submit: Rc<dyn Fn()>,
|
||||
pub window: packet_server::WvrWindow,
|
||||
pub interface: &'a mut BoxDashInterface<T>,
|
||||
pub data: &'a mut T,
|
||||
}
|
||||
|
||||
impl View {
|
||||
pub fn new<T>(params: Params<T>) -> anyhow::Result<Self> {
|
||||
let doc_params = &ParseDocumentParams {
|
||||
globals: params.globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/view/window_options.xml"),
|
||||
extra: Default::default(),
|
||||
};
|
||||
|
||||
let state = wgui::parser::parse_from_assets(doc_params, params.layout, params.parent_id)?;
|
||||
|
||||
let tasks = Tasks::new();
|
||||
|
||||
let window_parent = state.get_widget_id("window_parent")?;
|
||||
let btn_close = state.fetch_component_as::<ComponentButton>("btn_close")?;
|
||||
let btn_kill = state.fetch_component_as::<ComponentButton>("btn_kill")?;
|
||||
let btn_show_hide = state.fetch_component_as::<ComponentButton>("btn_show_hide")?;
|
||||
|
||||
construct_window_button(
|
||||
&mut ConstructEssentials {
|
||||
layout: params.layout,
|
||||
parent: window_parent,
|
||||
},
|
||||
params.interface,
|
||||
params.data,
|
||||
¶ms.globals,
|
||||
¶ms.window,
|
||||
)?;
|
||||
|
||||
{
|
||||
let mut c = params.layout.start_common();
|
||||
btn_show_hide.set_text(
|
||||
&mut c.common(),
|
||||
Translation::from_translation_key(if params.window.visible { "HIDE" } else { "SHOW" }),
|
||||
);
|
||||
c.finish()?;
|
||||
}
|
||||
|
||||
tasks.handle_button(&btn_close, Task::Close);
|
||||
tasks.handle_button(&btn_kill, Task::Kill);
|
||||
tasks.handle_button(&btn_show_hide, Task::SetVisible(!params.window.visible));
|
||||
|
||||
Ok(Self {
|
||||
state,
|
||||
tasks,
|
||||
window: params.window,
|
||||
frontend_tasks: params.frontend_tasks,
|
||||
on_submit: params.on_submit,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update<T>(
|
||||
&mut self,
|
||||
_layout: &mut Layout,
|
||||
interface: &mut BoxDashInterface<T>,
|
||||
data: &mut T,
|
||||
) -> anyhow::Result<()> {
|
||||
for task in self.tasks.drain() {
|
||||
match task {
|
||||
Task::SetVisible(v) => self.action_set_visible(interface, data, v),
|
||||
Task::Close => self.action_close(interface, data),
|
||||
Task::Kill => self.action_kill(interface, data),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl View {
|
||||
fn action_set_visible<T>(&mut self, interface: &mut BoxDashInterface<T>, data: &mut T, visible: bool) {
|
||||
if let Err(e) = interface.window_set_visible(data, self.window.handle.clone(), visible) {
|
||||
self
|
||||
.frontend_tasks
|
||||
.push(FrontendTask::PushToast(Translation::from_raw_text_string(format!(
|
||||
"Failed to set window visibility: {:?}",
|
||||
e
|
||||
))));
|
||||
};
|
||||
|
||||
(*self.on_submit)();
|
||||
}
|
||||
|
||||
fn action_close<T>(&mut self, interface: &mut BoxDashInterface<T>, data: &mut T) {
|
||||
if let Err(e) = interface.window_request_close(data, self.window.handle.clone()) {
|
||||
self
|
||||
.frontend_tasks
|
||||
.push(FrontendTask::PushToast(Translation::from_raw_text_string(format!(
|
||||
"Failed to close window: {:?}",
|
||||
e
|
||||
))));
|
||||
};
|
||||
|
||||
(*self.on_submit)();
|
||||
}
|
||||
|
||||
fn action_kill_process<T>(&mut self, interface: &mut BoxDashInterface<T>, data: &mut T) -> anyhow::Result<()> {
|
||||
let process = interface
|
||||
.process_get(data, self.window.process_handle.clone())
|
||||
.context("Process not found")?;
|
||||
interface.process_terminate(data, process.handle)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn action_kill<T>(&mut self, interface: &mut BoxDashInterface<T>, data: &mut T) {
|
||||
if let Err(e) = self.action_kill_process(interface, data) {
|
||||
self
|
||||
.frontend_tasks
|
||||
.push(FrontendTask::PushToast(Translation::from_raw_text_string(format!(
|
||||
"Failed to kill process: {:?}",
|
||||
e
|
||||
))));
|
||||
};
|
||||
|
||||
(*self.on_submit)();
|
||||
}
|
||||
}
|
||||
@@ -131,6 +131,7 @@ async function run() {
|
||||
let llm_translated_json = {};
|
||||
const translated_json_path = lang_path + "/" + template_name + ".json";
|
||||
if (await fsp.exists(translated_json_path)) {
|
||||
console.log("Loading file", translated_json_path);
|
||||
llm_translated_json = JSON.parse((await fsp.readFile(translated_json_path)).toString());
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,13 @@
|
||||
"RELOAD_FROM_DISK": "XML-Datei von der Festplatte neu laden",
|
||||
"CLOSE_MIRROR": "Spiegel schließen",
|
||||
"CLOSE_APP": "App schließen",
|
||||
"FORCE_CLOSE_APP": "App zwangsweise schließen"
|
||||
"FORCE_CLOSE_APP": "App zwangsweise schließen",
|
||||
"HANDSFREE": {
|
||||
"TITLE": "Freihändig-Modus",
|
||||
"NONE": "Aus",
|
||||
"HMD": "HMD + Kneifen",
|
||||
"EYE_TRACKING": "Auge + Kneifen"
|
||||
}
|
||||
},
|
||||
"WATCH": {
|
||||
"RECENTER": "Spielbereich neu zentrieren",
|
||||
@@ -59,7 +65,8 @@
|
||||
"FULL_FRAME": "Voll 3D",
|
||||
"FULL_FRAME_SBS": "Full-SBS",
|
||||
"FULL_FRAME_TAB": "Full-TAB",
|
||||
"FULL_FRAME_BAT": "Full-BAT"
|
||||
"FULL_FRAME_BAT": "Full-BAT",
|
||||
"ADJUST_MOUSE": "Maus anpassen"
|
||||
},
|
||||
"STEREO_3D_MODE_": {},
|
||||
"ALIGN_TO_HMD": "An HMD ausrichten",
|
||||
@@ -74,7 +81,8 @@
|
||||
"ROTATE90": "90° gedreht",
|
||||
"ROTATE180": "180° gedreht",
|
||||
"ROTATE270": "270° gedreht"
|
||||
}
|
||||
},
|
||||
"GLOBAL": "Immer sichtbar"
|
||||
},
|
||||
"DISABLED": "Deaktiviert",
|
||||
"DEFAULT": "Standard",
|
||||
|
||||
@@ -12,7 +12,13 @@
|
||||
"RELOAD_FROM_DISK": "Volver a cargar XML desde el disco",
|
||||
"CLOSE_MIRROR": "Cerrar espejo",
|
||||
"CLOSE_APP": "Cerrar aplicación",
|
||||
"FORCE_CLOSE_APP": "Forzar cierre de la aplicación"
|
||||
"FORCE_CLOSE_APP": "Forzar cierre de la aplicación",
|
||||
"HANDSFREE": {
|
||||
"TITLE": "Modo manos libres",
|
||||
"NONE": "Desactivado",
|
||||
"HMD": "HMD + pellizco",
|
||||
"EYE_TRACKING": "Ojo + pellizco"
|
||||
}
|
||||
},
|
||||
"WATCH": {
|
||||
"RECENTER": "Recentrar el área de juego",
|
||||
@@ -59,7 +65,8 @@
|
||||
"FULL_FRAME": "3D completo",
|
||||
"FULL_FRAME_SBS": "Full-SBS",
|
||||
"FULL_FRAME_TAB": "Full-TAB",
|
||||
"FULL_FRAME_BAT": "Full-BAT"
|
||||
"FULL_FRAME_BAT": "Full-BAT",
|
||||
"ADJUST_MOUSE": "Ajustar ratón"
|
||||
},
|
||||
"STEREO_3D_MODE_": {},
|
||||
"ALIGN_TO_HMD": "Alinear al HMD",
|
||||
@@ -74,7 +81,8 @@
|
||||
"ROTATE90": "Rotado 90°",
|
||||
"ROTATE180": "Rotado 180°",
|
||||
"ROTATE270": "Rotado 270°"
|
||||
}
|
||||
},
|
||||
"GLOBAL": "Siempre visible"
|
||||
},
|
||||
"DISABLED": "Deshabilitado",
|
||||
"DEFAULT": "Por defecto",
|
||||
|
||||
@@ -12,7 +12,13 @@
|
||||
"RELOAD_FROM_DISK": "Ricarica XML dal disco",
|
||||
"CLOSE_MIRROR": "Chiudi mirror",
|
||||
"CLOSE_APP": "Chiudi app",
|
||||
"FORCE_CLOSE_APP": "Chiudi forzatamente l'app"
|
||||
"FORCE_CLOSE_APP": "Chiudi forzatamente l'app",
|
||||
"HANDSFREE": {
|
||||
"TITLE": "Modalità a mani libere",
|
||||
"NONE": "Disattivato",
|
||||
"HMD": "HMD + pizzico",
|
||||
"EYE_TRACKING": "Occhio + pizzico"
|
||||
}
|
||||
},
|
||||
"DEFAULT": "Predefinito",
|
||||
"DISABLED": "Disabilitato",
|
||||
@@ -49,7 +55,8 @@
|
||||
"FULL_FRAME": "3D Completo",
|
||||
"FULL_FRAME_SBS": "Full-SBS",
|
||||
"FULL_FRAME_TAB": "Full-TAB",
|
||||
"FULL_FRAME_BAT": "Full-BAT"
|
||||
"FULL_FRAME_BAT": "Full-BAT",
|
||||
"ADJUST_MOUSE": "Regola il mouse"
|
||||
},
|
||||
"MOUSE": {
|
||||
"TITLE": "Correzioni del mouse",
|
||||
@@ -62,7 +69,8 @@
|
||||
"FLIP90": "Ruotato di 90°",
|
||||
"FLIP180": "Ruotato di 180°",
|
||||
"FLIP270": "Ruotato di 270°"
|
||||
}
|
||||
},
|
||||
"GLOBAL": "Sempre visibile"
|
||||
},
|
||||
"GRAB": {
|
||||
"ADJUST_DISTANCE": "Regola la distanza",
|
||||
|
||||
@@ -12,7 +12,13 @@
|
||||
"RELOAD_FROM_DISK": "ディスクからXMLを再読み込み",
|
||||
"CLOSE_MIRROR": "ミラーを閉じる",
|
||||
"CLOSE_APP": "アプリを閉じる",
|
||||
"FORCE_CLOSE_APP": "アプリを強制終了"
|
||||
"FORCE_CLOSE_APP": "アプリを強制終了",
|
||||
"HANDSFREE": {
|
||||
"TITLE": "ハンズフリーモード",
|
||||
"NONE": "オフ",
|
||||
"HMD": "HMD + ピンチ",
|
||||
"EYE_TRACKING": "視線 + ピンチ"
|
||||
}
|
||||
},
|
||||
"WATCH": {
|
||||
"RECENTER": "プレイスペースをリセンター",
|
||||
@@ -58,7 +64,8 @@
|
||||
"FULL_FRAME": "フル3D",
|
||||
"FULL_FRAME_SBS": "フルSBS",
|
||||
"FULL_FRAME_TAB": "フルTAB",
|
||||
"FULL_FRAME_BAT": "フルBAT"
|
||||
"FULL_FRAME_BAT": "フルBAT",
|
||||
"ADJUST_MOUSE": "マウス調整"
|
||||
},
|
||||
"ALIGN_TO_HMD": "常にHMDの方を向く",
|
||||
"MOUSE": {
|
||||
@@ -72,7 +79,8 @@
|
||||
"ROTATE90": "回転 90°",
|
||||
"ROTATE180": "回転 180°",
|
||||
"ROTATE270": "回転 270°"
|
||||
}
|
||||
},
|
||||
"GLOBAL": "常に表示"
|
||||
},
|
||||
"DISABLED": "無効",
|
||||
"DEFAULT": "デフォルト",
|
||||
@@ -100,4 +108,4 @@
|
||||
"CANNOT_ADD_SET": "セットを追加できません!",
|
||||
"MAXIMUM_SETS_REACHED": "最大セット数に達しました。"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,13 @@
|
||||
"RELOAD_FROM_DISK": "Przeładuj XML z dysku",
|
||||
"CLOSE_MIRROR": "Zamknij lustro",
|
||||
"CLOSE_APP": "Zamknij aplikację",
|
||||
"FORCE_CLOSE_APP": "Wymuś zamknięcie aplikacji"
|
||||
"FORCE_CLOSE_APP": "Wymuś zamknięcie aplikacji",
|
||||
"HANDSFREE": {
|
||||
"TITLE": "Tryb wolnych rąk",
|
||||
"NONE": "Wyłączone",
|
||||
"HMD": "HMD + uszczypnięcie",
|
||||
"EYE_TRACKING": "Oko + uszczypnięcie"
|
||||
}
|
||||
},
|
||||
"WATCH": {
|
||||
"RECENTER": "Wyśrodkuj przestrzeń gry",
|
||||
@@ -58,7 +64,8 @@
|
||||
"FULL_FRAME": "Pełny 3D",
|
||||
"FULL_FRAME_SBS": "Full-SBS",
|
||||
"FULL_FRAME_TAB": "Full-TAB",
|
||||
"FULL_FRAME_BAT": "Full-BAT"
|
||||
"FULL_FRAME_BAT": "Full-BAT",
|
||||
"ADJUST_MOUSE": "Dostosuj mysz"
|
||||
},
|
||||
"ALIGN_TO_HMD": "Dopasuj do HMD",
|
||||
"MOUSE": {
|
||||
@@ -72,7 +79,8 @@
|
||||
"FLIP90": "Odwrócony o 90°",
|
||||
"FLIP180": "Odwrócony o 180°",
|
||||
"FLIP270": "Odwrócony o 270°"
|
||||
}
|
||||
},
|
||||
"GLOBAL": "Zawsze widoczne"
|
||||
},
|
||||
"DISABLED": "Wyłączone",
|
||||
"DEFAULT": "Domyślny",
|
||||
|
||||
@@ -12,7 +12,13 @@
|
||||
"RELOAD_FROM_DISK": "从磁盘重新加载 XML",
|
||||
"CLOSE_MIRROR": "关闭镜像",
|
||||
"CLOSE_APP": "关闭应用",
|
||||
"FORCE_CLOSE_APP": "强制关闭应用"
|
||||
"FORCE_CLOSE_APP": "强制关闭应用",
|
||||
"HANDSFREE": {
|
||||
"TITLE": "免提模式",
|
||||
"NONE": "关闭",
|
||||
"HMD": "HMD + 捏合",
|
||||
"EYE_TRACKING": "眼动 + 捏合"
|
||||
}
|
||||
},
|
||||
"DEFAULT": "默认",
|
||||
"DISABLED": "已禁用",
|
||||
@@ -49,7 +55,8 @@
|
||||
"FULL_FRAME": "完整 3D",
|
||||
"FULL_FRAME_SBS": "完整左右 (Full-SBS)",
|
||||
"FULL_FRAME_TAB": "完整上下 (Full-TAB)",
|
||||
"FULL_FRAME_BAT": "完整下上 (Full-BAT)"
|
||||
"FULL_FRAME_BAT": "完整下上 (Full-BAT)",
|
||||
"ADJUST_MOUSE": "调整鼠标"
|
||||
},
|
||||
"MOUSE": {
|
||||
"TITLE": "鼠标修复",
|
||||
@@ -62,7 +69,8 @@
|
||||
"FLIP90": "镜像旋转 90°",
|
||||
"FLIP180": "镜像旋转 180°",
|
||||
"FLIP270": "镜像旋转 270°"
|
||||
}
|
||||
},
|
||||
"GLOBAL": "始终可见"
|
||||
},
|
||||
"GRAB": {
|
||||
"ADJUST_DISTANCE": "调整距离",
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
use std::{
|
||||
sync::{Arc, LazyLock},
|
||||
time::Duration,
|
||||
};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
|
||||
use glam::{Affine3A, Quat, Vec3, vec3};
|
||||
use wgui::globals::expand_env_vars;
|
||||
|
||||
@@ -67,7 +67,7 @@ impl InteractLockHandler {
|
||||
app: &mut AppState,
|
||||
anim_mult: f32,
|
||||
) -> Box<ModifyOverlayTask> {
|
||||
let defaults = app.wgui_globals.get().defaults.clone();
|
||||
let defaults = app.wgui_globals.defaults().clone();
|
||||
let rect_color = self.color;
|
||||
|
||||
self.interactable = !self.interactable;
|
||||
|
||||
@@ -53,9 +53,11 @@ pub(super) fn create_keyboard_panel(
|
||||
let doc_params = new_doc_params(&mut panel);
|
||||
|
||||
let globals = app.wgui_globals.clone();
|
||||
let accent_color = globals.get().defaults.accent_color;
|
||||
|
||||
let anim_mult = globals.defaults().animation_mult;
|
||||
let (accent_color, anim_mult) = {
|
||||
let def = globals.defaults();
|
||||
(def.accent_color, def.animation_mult)
|
||||
};
|
||||
|
||||
let root = panel
|
||||
.parser_state
|
||||
|
||||
@@ -135,8 +135,8 @@ impl ComponentTrait for ComponentButton {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_color2(color: &drawing::Color) -> drawing::Color {
|
||||
color.lerp(&Color::new(0.0, 0.0, 0.0, color.a), 0.2)
|
||||
fn get_color2(color: &drawing::Color, gradient_intensity: f32) -> drawing::Color {
|
||||
color.lerp(&Color::new(0.0, 0.0, 0.0, color.a), gradient_intensity)
|
||||
}
|
||||
|
||||
impl ComponentButton {
|
||||
@@ -157,6 +157,8 @@ impl ComponentButton {
|
||||
}
|
||||
|
||||
pub fn set_color(&self, common: &mut CallbackDataCommon, color: Color) {
|
||||
let gradient_intensity = common.defaults().gradient_intensity;
|
||||
|
||||
let Some(mut rect) = common.state.widgets.get_as::<WidgetRectangle>(self.data.id_rect) else {
|
||||
return;
|
||||
};
|
||||
@@ -165,7 +167,7 @@ impl ComponentButton {
|
||||
state.colors.color = color;
|
||||
|
||||
rect.params.color = color;
|
||||
rect.params.color2 = get_color2(&color);
|
||||
rect.params.color2 = get_color2(&color, gradient_intensity);
|
||||
}
|
||||
|
||||
pub fn get_time_since_last_pressed(&self) -> Duration {
|
||||
@@ -191,7 +193,11 @@ impl ComponentButton {
|
||||
return;
|
||||
}
|
||||
|
||||
let anim_mult = common.state.globals.defaults().animation_mult;
|
||||
let (anim_mult, gradient_intensity) = {
|
||||
let defaults = common.state.globals.defaults();
|
||||
(defaults.animation_mult, defaults.gradient_intensity)
|
||||
};
|
||||
|
||||
let anim_ticks = if sticky_down { 5. } else { 10. };
|
||||
|
||||
let state = self.state.clone();
|
||||
@@ -211,7 +217,7 @@ impl ComponentButton {
|
||||
let colors = &state.colors;
|
||||
let bgcolor = colors.color.lerp(&colors.hover_color, mult * 0.5);
|
||||
rect.params.color = bgcolor;
|
||||
rect.params.color2 = get_color2(&bgcolor);
|
||||
rect.params.color2 = get_color2(&bgcolor, gradient_intensity);
|
||||
rect.params.border_color = colors.border_color.lerp(&colors.hover_border_color, mult);
|
||||
common.alterables.mark_redraw();
|
||||
}),
|
||||
@@ -222,6 +228,7 @@ impl ComponentButton {
|
||||
}
|
||||
|
||||
fn anim_hover(
|
||||
common: &mut CallbackDataCommon,
|
||||
rect: &mut WidgetRectangle,
|
||||
widget_data: &mut WidgetData,
|
||||
colors: &Colors,
|
||||
@@ -240,13 +247,15 @@ fn anim_hover(
|
||||
|
||||
let bgcolor = init_color.lerp(&colors.hover_color, mult);
|
||||
|
||||
let gradient_intensity = common.globals().defaults.gradient_intensity;
|
||||
|
||||
//let t = Mat4::from_scale(Vec3::splat(1.0 + pos * 0.5)) * Mat4::from_rotation_z(pos * 1.0);
|
||||
|
||||
let t = Mat4::from_scale(Vec3::splat(1.0 + pos * 0.05));
|
||||
widget_data.transform = centered_matrix(widget_boundary.size, &t);
|
||||
|
||||
rect.params.color = bgcolor;
|
||||
rect.params.color2 = get_color2(&bgcolor);
|
||||
rect.params.color2 = get_color2(&bgcolor, gradient_intensity);
|
||||
|
||||
rect.params.border_color = init_border_color.lerp(&colors.hover_border_color, mult);
|
||||
}
|
||||
@@ -260,6 +269,7 @@ fn anim_hover_create(state: Rc<RefCell<State>>, widget_id: WidgetID, fade_in: bo
|
||||
let rect = anim_data.obj.get_as_mut::<WidgetRectangle>().unwrap();
|
||||
let state = state.borrow();
|
||||
anim_hover(
|
||||
common,
|
||||
rect,
|
||||
anim_data.data,
|
||||
&state.colors,
|
||||
@@ -326,6 +336,7 @@ fn register_event_mouse_press(state: Rc<RefCell<State>>, listeners: &mut EventLi
|
||||
|
||||
let rect = event_data.obj.get_as_mut::<WidgetRectangle>().unwrap();
|
||||
anim_hover(
|
||||
common,
|
||||
rect,
|
||||
event_data.widget_data,
|
||||
&state.colors,
|
||||
@@ -373,6 +384,7 @@ fn register_event_mouse_release(
|
||||
state.down = false;
|
||||
if state.hovered {
|
||||
anim_hover(
|
||||
common,
|
||||
rect,
|
||||
event_data.widget_data,
|
||||
&state.colors,
|
||||
@@ -418,7 +430,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
||||
let color = if let Some(color) = params.color {
|
||||
color
|
||||
} else {
|
||||
globals.get().defaults.button_color
|
||||
globals.defaults().button_color
|
||||
};
|
||||
|
||||
let border_color = if let Some(border_color) = params.border_color {
|
||||
@@ -439,11 +451,13 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
||||
Color::new(color.r + 0.5, color.g + 0.5, color.g + 0.5, color.a + 0.5)
|
||||
};
|
||||
|
||||
let gradient_intensity = ess.layout.state.globals.defaults().gradient_intensity;
|
||||
|
||||
let (root, _) = ess.layout.add_child(
|
||||
ess.parent,
|
||||
WidgetRectangle::create(WidgetRectangleParams {
|
||||
color,
|
||||
color2: get_color2(&color),
|
||||
color2: get_color2(&color, gradient_intensity),
|
||||
gradient: drawing::GradientMode::Vertical,
|
||||
round: params.round,
|
||||
border_color,
|
||||
@@ -455,7 +469,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
||||
let id_rect = root.id;
|
||||
|
||||
let light_text = {
|
||||
let mult = if globals.get().defaults.dark_mode {
|
||||
let mult = if globals.defaults().dark_mode {
|
||||
color.a
|
||||
} else {
|
||||
1.0 - color.a
|
||||
|
||||
@@ -9,14 +9,10 @@ use crate::{
|
||||
layout::WidgetPair,
|
||||
widget::{ConstructEssentials, div::WidgetDiv},
|
||||
};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
rc::{Rc, Weak},
|
||||
sync::Arc,
|
||||
};
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use taffy::{
|
||||
AlignItems,
|
||||
prelude::{auto, length, percent},
|
||||
prelude::{length, percent},
|
||||
};
|
||||
|
||||
pub struct Entry<'a> {
|
||||
@@ -49,11 +45,8 @@ struct State {
|
||||
on_select: Option<TabSelectCallback>,
|
||||
}
|
||||
|
||||
struct Data {}
|
||||
|
||||
pub struct ComponentTabs {
|
||||
base: ComponentBase,
|
||||
data: Rc<Data>,
|
||||
state: Rc<RefCell<State>>,
|
||||
}
|
||||
|
||||
@@ -145,7 +138,6 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
||||
});
|
||||
}
|
||||
|
||||
let data = Rc::new(Data {});
|
||||
let state = Rc::new(RefCell::new(State {
|
||||
selected_entry_name: Rc::from(params.selected_entry_name),
|
||||
mounted_entries,
|
||||
@@ -169,7 +161,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
||||
lhandles: Default::default(),
|
||||
};
|
||||
|
||||
let tabs = Rc::new(ComponentTabs { base, data, state });
|
||||
let tabs = Rc::new(ComponentTabs { base, state });
|
||||
|
||||
ess.layout.defer_component_refresh(Component(tabs.clone()));
|
||||
Ok((root, tabs))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
cell::RefMut,
|
||||
cell::{Ref, RefMut},
|
||||
collections::HashSet,
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@ use slotmap::{DenseSlotMap, new_key_type};
|
||||
use crate::{
|
||||
animation::{self, Animation},
|
||||
components::Component,
|
||||
globals,
|
||||
i18n::I18n,
|
||||
layout::{LayoutState, LayoutTask, WidgetID},
|
||||
sound::WguiSoundType,
|
||||
@@ -162,11 +163,19 @@ impl CallbackDataCommon<'_> {
|
||||
self.state.globals.i18n()
|
||||
}
|
||||
|
||||
// helper function
|
||||
// helper functions
|
||||
pub fn mark_widget_dirty(&mut self, id: WidgetID) {
|
||||
self.alterables.mark_dirty(id);
|
||||
self.alterables.mark_redraw();
|
||||
}
|
||||
|
||||
pub fn globals(&self) -> RefMut<'_, globals::Globals> {
|
||||
self.state.globals.get()
|
||||
}
|
||||
|
||||
pub fn defaults(&self) -> Ref<'_, globals::Defaults> {
|
||||
self.state.globals.defaults()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CallbackData<'a> {
|
||||
|
||||
@@ -29,6 +29,7 @@ pub struct Defaults {
|
||||
pub translucent_alpha: f32,
|
||||
pub animation_mult: f32,
|
||||
pub rounding_mult: f32,
|
||||
pub gradient_intensity: f32, // currently used for buttons
|
||||
}
|
||||
|
||||
impl Default for Defaults {
|
||||
@@ -44,6 +45,7 @@ impl Default for Defaults {
|
||||
translucent_alpha: 0.5,
|
||||
animation_mult: 1.0,
|
||||
rounding_mult: 1.0,
|
||||
gradient_intensity: 0.3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
assets::AssetPath,
|
||||
components::{Component, button, tooltip},
|
||||
components::{Component, button},
|
||||
drawing::Color,
|
||||
i18n::Translation,
|
||||
layout::WidgetID,
|
||||
@@ -57,7 +57,7 @@ pub fn parse_component_button<'a>(
|
||||
key,
|
||||
value,
|
||||
&mut round,
|
||||
ctx.doc_params.globals.get().defaults.rounding_mult,
|
||||
ctx.doc_params.globals.defaults().rounding_mult,
|
||||
);
|
||||
}
|
||||
"color" => {
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::{
|
||||
assets::AssetPath,
|
||||
components::{Component, tabs},
|
||||
i18n::Translation,
|
||||
layout::WidgetID,
|
||||
parser::{AttribPair, ParserContext, ParserFile, get_asset_path_from_kv, process_component, style::parse_style},
|
||||
parser::{AttribPair, ParserContext, get_asset_path_from_kv, process_component, style::parse_style},
|
||||
};
|
||||
|
||||
pub fn parse_component_tabs<'a>(
|
||||
file: &'a ParserFile,
|
||||
ctx: &mut ParserContext,
|
||||
node: roxmltree::Node<'a, 'a>,
|
||||
parent_id: WidgetID,
|
||||
|
||||
@@ -1054,9 +1054,7 @@ fn parse_child<'a>(
|
||||
)?);
|
||||
}
|
||||
"Tabs" => {
|
||||
new_widget_id = Some(parse_component_tabs(
|
||||
file, ctx, child_node, parent_id, &attribs, tag_name,
|
||||
)?);
|
||||
new_widget_id = Some(parse_component_tabs(ctx, child_node, parent_id, &attribs, tag_name)?);
|
||||
}
|
||||
"" => { /* ignore */ }
|
||||
other_tag_name => {
|
||||
|
||||
@@ -43,7 +43,7 @@ pub fn parse_widget_image<'a>(
|
||||
key,
|
||||
value,
|
||||
&mut params.round,
|
||||
ctx.doc_params.globals.get().defaults.rounding_mult,
|
||||
ctx.doc_params.globals.defaults().rounding_mult,
|
||||
);
|
||||
}
|
||||
"border" => {
|
||||
|
||||
@@ -47,7 +47,7 @@ pub fn parse_widget_rectangle<'a>(
|
||||
key,
|
||||
value,
|
||||
&mut params.round,
|
||||
ctx.doc_params.globals.get().defaults.rounding_mult,
|
||||
ctx.doc_params.globals.defaults().rounding_mult,
|
||||
);
|
||||
}
|
||||
"border" => {
|
||||
|
||||
Reference in New Issue
Block a user