draft tutorial revisions

This commit is contained in:
John McCardle 2026-01-03 11:01:10 -05:00
commit 48359b5a48
70 changed files with 6216 additions and 28 deletions

View file

@ -0,0 +1,159 @@
"""McRogueFace - Selection Menu Widget (enhanced)
Documentation: https://mcrogueface.github.io/cookbook/ui_menu
Repository: https://github.com/jmccardle/McRogueFace/blob/master/docs/cookbook/ui/ui_menu_enhanced.py
This code is extracted from the McRogueFace documentation and can be
run directly with: ./mcrogueface path/to/this/file.py
"""
import mcrfpy
class MenuBar:
"""Horizontal menu bar with dropdown submenus."""
def __init__(self, y=0, items=None):
"""
Create a menu bar.
Args:
y: Y position (usually 0 for top)
items: List of dicts with 'label' and 'options' keys
"""
self.y = y
self.items = items or []
self.selected_item = 0
self.dropdown_open = False
self.dropdown_selected = 0
self.item_width = 100
self.height = 30
# Main bar frame
self.bar = mcrfpy.Frame(0, y, 1024, self.height)
self.bar.fill_color = mcrfpy.Color(50, 50, 70)
self.bar.outline = 0
# Item captions
self.item_captions = []
for i, item in enumerate(items):
cap = mcrfpy.Caption(
item['label'],
mcrfpy.default_font,
10 + i * self.item_width,
y + 7
)
cap.fill_color = mcrfpy.Color(200, 200, 200)
self.item_captions.append(cap)
# Dropdown panel (hidden initially)
self.dropdown = None
self.dropdown_captions = []
def _update_highlight(self):
"""Update visual selection on bar."""
for i, cap in enumerate(self.item_captions):
if i == self.selected_item and self.dropdown_open:
cap.fill_color = mcrfpy.Color(255, 255, 100)
else:
cap.fill_color = mcrfpy.Color(200, 200, 200)
def _show_dropdown(self, ui):
"""Show dropdown for selected item."""
# Remove existing dropdown
self._hide_dropdown(ui)
item = self.items[self.selected_item]
options = item.get('options', [])
if not options:
return
x = 5 + self.selected_item * self.item_width
y = self.y + self.height
width = 150
height = len(options) * 25 + 10
self.dropdown = mcrfpy.Frame(x, y, width, height)
self.dropdown.fill_color = mcrfpy.Color(40, 40, 60, 250)
self.dropdown.outline = 1
self.dropdown.outline_color = mcrfpy.Color(80, 80, 100)
ui.append(self.dropdown)
self.dropdown_captions = []
for i, opt in enumerate(options):
cap = mcrfpy.Caption(
opt['label'],
mcrfpy.default_font,
x + 10,
y + 5 + i * 25
)
cap.fill_color = mcrfpy.Color(200, 200, 200)
self.dropdown_captions.append(cap)
ui.append(cap)
self.dropdown_selected = 0
self._update_dropdown_highlight()
def _hide_dropdown(self, ui):
"""Hide dropdown menu."""
if self.dropdown:
try:
ui.remove(self.dropdown)
except:
pass
self.dropdown = None
for cap in self.dropdown_captions:
try:
ui.remove(cap)
except:
pass
self.dropdown_captions = []
def _update_dropdown_highlight(self):
"""Update dropdown selection highlight."""
for i, cap in enumerate(self.dropdown_captions):
if i == self.dropdown_selected:
cap.fill_color = mcrfpy.Color(255, 255, 100)
else:
cap.fill_color = mcrfpy.Color(200, 200, 200)
def add_to_scene(self, ui):
ui.append(self.bar)
for cap in self.item_captions:
ui.append(cap)
def handle_key(self, key, ui):
"""Handle keyboard navigation."""
if not self.dropdown_open:
if key == "Left":
self.selected_item = (self.selected_item - 1) % len(self.items)
self._update_highlight()
elif key == "Right":
self.selected_item = (self.selected_item + 1) % len(self.items)
self._update_highlight()
elif key == "Return" or key == "Down":
self.dropdown_open = True
self._show_dropdown(ui)
self._update_highlight()
else:
if key == "Up":
options = self.items[self.selected_item].get('options', [])
self.dropdown_selected = (self.dropdown_selected - 1) % len(options)
self._update_dropdown_highlight()
elif key == "Down":
options = self.items[self.selected_item].get('options', [])
self.dropdown_selected = (self.dropdown_selected + 1) % len(options)
self._update_dropdown_highlight()
elif key == "Return":
opt = self.items[self.selected_item]['options'][self.dropdown_selected]
if opt.get('action'):
opt['action']()
self.dropdown_open = False
self._hide_dropdown(ui)
self._update_highlight()
elif key == "Escape":
self.dropdown_open = False
self._hide_dropdown(ui)
self._update_highlight()