Refine tree widget event handling and hover state management
This commit is contained in:
parent
7af12f7035
commit
b7e4c96188
@ -127,13 +127,16 @@ class InputHandler:
|
|||||||
# Zoom in viewport
|
# Zoom in viewport
|
||||||
self.camera.handle_zoom(event.y)
|
self.camera.handle_zoom(event.y)
|
||||||
elif inspector_rect and inspector_rect.collidepoint(mouse_x, mouse_y) and self.hud.tree_widget:
|
elif inspector_rect and inspector_rect.collidepoint(mouse_x, mouse_y) and self.hud.tree_widget:
|
||||||
# Scroll tree widget in inspector - convert to local coordinates if needed
|
# Scroll tree widget in inspector
|
||||||
|
if not viewport_rect.collidepoint(mouse_x, mouse_y):
|
||||||
|
# Convert to local coordinates if needed
|
||||||
if not hasattr(event, 'pos'):
|
if not hasattr(event, 'pos'):
|
||||||
event.pos = (mouse_x - inspector_rect.x, mouse_y - inspector_rect.y)
|
event.pos = (mouse_x - inspector_rect.x, mouse_y - inspector_rect.y)
|
||||||
else:
|
else:
|
||||||
local_x = mouse_x - inspector_rect.x
|
local_x = mouse_x - inspector_rect.x
|
||||||
local_y = mouse_y - inspector_rect.y
|
local_y = mouse_y - inspector_rect.y
|
||||||
event.pos = (local_x, local_y)
|
event.pos = (local_x, local_y)
|
||||||
|
print("Passing event to tree widget")
|
||||||
self.hud.tree_widget.handle_event(event)
|
self.hud.tree_widget.handle_event(event)
|
||||||
else:
|
else:
|
||||||
# Fallback: always zoom if no HUD reference
|
# Fallback: always zoom if no HUD reference
|
||||||
|
|||||||
@ -368,11 +368,16 @@ class HUD:
|
|||||||
if (0 <= tree_local_pos[0] < self.tree_widget.rect.width and
|
if (0 <= tree_local_pos[0] < self.tree_widget.rect.width and
|
||||||
0 <= tree_local_pos[1] < self.tree_widget.rect.height):
|
0 <= tree_local_pos[1] < self.tree_widget.rect.height):
|
||||||
event.pos = tree_local_pos
|
event.pos = tree_local_pos
|
||||||
|
# This is the handle_event call that is being run even when the mouse is not over the tree widget
|
||||||
if self.tree_widget.handle_event(event):
|
if self.tree_widget.handle_event(event):
|
||||||
selected_entities = self.tree_widget.get_selected_entities()
|
selected_entities = self.tree_widget.get_selected_entities()
|
||||||
return 'tree_selection_changed', selected_entities
|
return 'tree_selection_changed', selected_entities
|
||||||
else:
|
else:
|
||||||
# For non-mouse events, try handling them normally
|
# Mouse left the tree widget area, clear hover
|
||||||
|
self.tree_widget.clear_hover()
|
||||||
|
else:
|
||||||
|
# Handle specific mouse events in tree widget (but not wheel - handled by InputHandler)
|
||||||
|
if event.type in (pygame.MOUSEBUTTONDOWN, pygame.MOUSEBUTTONUP):
|
||||||
if self.tree_widget.handle_event(event):
|
if self.tree_widget.handle_event(event):
|
||||||
selected_entities = self.tree_widget.get_selected_entities()
|
selected_entities = self.tree_widget.get_selected_entities()
|
||||||
return 'tree_selection_changed', selected_entities
|
return 'tree_selection_changed', selected_entities
|
||||||
|
|||||||
@ -23,11 +23,7 @@ class TreeNode(ABC):
|
|||||||
def add_child(self, child: 'TreeNode') -> None:
|
def add_child(self, child: 'TreeNode') -> None:
|
||||||
"""Add a child node to this node."""
|
"""Add a child node to this node."""
|
||||||
child.parent = self
|
child.parent = self
|
||||||
old_depth = child.depth
|
|
||||||
child.depth = self.depth + 1
|
child.depth = self.depth + 1
|
||||||
# Debug: check if depth changed incorrectly
|
|
||||||
if hasattr(child, 'entity') and isinstance(child, EntityNode) and old_depth != child.depth:
|
|
||||||
print(f"EntityNode depth changed from {old_depth} to {child.depth} when added to {self.label}")
|
|
||||||
self.children.append(child)
|
self.children.append(child)
|
||||||
|
|
||||||
def remove_child(self, child: 'TreeNode') -> None:
|
def remove_child(self, child: 'TreeNode') -> None:
|
||||||
@ -81,12 +77,7 @@ class TreeNode(ABC):
|
|||||||
|
|
||||||
def get_indent(self) -> int:
|
def get_indent(self) -> int:
|
||||||
"""Get the indentation width for this node."""
|
"""Get the indentation width for this node."""
|
||||||
indent = self.depth * 20
|
return self.depth * 20
|
||||||
# Debug: print inconsistent depths (only for EntityNodes)
|
|
||||||
if hasattr(self, 'entity') and isinstance(self, EntityNode):
|
|
||||||
if self.depth != 2: # EntityNodes should always be depth 2 (Simulation -> EntityType -> Entity)
|
|
||||||
print(f"Entity {self.entity_id} has inconsistent depth: {self.depth}, indent: {indent}")
|
|
||||||
return indent
|
|
||||||
|
|
||||||
|
|
||||||
class SimulationNode(TreeNode):
|
class SimulationNode(TreeNode):
|
||||||
@ -131,9 +122,9 @@ class SimulationNode(TreeNode):
|
|||||||
else:
|
else:
|
||||||
# Create new type node
|
# Create new type node
|
||||||
type_node = EntityTypeNode(type_name, entities)
|
type_node = EntityTypeNode(type_name, entities)
|
||||||
print(f"SimulationNode: adding {type_name} with current depth {type_node.depth}, my depth is {self.depth}")
|
|
||||||
self.add_child(type_node)
|
self.add_child(type_node)
|
||||||
print(f"SimulationNode: after adding, {type_name} has depth {type_node.depth}")
|
# Now update children after this node has correct depth
|
||||||
|
type_node._update_children()
|
||||||
|
|
||||||
|
|
||||||
class EntityTypeNode(TreeNode):
|
class EntityTypeNode(TreeNode):
|
||||||
@ -142,8 +133,6 @@ class EntityTypeNode(TreeNode):
|
|||||||
def __init__(self, entity_type: str, entities: List[Any]):
|
def __init__(self, entity_type: str, entities: List[Any]):
|
||||||
super().__init__(entity_type)
|
super().__init__(entity_type)
|
||||||
self.entities = entities
|
self.entities = entities
|
||||||
# Debug: check depth
|
|
||||||
print(f"EntityTypeNode {entity_type} created with depth {self.depth}")
|
|
||||||
# Don't call _update_children() here - parent will call after adding this node
|
# Don't call _update_children() here - parent will call after adding this node
|
||||||
|
|
||||||
def _update_children(self) -> None:
|
def _update_children(self) -> None:
|
||||||
@ -162,9 +151,6 @@ class EntityTypeNode(TreeNode):
|
|||||||
# Update existing node
|
# Update existing node
|
||||||
entity_node = existing_ids[entity_id]
|
entity_node = existing_ids[entity_id]
|
||||||
entity_node.entity = entity
|
entity_node.entity = entity
|
||||||
# Debug: verify depth is correct for updated nodes
|
|
||||||
if entity_node.depth != self.depth + 1:
|
|
||||||
print(f"Updated EntityNode {entity_id} has wrong depth: {entity_node.depth}, should be {self.depth + 1}")
|
|
||||||
else:
|
else:
|
||||||
# Create new entity node
|
# Create new entity node
|
||||||
entity_node = EntityNode(entity)
|
entity_node = EntityNode(entity)
|
||||||
|
|||||||
@ -42,6 +42,7 @@ class TreeWidget(UIElement):
|
|||||||
self.hovered_node: Optional[TreeNode] = None
|
self.hovered_node: Optional[TreeNode] = None
|
||||||
self.drag_start_node: Optional[TreeNode] = None
|
self.drag_start_node: Optional[TreeNode] = None
|
||||||
self.is_dragging = False
|
self.is_dragging = False
|
||||||
|
self.last_mouse_pos: Optional[Tuple[int, int]] = None
|
||||||
|
|
||||||
# Scrolling
|
# Scrolling
|
||||||
self.scroll_offset = 0
|
self.scroll_offset = 0
|
||||||
@ -183,6 +184,7 @@ class TreeWidget(UIElement):
|
|||||||
if event.type == pygame.MOUSEBUTTONDOWN:
|
if event.type == pygame.MOUSEBUTTONDOWN:
|
||||||
if event.button == 1: # Left click
|
if event.button == 1: # Left click
|
||||||
# Event position is already converted to local coordinates by HUD
|
# Event position is already converted to local coordinates by HUD
|
||||||
|
self.last_mouse_pos = event.pos
|
||||||
node = self._get_node_at_position_local(event.pos)
|
node = self._get_node_at_position_local(event.pos)
|
||||||
if node:
|
if node:
|
||||||
# Check for expand/collapse click
|
# Check for expand/collapse click
|
||||||
@ -197,6 +199,7 @@ class TreeWidget(UIElement):
|
|||||||
|
|
||||||
elif event.type == pygame.MOUSEMOTION:
|
elif event.type == pygame.MOUSEMOTION:
|
||||||
# Event position is already converted to local coordinates by HUD
|
# Event position is already converted to local coordinates by HUD
|
||||||
|
self.last_mouse_pos = event.pos
|
||||||
self.hovered_node = self._get_node_at_position_local(event.pos)
|
self.hovered_node = self._get_node_at_position_local(event.pos)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -218,6 +221,9 @@ class TreeWidget(UIElement):
|
|||||||
if self._should_update_tree():
|
if self._should_update_tree():
|
||||||
self._update_tree_structure()
|
self._update_tree_structure()
|
||||||
self._update_visible_nodes()
|
self._update_visible_nodes()
|
||||||
|
# Recalculate hover state based on last mouse position after structure changes
|
||||||
|
if self.last_mouse_pos:
|
||||||
|
self.hovered_node = self._get_node_at_position_local(self.last_mouse_pos)
|
||||||
|
|
||||||
def _should_update_tree(self) -> bool:
|
def _should_update_tree(self) -> bool:
|
||||||
"""Determine if the tree structure needs updating."""
|
"""Determine if the tree structure needs updating."""
|
||||||
@ -318,3 +324,8 @@ class TreeWidget(UIElement):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self._update_node_layout()
|
self._update_node_layout()
|
||||||
|
|
||||||
|
def clear_hover(self) -> None:
|
||||||
|
"""Clear the hover state (called when mouse leaves tree widget)."""
|
||||||
|
self.hovered_node = None
|
||||||
|
self.last_mouse_pos = None
|
||||||
Loading…
x
Reference in New Issue
Block a user