Add game logo files and enhance home view layout with grid and button components
This commit is contained in:
parent
9154f8ed3e
commit
d62820dd80
10
agentm/assets/game_logos/doapp.txt
Normal file
10
agentm/assets/game_logos/doapp.txt
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
██████╗ ███████╗ █████╗ ██████╗ ██████╗ ██████╗ █████╗ ██╗ ██╗██╗ ██╗███████╗
|
||||
██╔══██╗██╔════╝██╔══██╗██╔══██╗ ██╔═══██╗██╔══██╗ ██╔══██╗██║ ██║██║ ██║██╔════╝
|
||||
██║ ██║█████╗ ███████║██║ ██║ ██║ ██║██████╔╝ ███████║██║ ██║██║ ██║█████╗
|
||||
██║ ██║██╔══╝ ██╔══██║██║ ██║ ██║ ██║██╔══██╗ ██╔══██║██║ ██║╚██╗ ██╔╝██╔══╝
|
||||
██████╔╝███████╗██║ ██║██████╔╝ ╚██████╔╝██║ ██║ ██║ ██║███████╗██║ ╚████╔╝ ███████╗
|
||||
╚═════╝ ╚══════╝╚═╝ ╚═╝╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚══════╝
|
||||
|
||||
|
||||
10
agentm/assets/game_logos/kof98umh.txt
Normal file
10
agentm/assets/game_logos/kof98umh.txt
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
████████╗██╗ ██╗███████╗ ██╗ ██╗██╗███╗ ██╗ ██████╗ ██████╗ ███████╗ ███████╗██╗ ██████╗ ██╗ ██╗████████╗███████╗██████╗ ███████╗
|
||||
╚══██╔══╝██║ ██║██╔════╝ ██║ ██╔╝██║████╗ ██║██╔════╝ ██╔═══██╗██╔════╝ ██╔════╝██║██╔════╝ ██║ ██║╚══██╔══╝██╔════╝██╔══██╗██╔════╝
|
||||
██║ ███████║█████╗ █████╔╝ ██║██╔██╗ ██║██║ ███╗ ██║ ██║█████╗ █████╗ ██║██║ ███╗███████║ ██║ █████╗ ██████╔╝███████╗
|
||||
██║ ██╔══██║██╔══╝ ██╔═██╗ ██║██║╚██╗██║██║ ██║ ██║ ██║██╔══╝ ██╔══╝ ██║██║ ██║██╔══██║ ██║ ██╔══╝ ██╔══██╗╚════██║
|
||||
██║ ██║ ██║███████╗ ██║ ██╗██║██║ ╚████║╚██████╔╝ ╚██████╔╝██║ ██║ ██║╚██████╔╝██║ ██║ ██║ ███████╗██║ ██║███████║
|
||||
╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝
|
||||
|
||||
|
||||
10
agentm/assets/game_logos/mvsc.txt
Normal file
10
agentm/assets/game_logos/mvsc.txt
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
███╗ ███╗ █████╗ ██████╗ ██╗ ██╗███████╗██╗ ██╗ ██╗███████╗ ██████╗ █████╗ ██████╗ ██████╗ ██████╗ ███╗ ███╗
|
||||
████╗ ████║██╔══██╗██╔══██╗██║ ██║██╔════╝██║ ██║ ██║██╔════╝ ██╔════╝██╔══██╗██╔══██╗██╔════╝██╔═══██╗████╗ ████║
|
||||
██╔████╔██║███████║██████╔╝██║ ██║█████╗ ██║ ██║ ██║███████╗ ██║ ███████║██████╔╝██║ ██║ ██║██╔████╔██║
|
||||
██║╚██╔╝██║██╔══██║██╔══██╗╚██╗ ██╔╝██╔══╝ ██║ ╚██╗ ██╔╝╚════██║ ██║ ██╔══██║██╔═══╝ ██║ ██║ ██║██║╚██╔╝██║
|
||||
██║ ╚═╝ ██║██║ ██║██║ ██║ ╚████╔╝ ███████╗███████╗ ╚████╔╝ ███████║██╗ ╚██████╗██║ ██║██║ ╚██████╗╚██████╔╝██║ ╚═╝ ██║
|
||||
╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═══╝ ╚══════╝╚══════╝ ╚═══╝ ╚══════╝╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝
|
||||
|
||||
|
||||
10
agentm/assets/game_logos/samsh5sp.txt
Normal file
10
agentm/assets/game_logos/samsh5sp.txt
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
███████╗ █████╗ ███╗ ███╗██╗ ██╗██████╗ █████╗ ██╗ ███████╗██╗ ██╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗███╗ ██╗ ██╗ ██╗
|
||||
██╔════╝██╔══██╗████╗ ████║██║ ██║██╔══██╗██╔══██╗██║ ██╔════╝██║ ██║██╔═══██╗██╔══██╗██╔═══██╗██║ ██║████╗ ██║ ██║ ██║
|
||||
███████╗███████║██╔████╔██║██║ ██║██████╔╝███████║██║ ███████╗███████║██║ ██║██║ ██║██║ ██║██║ █╗ ██║██╔██╗ ██║ ██║ ██║
|
||||
╚════██║██╔══██║██║╚██╔╝██║██║ ██║██╔══██╗██╔══██║██║ ╚════██║██╔══██║██║ ██║██║ ██║██║ ██║██║███╗██║██║╚██╗██║ ╚██╗ ██╔╝
|
||||
███████║██║ ██║██║ ╚═╝ ██║╚██████╔╝██║ ██║██║ ██║██║ ███████║██║ ██║╚██████╔╝██████╔╝╚██████╔╝╚███╔███╔╝██║ ╚████║ ╚████╔╝
|
||||
╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══╝╚══╝ ╚═╝ ╚═══╝ ╚═══╝
|
||||
|
||||
|
||||
10
agentm/assets/game_logos/sfiii3n.txt
Normal file
10
agentm/assets/game_logos/sfiii3n.txt
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
███████╗████████╗██████╗ ███████╗███████╗████████╗ ███████╗██╗ ██████╗ ██╗ ██╗████████╗███████╗██████╗ ██╗██╗██╗
|
||||
██╔════╝╚══██╔══╝██╔══██╗██╔════╝██╔════╝╚══██╔══╝ ██╔════╝██║██╔════╝ ██║ ██║╚══██╔══╝██╔════╝██╔══██╗ ██║██║██║
|
||||
███████╗ ██║ ██████╔╝█████╗ █████╗ ██║ █████╗ ██║██║ ███╗███████║ ██║ █████╗ ██████╔╝ ██║██║██║
|
||||
╚════██║ ██║ ██╔══██╗██╔══╝ ██╔══╝ ██║ ██╔══╝ ██║██║ ██║██╔══██║ ██║ ██╔══╝ ██╔══██╗ ██║██║██║
|
||||
███████║ ██║ ██║ ██║███████╗███████╗ ██║ ██║ ██║╚██████╔╝██║ ██║ ██║ ███████╗██║ ██║ ██║██║██║
|
||||
╚══════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝╚═╝╚═╝
|
||||
|
||||
|
||||
10
agentm/assets/game_logos/soulclbr.txt
Normal file
10
agentm/assets/game_logos/soulclbr.txt
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
███████╗ ██████╗ ██╗ ██╗██╗ ██████╗ █████╗ ██╗ ██╗██████╗ ██╗ ██╗██████╗
|
||||
██╔════╝██╔═══██╗██║ ██║██║ ██╔════╝██╔══██╗██║ ██║██╔══██╗██║ ██║██╔══██╗
|
||||
███████╗██║ ██║██║ ██║██║ ██║ ███████║██║ ██║██████╔╝██║ ██║██████╔╝
|
||||
╚════██║██║ ██║██║ ██║██║ ██║ ██╔══██║██║ ██║██╔══██╗██║ ██║██╔══██╗
|
||||
███████║╚██████╔╝╚██████╔╝███████╗ ╚██████╗██║ ██║███████╗██║██████╔╝╚██████╔╝██║ ██║
|
||||
╚══════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝╚═════╝ ╚═════╝ ╚═╝ ╚═╝
|
||||
|
||||
|
||||
10
agentm/assets/game_logos/tektagt.txt
Normal file
10
agentm/assets/game_logos/tektagt.txt
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
████████╗███████╗██╗ ██╗██╗ ██╗███████╗███╗ ██╗ ████████╗ █████╗ ██████╗ ████████╗ ██████╗ ██╗ ██╗██████╗ ███╗ ██╗ █████╗ ███╗ ███╗███████╗███╗ ██╗████████╗
|
||||
╚══██╔══╝██╔════╝██║ ██╔╝██║ ██╔╝██╔════╝████╗ ██║ ╚══██╔══╝██╔══██╗██╔════╝ ╚══██╔══╝██╔═══██╗██║ ██║██╔══██╗████╗ ██║██╔══██╗████╗ ████║██╔════╝████╗ ██║╚══██╔══╝
|
||||
██║ █████╗ █████╔╝ █████╔╝ █████╗ ██╔██╗ ██║ ██║ ███████║██║ ███╗ ██║ ██║ ██║██║ ██║██████╔╝██╔██╗ ██║███████║██╔████╔██║█████╗ ██╔██╗ ██║ ██║
|
||||
██║ ██╔══╝ ██╔═██╗ ██╔═██╗ ██╔══╝ ██║╚██╗██║ ██║ ██╔══██║██║ ██║ ██║ ██║ ██║██║ ██║██╔══██╗██║╚██╗██║██╔══██║██║╚██╔╝██║██╔══╝ ██║╚██╗██║ ██║
|
||||
██║ ███████╗██║ ██╗██║ ██╗███████╗██║ ╚████║ ██║ ██║ ██║╚██████╔╝ ██║ ╚██████╔╝╚██████╔╝██║ ██║██║ ╚████║██║ ██║██║ ╚═╝ ██║███████╗██║ ╚████║ ██║
|
||||
╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝
|
||||
|
||||
|
||||
10
agentm/assets/game_logos/umk3.txt
Normal file
10
agentm/assets/game_logos/umk3.txt
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
███╗ ███╗ ██████╗ ██████╗ ████████╗ █████╗ ██╗ ██╗ ██╗ ██████╗ ███╗ ███╗██████╗ █████╗ ████████╗ ██████╗
|
||||
████╗ ████║██╔═══██╗██╔══██╗╚══██╔══╝██╔══██╗██║ ██║ ██╔╝██╔═══██╗████╗ ████║██╔══██╗██╔══██╗╚══██╔══╝ ╚════██╗
|
||||
██╔████╔██║██║ ██║██████╔╝ ██║ ███████║██║ █████╔╝ ██║ ██║██╔████╔██║██████╔╝███████║ ██║ █████╔╝
|
||||
██║╚██╔╝██║██║ ██║██╔══██╗ ██║ ██╔══██║██║ ██╔═██╗ ██║ ██║██║╚██╔╝██║██╔══██╗██╔══██║ ██║ ╚═══██╗
|
||||
██║ ╚═╝ ██║╚██████╔╝██║ ██║ ██║ ██║ ██║███████╗ ██║ ██╗╚██████╔╝██║ ╚═╝ ██║██████╔╝██║ ██║ ██║ ██████╔╝
|
||||
╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝
|
||||
|
||||
|
||||
10
agentm/assets/game_logos/xmvsf.txt
Normal file
10
agentm/assets/game_logos/xmvsf.txt
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
██╗ ██╗ ███╗ ███╗███████╗███╗ ██╗ ██╗ ██╗███████╗ ███████╗████████╗██████╗ ███████╗███████╗████████╗ ███████╗██╗ ██████╗ ██╗ ██╗████████╗███████╗██████╗
|
||||
╚██╗██╔╝ ████╗ ████║██╔════╝████╗ ██║ ██║ ██║██╔════╝ ██╔════╝╚══██╔══╝██╔══██╗██╔════╝██╔════╝╚══██╔══╝ ██╔════╝██║██╔════╝ ██║ ██║╚══██╔══╝██╔════╝██╔══██╗
|
||||
╚███╔╝█████╗██╔████╔██║█████╗ ██╔██╗ ██║ ██║ ██║███████╗ ███████╗ ██║ ██████╔╝█████╗ █████╗ ██║ █████╗ ██║██║ ███╗███████║ ██║ █████╗ ██████╔╝
|
||||
██╔██╗╚════╝██║╚██╔╝██║██╔══╝ ██║╚██╗██║ ╚██╗ ██╔╝╚════██║ ╚════██║ ██║ ██╔══██╗██╔══╝ ██╔══╝ ██║ ██╔══╝ ██║██║ ██║██╔══██║ ██║ ██╔══╝ ██╔══██╗
|
||||
██╔╝ ██╗ ██║ ╚═╝ ██║███████╗██║ ╚████║ ╚████╔╝ ███████║ ███████║ ██║ ██║ ██║███████╗███████╗ ██║ ██║ ██║╚██████╔╝██║ ██║ ██║ ███████╗██║ ██║
|
||||
╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═══╝ ╚══════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝
|
||||
|
||||
|
||||
@ -1,7 +1,13 @@
|
||||
# agentm/main.py
|
||||
|
||||
import subprocess
|
||||
from agentm.app import AgentMApp
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run the generate_theme_css module silently
|
||||
subprocess.run(
|
||||
["python", "-m", "agentm.theme.generate_theme_css", "--silent"],
|
||||
check=True
|
||||
)
|
||||
|
||||
# Launch the app
|
||||
app = AgentMApp()
|
||||
app.run()
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
from agentm.theme.palette import get_theme
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
from agentm.theme.palette import get_theme
|
||||
|
||||
# Check for --silent in command-line arguments
|
||||
silent = "--silent" in sys.argv
|
||||
|
||||
# Load dark theme instance
|
||||
theme = get_theme("dark")
|
||||
@ -16,14 +20,16 @@ template = template_path.read_text()
|
||||
# Find all placeholders like {{FOREGROUND}}, {{BACKGROUND}}, etc.
|
||||
tokens = set(re.findall(r"{{\s*([A-Z0-9_]+)\s*}}", template))
|
||||
|
||||
# Replace them with actual values from theme
|
||||
# Replace tokens
|
||||
for token in tokens:
|
||||
value = getattr(theme, token, None)
|
||||
if value is not None:
|
||||
template = template.replace(f"{{{{{token}}}}}", value)
|
||||
else:
|
||||
elif not silent:
|
||||
print(f"⚠️ Warning: Theme token '{token}' not found in ThemeManager")
|
||||
|
||||
# Write final output
|
||||
output_path.write_text(template)
|
||||
|
||||
if not silent:
|
||||
print(f"✅ Synced themed CSS written to: {output_path}")
|
||||
|
||||
@ -14,7 +14,7 @@ Screen {
|
||||
|
||||
/* === Headers === */
|
||||
|
||||
# Header, .header {
|
||||
# .header {
|
||||
# dock: top;
|
||||
# height: 3;
|
||||
# content-align: center middle;
|
||||
@ -31,10 +31,13 @@ Button {
|
||||
background: {{SURFACE_10}};
|
||||
color: {{ACCENT}};
|
||||
border: solid {{ACCENT}};
|
||||
padding: 1 2;
|
||||
margin: 1;
|
||||
padding: 1;
|
||||
margin: 0;
|
||||
content-align: center middle;
|
||||
text-style: bold;
|
||||
width: 100%;
|
||||
min-height: 3;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
Button:hover {
|
||||
@ -47,6 +50,42 @@ Button:focus {
|
||||
border: solid {{ACCENT}};
|
||||
}
|
||||
|
||||
Button:disabled {
|
||||
background: {{DISABLED_BG}};
|
||||
color: {{DISABLED}};
|
||||
border: solid {{DISABLED_BORDER}};
|
||||
text-style: dim;
|
||||
}
|
||||
|
||||
/* === Grid Layout === */
|
||||
|
||||
.rom_grid {
|
||||
grid-size: 5;
|
||||
grid-gutter: 1;
|
||||
padding: 0 1; /* Was: 1 2 */
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
align-horizontal: center;
|
||||
align-vertical: middle;
|
||||
height: auto; /* Ensure it can grow */
|
||||
}
|
||||
|
||||
#rom_grid_scroll {
|
||||
max-height: 30vh; /* was: height: 40vh */
|
||||
overflow-y: auto;
|
||||
scrollbar-gutter: stable;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-bottom: solid {{BORDER}};
|
||||
}
|
||||
|
||||
/* Optionally ensure the parent container scrolls properly */
|
||||
#game_content_layout {
|
||||
height: auto;
|
||||
width: 100%;
|
||||
padding: 1 2;
|
||||
}
|
||||
|
||||
/* === Inputs === */
|
||||
|
||||
Input {
|
||||
@ -115,7 +154,7 @@ Input:focus {
|
||||
content-align: center middle;
|
||||
}
|
||||
|
||||
/* === Game Layout === */
|
||||
/* === Layout === */
|
||||
|
||||
.centered_layout {
|
||||
layout: vertical;
|
||||
@ -125,30 +164,6 @@ Input:focus {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.rom_rows_container {
|
||||
layout: vertical;
|
||||
align-horizontal: center;
|
||||
}
|
||||
|
||||
.game_card {
|
||||
width: auto;
|
||||
height: auto;
|
||||
max-width: 60;
|
||||
margin: 1;
|
||||
padding: 1;
|
||||
background: {{SURFACE_10}};
|
||||
color: {{ACCENT}};
|
||||
border: solid {{BORDER}};
|
||||
content-align: center middle;
|
||||
text-style: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.game_card:hover {
|
||||
background: {{SURFACE_20}};
|
||||
color: {{ACCENT_HOVER}};
|
||||
}
|
||||
|
||||
Static {
|
||||
text-align: center;
|
||||
}
|
||||
@ -157,47 +172,16 @@ Horizontal {
|
||||
content-align: center middle;
|
||||
}
|
||||
|
||||
.game_card:focus {
|
||||
background: {{SURFACE_20}};
|
||||
border: solid {{ACCENT}};
|
||||
}
|
||||
|
||||
.game_card:disabled {
|
||||
background: {{SURFACE_10}};
|
||||
color: {{BORDER}};
|
||||
}
|
||||
|
||||
.game_card_clicked {
|
||||
background: {{ACCENT}};
|
||||
color: {{BACKGROUND}};
|
||||
}
|
||||
|
||||
.offset_card {
|
||||
width: 11;
|
||||
height: auto;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.rom_row {
|
||||
layout: horizontal;
|
||||
align-horizontal: center;
|
||||
align-vertical: middle;
|
||||
padding: 1 2;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.info_confirm_row {
|
||||
layout: horizontal;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
padding: 1 2;
|
||||
align-vertical: top;
|
||||
padding: 0 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#confirm_button {
|
||||
width: 20%;
|
||||
height: auto;
|
||||
content-align: center middle;
|
||||
width: 100%; /* Take full width of its container */
|
||||
min-width: 20; /* Increase minimum width if needed */
|
||||
max-width: 100%; /* Optional: avoid oversizing */
|
||||
}
|
||||
|
||||
.confirm_button:hover {
|
||||
@ -205,21 +189,30 @@ Horizontal {
|
||||
color: {{BACKGROUND}};
|
||||
}
|
||||
|
||||
Button:disabled {
|
||||
background: {{DISABLED_BG}};
|
||||
color: {{DISABLED}};
|
||||
border: solid {{DISABLED_BORDER}};
|
||||
text-style: dim;
|
||||
}
|
||||
|
||||
.game_info {
|
||||
padding: 1 2;
|
||||
padding: 0 1;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
margin-right: 1;
|
||||
color: {{ACCENT}};
|
||||
}
|
||||
|
||||
#game_info_box {
|
||||
width: 80%;
|
||||
height: auto;
|
||||
max-height: 50vh; /* Adjusted for better visibility */
|
||||
padding: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
Button.game_button {
|
||||
min-height: 3;
|
||||
}
|
||||
|
||||
#confirm_button_container {
|
||||
width: 20%;
|
||||
min-width: 20;
|
||||
align-vertical: middle;
|
||||
align-horizontal: center;
|
||||
height: 100%;
|
||||
padding-left: 1;
|
||||
}
|
||||
@ -14,7 +14,7 @@ Screen {
|
||||
|
||||
/* === Headers === */
|
||||
|
||||
# Header, .header {
|
||||
# .header {
|
||||
# dock: top;
|
||||
# height: 3;
|
||||
# content-align: center middle;
|
||||
@ -31,10 +31,13 @@ Button {
|
||||
background: #282828;
|
||||
color: #ed7d3a;
|
||||
border: solid #ed7d3a;
|
||||
padding: 1 2;
|
||||
margin: 1;
|
||||
padding: 1;
|
||||
margin: 0;
|
||||
content-align: center middle;
|
||||
text-style: bold;
|
||||
width: 100%;
|
||||
min-height: 3;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
Button:hover {
|
||||
@ -47,6 +50,42 @@ Button:focus {
|
||||
border: solid #ed7d3a;
|
||||
}
|
||||
|
||||
Button:disabled {
|
||||
background: #444444;
|
||||
color: #999999;
|
||||
border: solid #666666;
|
||||
text-style: dim;
|
||||
}
|
||||
|
||||
/* === Grid Layout === */
|
||||
|
||||
.rom_grid {
|
||||
grid-size: 5;
|
||||
grid-gutter: 1;
|
||||
padding: 0 1; /* Was: 1 2 */
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
align-horizontal: center;
|
||||
align-vertical: middle;
|
||||
height: auto; /* Ensure it can grow */
|
||||
}
|
||||
|
||||
#rom_grid_scroll {
|
||||
max-height: 30vh; /* was: height: 40vh */
|
||||
overflow-y: auto;
|
||||
scrollbar-gutter: stable;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-bottom: solid #3a9bed;
|
||||
}
|
||||
|
||||
/* Optionally ensure the parent container scrolls properly */
|
||||
#game_content_layout {
|
||||
height: auto;
|
||||
width: 100%;
|
||||
padding: 1 2;
|
||||
}
|
||||
|
||||
/* === Inputs === */
|
||||
|
||||
Input {
|
||||
@ -115,7 +154,7 @@ Input:focus {
|
||||
content-align: center middle;
|
||||
}
|
||||
|
||||
/* === Game Layout === */
|
||||
/* === Layout === */
|
||||
|
||||
.centered_layout {
|
||||
layout: vertical;
|
||||
@ -125,30 +164,6 @@ Input:focus {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.rom_rows_container {
|
||||
layout: vertical;
|
||||
align-horizontal: center;
|
||||
}
|
||||
|
||||
.game_card {
|
||||
width: auto;
|
||||
height: auto;
|
||||
max-width: 60;
|
||||
margin: 1;
|
||||
padding: 1;
|
||||
background: #282828;
|
||||
color: #ed7d3a;
|
||||
border: solid #3a9bed;
|
||||
content-align: center middle;
|
||||
text-style: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.game_card:hover {
|
||||
background: #3f3f3f;
|
||||
color: rgb(236, 194, 169);
|
||||
}
|
||||
|
||||
Static {
|
||||
text-align: center;
|
||||
}
|
||||
@ -157,47 +172,16 @@ Horizontal {
|
||||
content-align: center middle;
|
||||
}
|
||||
|
||||
.game_card:focus {
|
||||
background: #3f3f3f;
|
||||
border: solid #ed7d3a;
|
||||
}
|
||||
|
||||
.game_card:disabled {
|
||||
background: #282828;
|
||||
color: #3a9bed;
|
||||
}
|
||||
|
||||
.game_card_clicked {
|
||||
background: #ed7d3a;
|
||||
color: #0e0e0e;
|
||||
}
|
||||
|
||||
.offset_card {
|
||||
width: 11;
|
||||
height: auto;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.rom_row {
|
||||
layout: horizontal;
|
||||
align-horizontal: center;
|
||||
align-vertical: middle;
|
||||
padding: 1 2;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.info_confirm_row {
|
||||
layout: horizontal;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
padding: 1 2;
|
||||
align-vertical: top;
|
||||
padding: 0 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#confirm_button {
|
||||
width: 20%;
|
||||
height: auto;
|
||||
content-align: center middle;
|
||||
width: 100%; /* Take full width of its container */
|
||||
min-width: 20; /* Increase minimum width if needed */
|
||||
max-width: 100%; /* Optional: avoid oversizing */
|
||||
}
|
||||
|
||||
.confirm_button:hover {
|
||||
@ -205,21 +189,30 @@ Horizontal {
|
||||
color: #0e0e0e;
|
||||
}
|
||||
|
||||
Button:disabled {
|
||||
background: #444444;
|
||||
color: #999999;
|
||||
border: solid #666666;
|
||||
text-style: dim;
|
||||
}
|
||||
|
||||
.game_info {
|
||||
padding: 1 2;
|
||||
padding: 0 1;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
margin-right: 1;
|
||||
color: #ed7d3a;
|
||||
}
|
||||
|
||||
#game_info_box {
|
||||
width: 80%;
|
||||
height: auto;
|
||||
max-height: 50vh; /* Adjusted for better visibility */
|
||||
padding: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
Button.game_button {
|
||||
min-height: 3;
|
||||
}
|
||||
|
||||
#confirm_button_container {
|
||||
width: 20%;
|
||||
min-width: 20;
|
||||
align-vertical: middle;
|
||||
align-horizontal: center;
|
||||
height: 100%;
|
||||
padding-left: 1;
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
from textual.screen import Screen
|
||||
from textual.widgets import Static, Button
|
||||
from textual.containers import Vertical, Horizontal, HorizontalScroll
|
||||
from textual.containers import Vertical, Horizontal, VerticalScroll, Grid
|
||||
from textual.message import Message
|
||||
from textual.reactive import reactive
|
||||
from textual.widget import Widget
|
||||
@ -8,18 +8,12 @@ from rich.panel import Panel
|
||||
from rich.console import Group
|
||||
from rich.table import Table
|
||||
from rich.rule import Rule
|
||||
from rich.markup import escape
|
||||
from PIL import Image, ImageFilter
|
||||
import os
|
||||
|
||||
from rich_pixels import Pixels
|
||||
from rich_pixels._renderer import HalfcellRenderer
|
||||
from rich.text import Text
|
||||
|
||||
from agentm.utils.logger import log_with_caller
|
||||
from agentm.logic.roms import get_verified_roms, GAME_FILES
|
||||
from agentm.theme.palette import get_theme
|
||||
from agentm.components.footer import AgentMFooter
|
||||
from agentm.components.game_image_preview import GameImagePreview
|
||||
|
||||
palette = get_theme()
|
||||
|
||||
@ -37,30 +31,19 @@ class ProgressWidget(Widget):
|
||||
return f"[bold {palette.ACCENT}]{self.message}[/]"
|
||||
|
||||
|
||||
|
||||
class GameAccordion(Static):
|
||||
def __init__(self, title: str, rom_file: str, metadata: dict, parent_view):
|
||||
super().__init__(
|
||||
id=f"accordion_{rom_file.replace('.', '_').replace('-', '_')}",
|
||||
classes="game_card"
|
||||
)
|
||||
|
||||
self.title = title
|
||||
self.rom_file = rom_file
|
||||
class GameCardButton(Button):
|
||||
def __init__(self, metadata: dict, parent_view):
|
||||
self.metadata = metadata
|
||||
self.parent_view = parent_view
|
||||
safe_id = metadata["rom_file"].replace(".", "_").replace("-", "_")
|
||||
label = Text(metadata["title"], style=f"bold {palette.ACCENT}")
|
||||
|
||||
self.title_label = Static(
|
||||
f"[b {palette.ACCENT}]{escape(self.title.upper())}[/]\n",
|
||||
classes="game_title",
|
||||
markup=True
|
||||
super().__init__(
|
||||
label=label,
|
||||
id=f"game_btn_{safe_id}",
|
||||
classes="game_button"
|
||||
)
|
||||
|
||||
self.image_path = os.path.abspath(self.metadata.get("image_path", ""))
|
||||
|
||||
def compose(self):
|
||||
yield self.title_label
|
||||
yield GameImagePreview(image_path=self.image_path)
|
||||
self.styles.min_height = 3 # Ensures buttons stay visible even in constrained space
|
||||
|
||||
async def on_click(self):
|
||||
await self.display_info()
|
||||
@ -68,19 +51,19 @@ class GameAccordion(Static):
|
||||
|
||||
async def display_info(self):
|
||||
meta = self.metadata
|
||||
log_with_caller("debug", f"Showing shared info for {self.rom_file}")
|
||||
|
||||
table = Table.grid(expand=True)
|
||||
table.add_column(ratio=1)
|
||||
table.add_column()
|
||||
table.add_row("[b]Title:[/b]", meta['title'])
|
||||
table.add_row("[b]Game ID:[/b]", meta['game_id'])
|
||||
table.add_row("[b]Difficulty:[/b]", f"{meta.get('difficulty_min')} - {meta.get('difficulty_max')}")
|
||||
table.add_row("[b]Characters:[/b]", ", ".join(meta.get("characters", [])))
|
||||
table.add_row("[b]Keywords:[/b]", ", ".join(meta.get("keywords", [])))
|
||||
table.add_row("[b]SHA256:[/b]", meta["sha256"])
|
||||
table = Table.grid(padding=(0, 1))
|
||||
table.add_column("Key", style="bold underline", no_wrap=True)
|
||||
table.add_column("Value", style=palette.ACCENT, overflow="fold")
|
||||
|
||||
self.parent_view.shared_info_box.update(
|
||||
table.add_row("Title", meta["title"])
|
||||
table.add_row("Game ID", meta["game_id"])
|
||||
table.add_row("Difficulty", f"{meta.get('difficulty_min')} - {meta.get('difficulty_max')}")
|
||||
table.add_row("Characters", ", ".join(meta.get("characters", [])))
|
||||
table.add_row("Keywords", ", ".join(meta.get("keywords", [])))
|
||||
table.add_row("SHA256", meta["sha256"])
|
||||
|
||||
self.parent_view.shared_info_content.update(
|
||||
Panel(Group(table, Rule(style="dim")), title="Game Info", border_style=palette.BORDER, expand=True)
|
||||
)
|
||||
self.parent_view.shared_confirm_button.label = f"✅ Confirm {meta['title']}"
|
||||
@ -88,13 +71,12 @@ class GameAccordion(Static):
|
||||
self.parent_view.selected_game = meta
|
||||
|
||||
|
||||
|
||||
class HomeView(Screen):
|
||||
BINDINGS = [("escape", "app.quit", "Quit")]
|
||||
|
||||
def highlight_selected(self, selected_widget: GameAccordion):
|
||||
for card in self.rom_scroll_row.children:
|
||||
if isinstance(card, GameAccordion):
|
||||
def highlight_selected(self, selected_widget: GameCardButton):
|
||||
for card in self.rom_grid.children:
|
||||
if isinstance(card, GameCardButton):
|
||||
card.remove_class("game_card_clicked")
|
||||
selected_widget.add_class("game_card_clicked")
|
||||
|
||||
@ -125,7 +107,6 @@ class HomeView(Screen):
|
||||
id="loading_container"
|
||||
)
|
||||
|
||||
# This will be the main container we later modify
|
||||
self.dynamic_container = Vertical(self.loading_container, id="dynamic_content")
|
||||
|
||||
yield Vertical(
|
||||
@ -148,7 +129,7 @@ class HomeView(Screen):
|
||||
|
||||
for idx, rom in enumerate(verified_roms, start=1):
|
||||
self.app.call_from_thread(
|
||||
lambda title=rom['title'], idx=idx: setattr(
|
||||
lambda title=rom["title"], idx=idx: setattr(
|
||||
self.progress_text, "message",
|
||||
f"Processing {title} ({idx}/{total})"
|
||||
)
|
||||
@ -161,49 +142,56 @@ class HomeView(Screen):
|
||||
async def display_verified_roms(self, verified_roms):
|
||||
log_with_caller("info", f"ROM verification complete. Total: {len(verified_roms)}")
|
||||
|
||||
self.shared_info_box = Static(
|
||||
self.shared_info_content = Static(
|
||||
Panel(
|
||||
"[dim]Select a Game From Above to Start[/dim]",
|
||||
"[dim]Select a Game From the Grid Below to Start[/dim]",
|
||||
title="Game Info",
|
||||
border_style=palette.BORDER,
|
||||
expand=True
|
||||
),
|
||||
id="game_info_box",
|
||||
classes="game_info",
|
||||
expand=True
|
||||
id="info_panel_static"
|
||||
)
|
||||
|
||||
self.shared_info_box = VerticalScroll(
|
||||
self.shared_info_content,
|
||||
id="game_info_box",
|
||||
classes="game_info"
|
||||
)
|
||||
self.shared_info_box.styles.height = 7 # Around 5 visible rows
|
||||
|
||||
self.shared_confirm_button = Button(
|
||||
"✅ Confirm",
|
||||
id="confirm_button",
|
||||
classes="confirm_button",
|
||||
disabled=True
|
||||
)
|
||||
self.rom_scroll_row = HorizontalScroll(id="rom_scroll_row", classes="rom_row")
|
||||
|
||||
self.rom_grid = Grid(id="rom_grid", classes="rom_grid")
|
||||
self.rom_grid.styles.grid_columns = ["1fr"] * 5
|
||||
self.rom_grid.styles.grid_gap = (0, 1)
|
||||
self.rom_grid.styles.width = "100%"
|
||||
|
||||
rom_grid_scroll = VerticalScroll(self.rom_grid, id="rom_grid_scroll")
|
||||
rom_grid_scroll.styles.max_height = "30vh"
|
||||
|
||||
new_content = Vertical(
|
||||
self.rom_scroll_row,
|
||||
rom_grid_scroll,
|
||||
Horizontal(
|
||||
self.shared_info_box,
|
||||
self.shared_confirm_button,
|
||||
Vertical(self.shared_confirm_button, id="confirm_button_container"),
|
||||
id="info_row",
|
||||
classes="info_confirm_row"
|
||||
)
|
||||
),
|
||||
id="game_content_layout",
|
||||
classes="game_content_layout"
|
||||
)
|
||||
|
||||
# Replace loading content with new UI below logo and welcome
|
||||
dynamic_container = self.query_one("#dynamic_content")
|
||||
await dynamic_container.remove_children()
|
||||
await dynamic_container.mount(new_content)
|
||||
|
||||
# Populate games
|
||||
for rom in verified_roms:
|
||||
await self.rom_scroll_row.mount(GameAccordion(
|
||||
title=rom["title"],
|
||||
rom_file=rom["rom_file"],
|
||||
metadata=rom,
|
||||
parent_view=self
|
||||
))
|
||||
|
||||
await self.rom_grid.mount(GameCardButton(metadata=rom, parent_view=self))
|
||||
|
||||
async def on_button_pressed(self, event: Button.Pressed) -> None:
|
||||
if event.button.id == "confirm_button" and self.selected_game:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user