feat: Add new GUI effects view and numerous image assets.
This commit is contained in:
@@ -331,7 +331,7 @@ class CardListFrame(ttk.Frame):
|
||||
if resolved_path and os.path.exists(resolved_path):
|
||||
try:
|
||||
pil_img = Image.open(resolved_path)
|
||||
pil_img.thumbnail((32, 32), Image.Resampling.LANCZOS)
|
||||
pil_img.thumbnail((48, 48), Image.Resampling.LANCZOS)
|
||||
img = ImageTk.PhotoImage(pil_img)
|
||||
self.icon_cache[card_id] = img
|
||||
except:
|
||||
|
||||
@@ -49,13 +49,13 @@ class CardSlot(tk.Frame):
|
||||
|
||||
# Image Area (Left)
|
||||
self.image_label = tk.Label(self, bg=BG_MEDIUM, text="📭", fg=TEXT_MUTED,
|
||||
font=('Segoe UI', 20))
|
||||
self.image_label.grid(row=0, column=0, rowspan=3, padx=8, pady=8)
|
||||
font=('Segoe UI', 32))
|
||||
self.image_label.grid(row=0, column=0, rowspan=3, padx=12, pady=12)
|
||||
|
||||
# Details Area (Right)
|
||||
self.name_label = tk.Label(self, text="Empty Slot", bg=BG_MEDIUM, fg=TEXT_MUTED,
|
||||
font=FONT_BODY_BOLD, anchor='w', wraplength=130)
|
||||
self.name_label.grid(row=0, column=1, sticky='w', padx=8, pady=(10, 0))
|
||||
self.name_label = tk.Label(self, text="Empty Slot", bg=BG_MEDIUM, fg=TEXT_PRIMARY,
|
||||
font=FONT_BODY_BOLD, anchor='w', wraplength=180) # Increased wrap
|
||||
self.name_label.grid(row=0, column=1, sticky='w', padx=8, pady=(15, 0))
|
||||
|
||||
self.meta_label = tk.Label(self, text="", bg=BG_MEDIUM, fg=TEXT_MUTED,
|
||||
font=FONT_SMALL, anchor='w')
|
||||
@@ -139,7 +139,7 @@ class CardSlot(tk.Frame):
|
||||
def reset(self):
|
||||
self.name_label.config(text="Empty Slot", fg=TEXT_MUTED)
|
||||
self.meta_label.config(text="Click a card to add")
|
||||
self.image_label.config(image='', text="📭", font=('Segoe UI', 20))
|
||||
self.image_label.config(image='', text="📭", font=('Segoe UI', 32))
|
||||
self.config(highlightbackground=BG_LIGHT)
|
||||
self.image_ref = None
|
||||
self.toggle_controls(False)
|
||||
@@ -149,7 +149,8 @@ class CardSlot(tk.Frame):
|
||||
if resolved_path and os.path.exists(resolved_path):
|
||||
try:
|
||||
pil_img = Image.open(resolved_path)
|
||||
pil_img.thumbnail((65, 65), Image.Resampling.LANCZOS)
|
||||
# Significantly larger images as requested (120x120)
|
||||
pil_img.thumbnail((120, 120), Image.Resampling.LANCZOS)
|
||||
self.image_ref = ImageTk.PhotoImage(pil_img)
|
||||
self.image_label.config(image=self.image_ref, text='')
|
||||
except Exception as e:
|
||||
@@ -369,7 +370,8 @@ class DeckBuilderFrame(ttk.Frame):
|
||||
if not img and resolved_path and os.path.exists(resolved_path):
|
||||
try:
|
||||
pil_img = Image.open(resolved_path)
|
||||
pil_img.thumbnail((32, 32), Image.Resampling.LANCZOS)
|
||||
# Larger thumbnails in the list too (48x48)
|
||||
pil_img.thumbnail((48, 48), Image.Resampling.LANCZOS)
|
||||
img = ImageTk.PhotoImage(pil_img)
|
||||
self.icon_cache[card_id] = img
|
||||
except:
|
||||
|
||||
@@ -152,7 +152,7 @@ class DeckSkillsFrame(ttk.Frame):
|
||||
if resolved_path and os.path.exists(resolved_path):
|
||||
try:
|
||||
pil_img = Image.open(resolved_path)
|
||||
pil_img.thumbnail((32, 32), Image.Resampling.LANCZOS)
|
||||
pil_img.thumbnail((48, 48), Image.Resampling.LANCZOS)
|
||||
img = ImageTk.PhotoImage(pil_img)
|
||||
self.icon_cache[card_id] = img
|
||||
except: pass
|
||||
|
||||
@@ -82,7 +82,7 @@ class EffectsFrame(ttk.Frame):
|
||||
button_frame = tk.Frame(control_frame, bg=BG_MEDIUM)
|
||||
button_frame.pack(side=tk.LEFT, padx=25)
|
||||
|
||||
quick_levels = [1, 25, 40, 50]
|
||||
quick_levels = [25, 30, 35, 40, 45, 50]
|
||||
for lvl in quick_levels:
|
||||
btn = create_styled_button(button_frame, text=f"Lv{lvl}",
|
||||
command=lambda l=lvl: self.set_level(l),
|
||||
|
||||
@@ -132,14 +132,23 @@ class SkillSearchFrame(ttk.Frame):
|
||||
|
||||
def load_skills(self):
|
||||
"""Load all unique skills into listbox"""
|
||||
self.all_skills = get_all_unique_skills()
|
||||
self.update_listbox(self.all_skills)
|
||||
skills_data = get_all_unique_skills()
|
||||
# Store as list of (skill_name, is_golden) tuples
|
||||
self.all_skills = skills_data
|
||||
self.update_listbox(skills_data)
|
||||
|
||||
def update_listbox(self, items):
|
||||
"""Update listbox content"""
|
||||
self.skill_listbox.delete(0, tk.END)
|
||||
for item in items:
|
||||
self.skill_listbox.insert(tk.END, item)
|
||||
if isinstance(item, tuple):
|
||||
skill_name, is_golden = item
|
||||
# Display with golden indicator
|
||||
display_name = f"✨ GOLDEN {skill_name}" if is_golden else skill_name
|
||||
self.skill_listbox.insert(tk.END, display_name)
|
||||
else:
|
||||
# Backward compatibility
|
||||
self.skill_listbox.insert(tk.END, item)
|
||||
|
||||
def filter_skills(self, *args):
|
||||
"""Filter skills based on search text"""
|
||||
@@ -147,8 +156,18 @@ class SkillSearchFrame(ttk.Frame):
|
||||
if not search:
|
||||
self.update_listbox(self.all_skills)
|
||||
return
|
||||
|
||||
filtered = [s for s in self.all_skills if search in s.lower()]
|
||||
|
||||
# Filter skills - handle both tuple format and string format
|
||||
filtered = []
|
||||
for item in self.all_skills:
|
||||
if isinstance(item, tuple):
|
||||
skill_name, is_golden = item
|
||||
if search in skill_name.lower() or (search == "golden" and is_golden):
|
||||
filtered.append(item)
|
||||
else:
|
||||
if search in item.lower():
|
||||
filtered.append(item)
|
||||
|
||||
self.update_listbox(filtered)
|
||||
|
||||
def on_filter_changed(self):
|
||||
@@ -162,7 +181,13 @@ class SkillSearchFrame(ttk.Frame):
|
||||
if not selection:
|
||||
return
|
||||
|
||||
skill_name = self.skill_listbox.get(selection[0])
|
||||
display_name = self.skill_listbox.get(selection[0])
|
||||
# Extract actual skill name (remove "✨ GOLDEN " prefix if present)
|
||||
if display_name.startswith("✨ GOLDEN "):
|
||||
skill_name = display_name.replace("✨ GOLDEN ", "", 1)
|
||||
else:
|
||||
skill_name = display_name
|
||||
|
||||
self.current_skill = skill_name
|
||||
self.show_cards_for_skill(skill_name)
|
||||
|
||||
@@ -191,22 +216,34 @@ class SkillSearchFrame(ttk.Frame):
|
||||
if resolved_path and os.path.exists(resolved_path):
|
||||
try:
|
||||
pil_img = Image.open(resolved_path)
|
||||
pil_img.thumbnail((32, 32), Image.Resampling.LANCZOS)
|
||||
pil_img.thumbnail((48, 48), Image.Resampling.LANCZOS)
|
||||
img = ImageTk.PhotoImage(pil_img)
|
||||
self.icon_cache[card_id] = img
|
||||
except:
|
||||
pass
|
||||
|
||||
type_display = f"{get_type_icon(card['type'])} {card['type']}"
|
||||
# Handle both 'type' and 'card_type' keys for compatibility
|
||||
card_type = card.get('type') or card.get('card_type') or 'Unknown'
|
||||
type_display = f"{get_type_icon(card_type)} {card_type}"
|
||||
owned_mark = "★" if card.get('is_owned') else ""
|
||||
|
||||
# Highlight golden skills in source column
|
||||
source = card.get('source', 'Event')
|
||||
if card.get('is_gold', False):
|
||||
source = f"✨ GOLDEN {source.replace('✨ GOLDEN ', '')}" # Ensure no double prefix
|
||||
|
||||
# Handle potential None values
|
||||
card_name = card.get('name') or 'Unknown'
|
||||
card_rarity = card.get('rarity') or 'Unknown'
|
||||
card_details = card.get('details') or 'No details available'
|
||||
|
||||
values = (
|
||||
owned_mark,
|
||||
card['name'],
|
||||
card['rarity'],
|
||||
card_name,
|
||||
card_rarity,
|
||||
type_display,
|
||||
card['source'],
|
||||
card['details']
|
||||
source,
|
||||
card_details
|
||||
)
|
||||
|
||||
if img:
|
||||
|
||||
@@ -37,6 +37,7 @@ class MainWindow:
|
||||
self.root.geometry("1400x850")
|
||||
self.root.minsize(1350, 800)
|
||||
|
||||
|
||||
# Set icon
|
||||
try:
|
||||
icon_path = resolve_image_path("1_Special Week.png")
|
||||
@@ -240,7 +241,9 @@ class MainWindow:
|
||||
show_update_dialog(self.root)
|
||||
|
||||
def run(self):
|
||||
"""Start the application"""
|
||||
"""
|
||||
Start the GUI application and display the main window.
|
||||
"""
|
||||
self.root.mainloop()
|
||||
|
||||
|
||||
|
||||
12
gui/theme.py
12
gui/theme.py
@@ -209,7 +209,7 @@ def configure_styles(root: tk.Tk):
|
||||
foreground=TEXT_SECONDARY,
|
||||
fieldbackground=BG_MEDIUM,
|
||||
font=FONT_BODY,
|
||||
rowheight=40)
|
||||
rowheight=60)
|
||||
|
||||
# Deck list style
|
||||
style.configure('DeckList.Treeview',
|
||||
@@ -217,7 +217,7 @@ def configure_styles(root: tk.Tk):
|
||||
foreground=TEXT_SECONDARY,
|
||||
fieldbackground=BG_MEDIUM,
|
||||
font=FONT_BODY,
|
||||
rowheight=40)
|
||||
rowheight=60)
|
||||
style.map('DeckList.Treeview',
|
||||
background=[('selected', ACCENT_PRIMARY)])
|
||||
|
||||
@@ -231,14 +231,6 @@ def configure_styles(root: tk.Tk):
|
||||
style.configure('Horizontal.TScale',
|
||||
background=BG_DARK)
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────
|
||||
# Progressbar styles
|
||||
# ─────────────────────────────────────────────────────────────────────────
|
||||
style.configure('TProgressbar',
|
||||
background=ACCENT_PRIMARY,
|
||||
troughcolor=BG_MEDIUM,
|
||||
borderwidth=0,
|
||||
thickness=8)
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────
|
||||
# Scrollbar styles
|
||||
|
||||
Reference in New Issue
Block a user