[Demo] Widget Focus System Example #143

Open
opened 2025-11-27 18:34:45 +00:00 by john · 0 comments
Owner

Python-level demonstration of a focus system using McRogueFace's event callbacks.

Context

Widget focus (click-to-focus, tab cycling, keyboard routing to focused widget) is a common UI pattern but highly application-specific:

  • Does mouseover change focus?
  • Does clicking?
  • Are some elements not focusable?
  • Should focus be visible? How?

Rather than bake one specific focus model into C++, this issue creates a Python demo showing how game developers can implement focus using the engine's primitives.

Philosophy

McRogueFace provides:

  • Mouse events: on_click, on_enter, on_exit (per-drawable)
  • Keyboard events: Scene-level on_key handler
  • Queryable state: mouse_pos, hovered

Game developers combine these to create their desired focus behavior. This demo shows one approach.

Definition of Done

  • demos/focus_system.py - working example
  • Demonstrates click-to-focus
  • Demonstrates tab cycling
  • Demonstrates visual focus indicator (outline, glow, etc.)
  • Routes keyboard input to focused widget
  • Well-commented to serve as documentation
  • Shows how to make elements non-focusable

Demo Design

# Conceptual structure - not final code

class FocusManager:
    def __init__(self, scene):
        self.focusable_widgets = []
        self.focused_index = -1
        scene.on_key = self.handle_key
    
    def register(self, widget, on_key_handler):
        widget.on_click = lambda x, y: self.focus(widget)
        self.focusable_widgets.append((widget, on_key_handler))
    
    def focus(self, widget):
        # Remove visual from old focused
        # Add visual to new focused
        # Update focused_index
        pass
    
    def handle_key(self, key, state):
        if key == "Tab" and state == "start":
            self.cycle_focus()
        elif self.focused_index >= 0:
            widget, handler = self.focusable_widgets[self.focused_index]
            handler(key, state)
    
    def cycle_focus(self):
        self.focused_index = (self.focused_index + 1) % len(self.focusable_widgets)
        self.focus(self.focusable_widgets[self.focused_index][0])

What This Is NOT

This is not a C++ engine feature. It's a demo showing that:

  1. McRogueFace provides sufficient primitives
  2. Focus can be implemented in pure Python
  3. Developers can customize focus behavior for their game

If patterns emerge that would benefit from C++ support, that's a future issue.

Dependencies

  • Blocked by: Callback Naming Standardization (NEW) - need on_click, on_enter
  • Blocked by: Mouse Enter/Exit Events (NEW) - for hover-to-focus variant
  • Demonstrates: #45 (Accessibility) - focus is key to keyboard navigation
  • Uses: All the new mouse event infrastructure
Python-level demonstration of a focus system using McRogueFace's event callbacks. ## Context Widget focus (click-to-focus, tab cycling, keyboard routing to focused widget) is a common UI pattern but highly application-specific: - Does mouseover change focus? - Does clicking? - Are some elements not focusable? - Should focus be visible? How? Rather than bake one specific focus model into C++, this issue creates a **Python demo** showing how game developers can implement focus using the engine's primitives. ## Philosophy McRogueFace provides: - **Mouse events**: on_click, on_enter, on_exit (per-drawable) - **Keyboard events**: Scene-level on_key handler - **Queryable state**: mouse_pos, hovered Game developers combine these to create their desired focus behavior. This demo shows one approach. ## Definition of Done - [ ] `demos/focus_system.py` - working example - [ ] Demonstrates click-to-focus - [ ] Demonstrates tab cycling - [ ] Demonstrates visual focus indicator (outline, glow, etc.) - [ ] Routes keyboard input to focused widget - [ ] Well-commented to serve as documentation - [ ] Shows how to make elements non-focusable ## Demo Design ```python # Conceptual structure - not final code class FocusManager: def __init__(self, scene): self.focusable_widgets = [] self.focused_index = -1 scene.on_key = self.handle_key def register(self, widget, on_key_handler): widget.on_click = lambda x, y: self.focus(widget) self.focusable_widgets.append((widget, on_key_handler)) def focus(self, widget): # Remove visual from old focused # Add visual to new focused # Update focused_index pass def handle_key(self, key, state): if key == "Tab" and state == "start": self.cycle_focus() elif self.focused_index >= 0: widget, handler = self.focusable_widgets[self.focused_index] handler(key, state) def cycle_focus(self): self.focused_index = (self.focused_index + 1) % len(self.focusable_widgets) self.focus(self.focusable_widgets[self.focused_index][0]) ``` ## What This Is NOT This is **not** a C++ engine feature. It's a demo showing that: 1. McRogueFace provides sufficient primitives 2. Focus can be implemented in pure Python 3. Developers can customize focus behavior for their game If patterns emerge that would benefit from C++ support, that's a future issue. ## Dependencies - **Blocked by**: Callback Naming Standardization (NEW) - need on_click, on_enter - **Blocked by**: Mouse Enter/Exit Events (NEW) - for hover-to-focus variant ## Related Issues - Demonstrates: #45 (Accessibility) - focus is key to keyboard navigation - Uses: All the new mouse event infrastructure
john added the
Demo Target
system:input
priority:tier2-foundation
workflow:blocked
labels 2025-11-27 19:31:04 +00:00
john added this to the Cursor, Grid, and Callback project 2025-11-27 19:31:09 +00:00
Sign in to join this conversation.
No Milestone
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: john/McRogueFace#143
No description provided.