139 lines
4.1 KiB
Python
139 lines
4.1 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
Node Module
|
|
-----------
|
|
Defines the Node class for representing folder nodes in the structure.
|
|
"""
|
|
import uuid
|
|
from typing import List, Optional, Dict, Any
|
|
|
|
|
|
class Node:
|
|
"""Represents a folder node in the structure with parent-child relationships.
|
|
|
|
Attributes:
|
|
id (str): Unique identifier for the node
|
|
name (str): Display name of the node
|
|
parent_id (Optional[str]): ID of the parent node, None for root nodes
|
|
children (List[Node]): List of child nodes
|
|
x (float): X-coordinate for display
|
|
y (float): Y-coordinate for display
|
|
width (float): Width of the node in pixels
|
|
height (float): Height of the node in pixels
|
|
"""
|
|
|
|
def __init__(self, name: str, node_id: Optional[str] = None, parent_id: Optional[str] = None):
|
|
"""Initialize a new node.
|
|
|
|
Args:
|
|
name: The display name of the node
|
|
node_id: Optional unique identifier. If not provided, a UUID will be generated.
|
|
parent_id: Optional ID of the parent node.
|
|
"""
|
|
self.id = node_id or str(uuid.uuid4())
|
|
self.name = name
|
|
self.parent_id = parent_id
|
|
self.children: List['Node'] = []
|
|
self.x = 0.0
|
|
self.y = 0.0
|
|
self.width = 120.0
|
|
self.height = 60.0
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
"""Convert the node and its children to a dictionary.
|
|
|
|
Returns:
|
|
A dictionary representation of the node and its children.
|
|
"""
|
|
return {
|
|
'id': self.id,
|
|
'name': self.name,
|
|
'parent_id': self.parent_id,
|
|
'x': self.x,
|
|
'y': self.y,
|
|
'width': self.width,
|
|
'height': self.height,
|
|
'children': [child.to_dict() for child in self.children]
|
|
}
|
|
|
|
@classmethod
|
|
def from_dict(cls, data: Dict[str, Any]) -> 'Node':
|
|
"""Create a Node instance from a dictionary.
|
|
|
|
Args:
|
|
data: Dictionary containing node data
|
|
|
|
Returns:
|
|
A new Node instance with the given data
|
|
"""
|
|
node = cls(
|
|
name=data['name'],
|
|
node_id=data['id'],
|
|
parent_id=data.get('parent_id')
|
|
)
|
|
node.x = data.get('x', 0)
|
|
node.y = data.get('y', 0)
|
|
node.width = data.get('width', 120)
|
|
node.height = data.get('height', 60)
|
|
|
|
# Recursively create child nodes
|
|
for child_data in data.get('children', []):
|
|
child_node = cls.from_dict(child_data)
|
|
child_node.parent_id = node.id
|
|
node.children.append(child_node)
|
|
|
|
return node
|
|
|
|
def add_child(self, name: str) -> 'Node':
|
|
"""Add a new child node.
|
|
|
|
Args:
|
|
name: Name for the new child node
|
|
|
|
Returns:
|
|
The newly created child node
|
|
"""
|
|
child = Node(name, parent_id=self.id)
|
|
self.children.append(child)
|
|
return child
|
|
|
|
def remove_child(self, node_id: str) -> bool:
|
|
"""Remove a child node by ID.
|
|
|
|
Args:
|
|
node_id: ID of the node to remove
|
|
|
|
Returns:
|
|
True if the node was found and removed, False otherwise
|
|
"""
|
|
for i, child in enumerate(self.children):
|
|
if child.id == node_id:
|
|
self.children.pop(i)
|
|
return True
|
|
if child.remove_child(node_id):
|
|
return True
|
|
return False
|
|
|
|
def find_node(self, node_id: str) -> Optional['Node']:
|
|
"""Find a node by ID in the subtree.
|
|
|
|
Args:
|
|
node_id: ID of the node to find
|
|
|
|
Returns:
|
|
The found node, or None if not found
|
|
"""
|
|
if self.id == node_id:
|
|
return self
|
|
|
|
for child in self.children:
|
|
found = child.find_node(node_id)
|
|
if found:
|
|
return found
|
|
|
|
return None
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<Node id='{self.id}' name='{self.name}'>"
|