fix(gui): proper Files & Media layout with equal space allocation
- Track section open state via _files_section_open, _shots_section_open - Calculate available space, divide by number of open sections - Each section gets equal height when both open - Content scrolls internally if it exceeds allocated space - Removed unused _render_files_panel and _render_screenshots_panel methods
This commit is contained in:
+81
-112
@@ -873,11 +873,87 @@ class App:
|
|||||||
exp, opened = imgui.begin("Files & Media", self.show_windows["Files & Media"])
|
exp, opened = imgui.begin("Files & Media", self.show_windows["Files & Media"])
|
||||||
self.show_windows["Files & Media"] = bool(opened)
|
self.show_windows["Files & Media"] = bool(opened)
|
||||||
if exp:
|
if exp:
|
||||||
if imgui.collapsing_header("Files"):
|
if not hasattr(self, "_files_section_open"): self._files_section_open = True
|
||||||
self._render_files_panel()
|
if not hasattr(self, "_shots_section_open"): self._shots_section_open = True
|
||||||
if imgui.collapsing_header("Screenshots"):
|
avail = imgui.get_content_region_avail().y
|
||||||
self._render_screenshots_panel()
|
files_open = imgui.collapsing_header("Files", imgui.TreeNodeFlags_.default_open if self._files_section_open else 0)
|
||||||
imgui.end()
|
if files_open != self._files_section_open: self._files_section_open = files_open
|
||||||
|
if files_open:
|
||||||
|
imgui.text("Paths | Base Dir:"); imgui.same_line()
|
||||||
|
imgui.set_next_item_width(-100)
|
||||||
|
ch, self.ui_files_base_dir = imgui.input_text("##f_base", self.ui_files_base_dir)
|
||||||
|
imgui.same_line()
|
||||||
|
if imgui.button("Browse##fb"):
|
||||||
|
r = hide_tk_root(); d = filedialog.askdirectory(); r.destroy()
|
||||||
|
if d: self.ui_files_base_dir = d
|
||||||
|
imgui.separator()
|
||||||
|
num_open = (1 if self._files_section_open else 0) + (1 if self._shots_section_open else 0)
|
||||||
|
child_h = (avail - 120) / max(num_open, 1)
|
||||||
|
if imgui.begin_child("f_paths", imgui.ImVec2(0, max(child_h, 50)), True):
|
||||||
|
if imgui.begin_table("files_table", 4, imgui.TableFlags_.resizable | imgui.TableFlags_.borders):
|
||||||
|
imgui.table_setup_column("Actions", imgui.TableColumnFlags_.width_fixed, 40)
|
||||||
|
imgui.table_setup_column("File Path", imgui.TableColumnFlags_.width_stretch)
|
||||||
|
imgui.table_setup_column("Flags", imgui.TableColumnFlags_.width_fixed, 150)
|
||||||
|
imgui.table_setup_column("Cache", imgui.TableColumnFlags_.width_fixed, 40)
|
||||||
|
imgui.table_headers_row()
|
||||||
|
for i, f_item in enumerate(self.files):
|
||||||
|
imgui.table_next_row()
|
||||||
|
imgui.table_set_column_index(0)
|
||||||
|
if imgui.button(f"x##f{i}"): self.files.pop(i); break
|
||||||
|
imgui.table_set_column_index(1)
|
||||||
|
imgui.text(f_item.path if hasattr(f_item, "path") else str(f_item))
|
||||||
|
imgui.table_set_column_index(2)
|
||||||
|
if hasattr(f_item, "auto_aggregate"):
|
||||||
|
changed_agg, f_item.auto_aggregate = imgui.checkbox(f"Agg##a{i}", f_item.auto_aggregate)
|
||||||
|
imgui.same_line()
|
||||||
|
changed_full, f_item.force_full = imgui.checkbox(f"Full##f{i}", f_item.force_full)
|
||||||
|
imgui.table_set_column_index(3)
|
||||||
|
path = f_item.path if hasattr(f_item, "path") else str(f_item)
|
||||||
|
is_cached = any(path in c for c in getattr(self, "_cached_files", []))
|
||||||
|
if is_cached: imgui.text_colored("●", imgui.ImVec4(0, 1, 0, 1))
|
||||||
|
else: imgui.text_disabled("○")
|
||||||
|
imgui.end_table()
|
||||||
|
imgui.end_child()
|
||||||
|
if imgui.button("Add File(s)"):
|
||||||
|
r = hide_tk_root(); paths = filedialog.askopenfilenames(); r.destroy()
|
||||||
|
for p in paths:
|
||||||
|
if p not in [f.path if hasattr(f, "path") else f for f in self.files]:
|
||||||
|
self.files.append(models.FileItem(path=p))
|
||||||
|
imgui.same_line()
|
||||||
|
if imgui.button("Add Wildcard"):
|
||||||
|
r = hide_tk_root(); d = filedialog.askdirectory(); r.destroy()
|
||||||
|
if d: self.files.append(models.FileItem(path=str(Path(d) / "**" / "*")))
|
||||||
|
imgui.separator()
|
||||||
|
from src import summarize
|
||||||
|
stats = summarize._summary_cache.get_stats()
|
||||||
|
imgui.text_disabled(f"Summary Cache: {stats['entries']} entries ({stats['size_bytes']} bytes)")
|
||||||
|
imgui.same_line()
|
||||||
|
if imgui.button("Clear##fsc"): self.controller._cb_clear_summary_cache()
|
||||||
|
shots_open = imgui.collapsing_header("Screenshots", imgui.TreeNodeFlags_.default_open if self._shots_section_open else 0)
|
||||||
|
if shots_open != self._shots_section_open: self._shots_section_open = shots_open
|
||||||
|
if shots_open:
|
||||||
|
imgui.text("Paths | Base Dir:"); imgui.same_line()
|
||||||
|
imgui.set_next_item_width(-100)
|
||||||
|
ch, self.ui_shots_base_dir = imgui.input_text("##s_base", self.ui_shots_base_dir)
|
||||||
|
imgui.same_line()
|
||||||
|
if imgui.button("Browse##sb"):
|
||||||
|
r = hide_tk_root(); d = filedialog.askdirectory(); r.destroy()
|
||||||
|
if d: self.ui_shots_base_dir = d
|
||||||
|
imgui.separator()
|
||||||
|
num_open = (1 if self._files_section_open else 0) + (1 if self._shots_section_open else 0)
|
||||||
|
child_h = (avail - 120) / max(num_open, 1)
|
||||||
|
if imgui.begin_child("s_paths", imgui.ImVec2(0, max(child_h, 50)), True):
|
||||||
|
for i, s in enumerate(self.screenshots):
|
||||||
|
if imgui.button(f"x##s{i}"): self.screenshots.pop(i); break
|
||||||
|
imgui.same_line(); imgui.text(s)
|
||||||
|
imgui.end_child()
|
||||||
|
if imgui.button("Add Screenshot(s)"):
|
||||||
|
r = hide_tk_root()
|
||||||
|
paths = filedialog.askopenfilenames(title="Select Screenshots", filetypes=[("Images", "*.png *.jpg *.jpeg *.gif *.bmp *.webp"), ("All", "*.*")])
|
||||||
|
r.destroy()
|
||||||
|
for p in paths:
|
||||||
|
if p not in self.screenshots: self.screenshots.append(p)
|
||||||
|
imgui.end()
|
||||||
if self.show_windows.get("AI Settings", False):
|
if self.show_windows.get("AI Settings", False):
|
||||||
exp, opened = imgui.begin("AI Settings", self.show_windows["AI Settings"])
|
exp, opened = imgui.begin("AI Settings", self.show_windows["AI Settings"])
|
||||||
self.show_windows["AI Settings"] = bool(opened)
|
self.show_windows["AI Settings"] = bool(opened)
|
||||||
@@ -2906,113 +2982,6 @@ def hello():
|
|||||||
markdown_helper.render(md)
|
markdown_helper.render(md)
|
||||||
|
|
||||||
|
|
||||||
def _render_files_panel(self) -> None:
|
|
||||||
if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_files_panel")
|
|
||||||
imgui.text("Paths")
|
|
||||||
imgui.same_line()
|
|
||||||
imgui.text("| Base Dir:")
|
|
||||||
imgui.same_line()
|
|
||||||
imgui.set_next_item_width(-100)
|
|
||||||
ch, self.ui_files_base_dir = imgui.input_text("##f_base", self.ui_files_base_dir)
|
|
||||||
imgui.same_line()
|
|
||||||
if imgui.button("Browse##fb"):
|
|
||||||
r = hide_tk_root()
|
|
||||||
d = filedialog.askdirectory()
|
|
||||||
r.destroy()
|
|
||||||
if d: self.ui_files_base_dir = d
|
|
||||||
imgui.separator()
|
|
||||||
imgui.begin_child("f_paths", imgui.ImVec2(0, -40), True)
|
|
||||||
if imgui.begin_table("files_table", 4, imgui.TableFlags_.resizable | imgui.TableFlags_.borders):
|
|
||||||
imgui.table_setup_column("Actions", imgui.TableColumnFlags_.width_fixed, 40)
|
|
||||||
imgui.table_setup_column("File Path", imgui.TableColumnFlags_.width_stretch)
|
|
||||||
imgui.table_setup_column("Flags", imgui.TableColumnFlags_.width_fixed, 150)
|
|
||||||
imgui.table_setup_column("Cache", imgui.TableColumnFlags_.width_fixed, 40)
|
|
||||||
imgui.table_headers_row()
|
|
||||||
|
|
||||||
for i, f_item in enumerate(self.files):
|
|
||||||
imgui.table_next_row()
|
|
||||||
# Actions
|
|
||||||
imgui.table_set_column_index(0)
|
|
||||||
if imgui.button(f"x##f{i}"):
|
|
||||||
self.files.pop(i)
|
|
||||||
break
|
|
||||||
# File Path
|
|
||||||
imgui.table_set_column_index(1)
|
|
||||||
imgui.text(f_item.path if hasattr(f_item, "path") else str(f_item))
|
|
||||||
# Flags
|
|
||||||
imgui.table_set_column_index(2)
|
|
||||||
if hasattr(f_item, "auto_aggregate"):
|
|
||||||
changed_agg, f_item.auto_aggregate = imgui.checkbox(f"Agg##a{i}", f_item.auto_aggregate)
|
|
||||||
imgui.same_line()
|
|
||||||
changed_full, f_item.force_full = imgui.checkbox(f"Full##f{i}", f_item.force_full)
|
|
||||||
# Cache
|
|
||||||
imgui.table_set_column_index(3)
|
|
||||||
path = f_item.path if hasattr(f_item, "path") else str(f_item)
|
|
||||||
is_cached = any(path in c for c in getattr(self, "_cached_files", []))
|
|
||||||
if is_cached:
|
|
||||||
imgui.text_colored("●", imgui.ImVec4(0, 1, 0, 1)) # Green dot
|
|
||||||
else:
|
|
||||||
imgui.text_disabled("○")
|
|
||||||
imgui.end_table()
|
|
||||||
imgui.end_child()
|
|
||||||
if imgui.button("Add File(s)"):
|
|
||||||
r = hide_tk_root()
|
|
||||||
paths = filedialog.askopenfilenames()
|
|
||||||
r.destroy()
|
|
||||||
for p in paths:
|
|
||||||
if p not in [f.path if hasattr(f, "path") else f for f in self.files]:
|
|
||||||
self.files.append(models.FileItem(path=p))
|
|
||||||
imgui.same_line()
|
|
||||||
if imgui.button("Add Wildcard"):
|
|
||||||
r = hide_tk_root()
|
|
||||||
d = filedialog.askdirectory()
|
|
||||||
r.destroy()
|
|
||||||
if d: self.files.append(models.FileItem(path=str(Path(d) / "**" / "*")))
|
|
||||||
|
|
||||||
imgui.separator()
|
|
||||||
from src import summarize
|
|
||||||
stats = summarize._summary_cache.get_stats()
|
|
||||||
imgui.text_disabled(f"Summary Cache: {stats['entries']} entries ({stats['size_bytes']} bytes)")
|
|
||||||
imgui.same_line()
|
|
||||||
if imgui.button("Clear Summary Cache##btn_clear_summary_cache"):
|
|
||||||
self.controller._cb_clear_summary_cache()
|
|
||||||
|
|
||||||
if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_files_panel")
|
|
||||||
|
|
||||||
def _render_screenshots_panel(self) -> None:
|
|
||||||
if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_screenshots_panel")
|
|
||||||
imgui.text("Paths")
|
|
||||||
imgui.same_line()
|
|
||||||
imgui.text("| Base Dir:")
|
|
||||||
imgui.same_line()
|
|
||||||
imgui.set_next_item_width(-100)
|
|
||||||
ch, self.ui_shots_base_dir = imgui.input_text("##s_base", self.ui_shots_base_dir)
|
|
||||||
imgui.same_line()
|
|
||||||
if imgui.button("Browse##sb"):
|
|
||||||
r = hide_tk_root()
|
|
||||||
d = filedialog.askdirectory()
|
|
||||||
r.destroy()
|
|
||||||
if d: self.ui_shots_base_dir = d
|
|
||||||
imgui.separator()
|
|
||||||
imgui.begin_child("s_paths", imgui.ImVec2(0, -40), True)
|
|
||||||
for i, s in enumerate(self.screenshots):
|
|
||||||
if imgui.button(f"x##s{i}"):
|
|
||||||
self.screenshots.pop(i)
|
|
||||||
break
|
|
||||||
imgui.same_line()
|
|
||||||
imgui.text(s)
|
|
||||||
imgui.end_child()
|
|
||||||
if imgui.button("Add Screenshot(s)"):
|
|
||||||
r = hide_tk_root()
|
|
||||||
paths = filedialog.askopenfilenames(
|
|
||||||
title="Select Screenshots",
|
|
||||||
filetypes=[("Images", "*.png *.jpg *.jpeg *.gif *.bmp *.webp"), ("All", "*.*")],
|
|
||||||
)
|
|
||||||
r.destroy()
|
|
||||||
for p in paths:
|
|
||||||
if p not in self.screenshots: self.screenshots.append(p)
|
|
||||||
if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_screenshots_panel")
|
|
||||||
|
|
||||||
def _render_discussion_panel(self) -> None:
|
def _render_discussion_panel(self) -> None:
|
||||||
"""
|
"""
|
||||||
[C: tests/test_discussion_takes_gui.py:test_render_discussion_tabs, tests/test_discussion_takes_gui.py:test_switching_discussion_via_tabs, tests/test_gui_discussion_tabs.py:test_discussion_tabs_rendered, tests/test_gui_phase4.py:test_track_discussion_toggle, tests/test_gui_symbol_navigation.py:test_render_discussion_panel_symbol_lookup]
|
[C: tests/test_discussion_takes_gui.py:test_render_discussion_tabs, tests/test_discussion_takes_gui.py:test_switching_discussion_via_tabs, tests/test_gui_discussion_tabs.py:test_discussion_tabs_rendered, tests/test_gui_phase4.py:test_track_discussion_toggle, tests/test_gui_symbol_navigation.py:test_render_discussion_panel_symbol_lookup]
|
||||||
|
|||||||
Reference in New Issue
Block a user