diff --git a/src/textual_paint/enhanced_directory_tree.py b/src/textual_paint/enhanced_directory_tree.py index 4cc8f59..726fa16 100644 --- a/src/textual_paint/enhanced_directory_tree.py +++ b/src/textual_paint/enhanced_directory_tree.py @@ -19,22 +19,17 @@ class EnhancedDirectoryTree(DirectoryTree): self.scroll_to_region(region, animate=False, top=True) self.set_timer(0.01, scroll_node_to_top) - def _hook_node_add(self, node: TreeNode[DirEntry], remaining_parts: tuple[str]) -> None: - # print("_hook_node_add", node, remaining_parts) + def _expand_matching_child(self, node: TreeNode[DirEntry], remaining_parts: tuple[str]) -> None: + """Hooks into DirectoryTree's add method, and expands the child node matching the next path part, recursively. + + Once the last part of the path is reached, it scrolls to and selects the node. + """ + # print("_expand_matching_child", node, remaining_parts) orig_add = node.add - _hook_node_add = self._hook_node_add + _expand_matching_child = self._expand_matching_child _add_to_load_queue = self._add_to_load_queue _go_to_node = self._go_to_node - def add( - self: TreeNode[DirEntry], - label: TextType, - data: DirEntry | None = None, - *, - expand: bool = False, - allow_expand: bool = True, - ) -> TreeNode[DirEntry]: - node = orig_add(label, data, expand=expand, allow_expand=allow_expand) - # print("add", node, node.data) + def expand_if_match(node: TreeNode[DirEntry]) -> None: if node.data: # print(f"comparing node.data.path.parts[-1] {node.data.path.parts[-1]!r} with remaining_parts[0] {remaining_parts[0]!r}") if node.data.path.parts[-1] == remaining_parts[0]: @@ -42,7 +37,7 @@ class EnhancedDirectoryTree(DirectoryTree): if node.data.path.is_dir(): sliced_parts = remaining_parts[1:] # print("recursing with sliced_parts", sliced_parts) - _hook_node_add(node, sliced_parts) # type: ignore + _expand_matching_child(node, sliced_parts) # type: ignore _add_to_load_queue(node) # else: # print("Found a file, not as last part of path:", node.data.path, "remaining_parts:", remaining_parts) @@ -54,8 +49,26 @@ class EnhancedDirectoryTree(DirectoryTree): # but for File > New, File > Open, it should expand the current directory. if node.data.path.is_dir(): _add_to_load_queue(node) + def add( + self: TreeNode[DirEntry], + label: TextType, + data: DirEntry | None = None, + *, + expand: bool = False, + allow_expand: bool = True, + ) -> TreeNode[DirEntry]: + node = orig_add(label, data, expand=expand, allow_expand=allow_expand) + # print("add", node, node.data) + expand_if_match(node) + # Note: The hook is left indefinitely. + # It may be worth some consideration as to whether this could pose any problems. + # However, we can't just reset to orig_add here since it would only handle the first added node. return node + # Hook the add method to handle new nodes. node.add = add.__get__(node, type(node)) + # Also expand children of the node already loaded. + for child in node.children: + expand_if_match(child) def expand_to_path(self, target_path: str | Path) -> None: """Expand the directory tree to the target path, loading any directories as needed.""" @@ -70,5 +83,5 @@ class EnhancedDirectoryTree(DirectoryTree): # - Maybe this method should return the node if it was found. # - Definitely want to figure out how to avoid the timers. - self._hook_node_add(self.root, target_path.parts[1:]) + self._expand_matching_child(self.root, target_path.parts[1:]) diff --git a/src/textual_paint/file_dialogs.py b/src/textual_paint/file_dialogs.py index 780194e..7d8518e 100644 --- a/src/textual_paint/file_dialogs.py +++ b/src/textual_paint/file_dialogs.py @@ -64,7 +64,15 @@ class FileDialogWindow(DialogWindow): if os.path.splitext(file_path)[1] == "": file_path += self._auto_add_default_extension - # TODO: if directory, just navigate to it in the directory tree + # if it's a directory, just navigate to it in the directory tree + if os.path.isdir(file_path): + # self._directory_tree_selected_path = file_path + # self._selected_file_path = file_path + # self._expand_directory_tree() + tree = self.content.query_one(EnhancedDirectoryTree) + tree.expand_to_path(file_path) + return + self.handle_selected_file_path(file_path) def on_mount(self) -> None: