Files
UmaCardApplication/gui/main_window.py
2025-12-28 17:44:46 +00:00

245 lines
8.0 KiB
Python

"""
Main Window for Umamusume Support Card Manager
Tabbed interface for card browsing, effects, deck builder, and hints
"""
import tkinter as tk
from tkinter import ttk
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from db.db_queries import get_database_stats, get_owned_count
from gui.card_view import CardListFrame
from gui.effects_view import EffectsFrame
from gui.hints_skills_view import SkillSearchFrame
from gui.training_sim import TrainingSimFrame
from gui.deck_builder import DeckBuilderFrame
from gui.update_dialog import show_update_dialog
from gui.theme import (
configure_styles, create_styled_button,
BG_DARK, BG_MEDIUM, BG_LIGHT, BG_HIGHLIGHT,
ACCENT_PRIMARY, ACCENT_SECONDARY, ACCENT_TERTIARY,
TEXT_PRIMARY, TEXT_SECONDARY, TEXT_MUTED,
FONT_TITLE, FONT_HEADER, FONT_BODY, FONT_SMALL
)
from utils import resolve_image_path
from version import VERSION
class MainWindow:
"""Main application window with tabbed interface"""
def __init__(self):
self.root = tk.Tk()
self.root.title("Umamusume Support Card Manager")
self.root.geometry("1400x850")
self.root.minsize(1350, 800)
# Set icon
try:
icon_path = resolve_image_path("1_Special Week.png")
if icon_path and os.path.exists(icon_path):
icon_img = tk.PhotoImage(file=icon_path)
self.root.iconphoto(True, icon_img)
except Exception as e:
print(f"Failed to set icon: {e}")
# Configure all styles using centralized theme
configure_styles(self.root)
# Create main container
main_container = ttk.Frame(self.root)
main_container.pack(fill=tk.BOTH, expand=True)
# Header with stats
self.create_header(main_container)
# Status bar - Create BEFORE notebook to anchor it to bottom
self.create_status_bar(main_container)
# Tabbed notebook
self.notebook = ttk.Notebook(main_container)
self.notebook.pack(fill=tk.BOTH, expand=True, padx=15, pady=8)
# Create tabs
self.create_tabs()
def create_header(self, parent):
"""Create header with database statistics and update button"""
# Header container with subtle bottom border effect
header_outer = tk.Frame(parent, bg=BG_DARK)
header_outer.pack(fill=tk.X)
header_frame = tk.Frame(header_outer, bg=BG_DARK)
header_frame.pack(fill=tk.X, padx=20, pady=15)
# Left side: Title and version
title_frame = tk.Frame(header_frame, bg=BG_DARK)
title_frame.pack(side=tk.LEFT)
# App icon and title
title_label = tk.Label(
title_frame,
text="🏇 Umamusume Support Card Manager",
font=FONT_TITLE,
bg=BG_DARK,
fg=ACCENT_PRIMARY
)
title_label.pack(side=tk.LEFT)
# Version badge
version_frame = tk.Frame(title_frame, bg=ACCENT_SECONDARY, padx=8, pady=2)
version_frame.pack(side=tk.LEFT, padx=12)
version_label = tk.Label(
version_frame,
text=f"v{VERSION}",
font=FONT_SMALL,
bg=ACCENT_SECONDARY,
fg=TEXT_PRIMARY
)
version_label.pack()
# Right side: Update button and stats
right_frame = tk.Frame(header_frame, bg=BG_DARK)
right_frame.pack(side=tk.RIGHT)
# Update button with modern styling
self.update_button = create_styled_button(
right_frame,
text="🔄 Check for Updates",
command=self.show_update_dialog,
style_type='default'
)
self.update_button.pack(side=tk.RIGHT, padx=(15, 0))
# Stats panel with card-like appearance
stats_frame = tk.Frame(right_frame, bg=BG_MEDIUM, padx=15, pady=8)
stats_frame.pack(side=tk.RIGHT)
stats = get_database_stats()
owned = get_owned_count()
# Build stats text with better formatting
stats_parts = [
f"📊 {stats.get('total_cards', 0)} Cards",
f"{owned} Owned",
f"🏆 {stats.get('by_rarity', {}).get('SSR', 0)} SSR",
f"{stats.get('by_rarity', {}).get('SR', 0)} SR",
f"{stats.get('by_rarity', {}).get('R', 0)} R"
]
stats_text = "".join(stats_parts)
self.stats_label = tk.Label(
stats_frame,
text=stats_text,
font=FONT_SMALL,
bg=BG_MEDIUM,
fg=TEXT_SECONDARY
)
self.stats_label.pack()
# Subtle separator line
separator = tk.Frame(header_outer, bg=BG_LIGHT, height=1)
separator.pack(fill=tk.X, padx=15)
def create_tabs(self):
"""Create all tab frames"""
# Card List Tab
self.card_frame = CardListFrame(self.notebook, on_card_selected_callback=self.on_card_selected)
self.notebook.add(self.card_frame, text=" 📋 Card List ")
# Effects Tab
self.effects_frame = EffectsFrame(self.notebook)
self.notebook.add(self.effects_frame, text=" 📊 Effects ")
# Deck Builder Tab
self.deck_frame = DeckBuilderFrame(self.notebook)
self.notebook.add(self.deck_frame, text=" 🎴 Deck Builder ")
# Skill Search Tab
self.hints_frame = SkillSearchFrame(self.notebook)
self.notebook.add(self.hints_frame, text=" 🔍 Skill Search (Beta) ")
# Training Sim Tab
self.sim_frame = TrainingSimFrame(self.notebook)
self.notebook.add(self.sim_frame, text=" 📈 Training Sim (Beta) ")
def create_status_bar(self, parent):
"""Create status bar at bottom"""
status_outer = tk.Frame(parent, bg=BG_MEDIUM)
status_outer.pack(fill=tk.X, side=tk.BOTTOM)
status_frame = tk.Frame(status_outer, bg=BG_MEDIUM)
status_frame.pack(fill=tk.X, padx=15, pady=8)
self.status_label = tk.Label(
status_frame,
text="✓ Ready",
font=FONT_SMALL,
bg=BG_MEDIUM,
fg=TEXT_MUTED
)
self.status_label.pack(side=tk.LEFT)
tk.Label(
status_frame,
text="Data from gametora.com",
font=FONT_SMALL,
bg=BG_MEDIUM,
fg=TEXT_MUTED
).pack(side=tk.RIGHT)
tk.Label(
status_frame,
text="Made by Kiyreload │ ",
font=FONT_SMALL,
bg=BG_MEDIUM,
fg=ACCENT_TERTIARY
).pack(side=tk.RIGHT)
def on_card_selected(self, card_id, card_name):
"""Handle card selection from card list"""
# Update other tabs with selected card
if hasattr(self, 'effects_frame'):
self.effects_frame.set_card(card_id)
if hasattr(self, 'hints_frame'):
self.hints_frame.set_card(card_id)
self.status_label.config(text=f"📌 Selected: {card_name}")
def refresh_stats(self):
"""Refresh the statistics display"""
stats = get_database_stats()
owned = get_owned_count()
stats_parts = [
f"📊 {stats.get('total_cards', 0)} Cards",
f"{owned} Owned",
f"🏆 {stats.get('by_rarity', {}).get('SSR', 0)} SSR",
f"{stats.get('by_rarity', {}).get('SR', 0)} SR",
f"{stats.get('by_rarity', {}).get('R', 0)} R"
]
stats_text = "".join(stats_parts)
self.stats_label.config(text=stats_text)
def show_update_dialog(self):
"""Show the update dialog"""
show_update_dialog(self.root)
def run(self):
"""Start the application"""
self.root.mainloop()
def main():
"""Entry point for GUI"""
app = MainWindow()
app.run()
if __name__ == "__main__":
main()