Add non-functional menu bar

This commit is contained in:
Isaiah Odhner 2023-04-12 20:49:16 -04:00
parent fd4944c296
commit b779059208
4 changed files with 126 additions and 0 deletions

2
__init__.py Normal file
View File

@ -0,0 +1,2 @@
# For relative imports to work in Python 3.6
import os, sys; sys.path.append(os.path.dirname(os.path.realpath(__file__)))

83
menus.py Normal file
View File

@ -0,0 +1,83 @@
import re
from enum import Enum
from typing import List
from textual import events
from textual.message import Message, MessageTarget
from textual.app import ComposeResult
from textual.containers import Container, Horizontal, Vertical
from textual.geometry import Offset, Region, Size
from textual.reactive import var, reactive
from textual.widget import Widget
from textual.widgets import Button, Static
def to_snake_case(name):
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
name = re.sub('__([A-Z])', r'_\1', name)
name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name)
return name.lower()
class Menu(Container):
"""A menu widget."""
items = var([])
focus_index = var(0)
def __init__(self, items: List[str], **kwargs) -> None:
"""Initialize a menu."""
super().__init__(**kwargs)
self.add_class("menu")
self.items = items
for item in items:
if not hasattr(item, "id"):
item.id = "menu_item_" + to_snake_case(item.name)
def compose(self) -> ComposeResult:
"""Define widget structure."""
for item in self.items:
if item.type == "separator":
yield Static("" * 20, classes="menu_separator")
else:
yield Button(item.name, id=item.id, classes="menu_item")
def on_key(self, event: events.Key) -> None:
"""Called when the user presses a key."""
if event.key == "up":
self.focus_index -= 1
if self.focus_index < 0:
self.focus_index = len(self.items) - 1
elif event.key == "down":
self.focus_index += 1
if self.focus_index >= len(self.items):
self.focus_index = 0
elif event.key == "enter":
if self.items[self.focus_index].action:
self.items[self.focus_index].action()
# elif self.items[self.focus_index].submenu:
# self.items[self.focus_index].submenu.open()
class MenuBar(Menu):
"""A menu bar widget."""
def __init__(self, items: List[str], **kwargs) -> None:
"""Initialize a menu bar."""
super().__init__(items, **kwargs)
self.add_class("menu_bar")
class MenuItem:
"""A menu item."""
def __init__(self, name: str, action = None, type: str = "item", submenu = None) -> None:
"""Initialize a menu item."""
self.name = name
self.action = action
self.type = type
self.submenu = submenu
class Separator(MenuItem):
"""A menu separator."""
def __init__(self) -> None:
"""Initialize a menu separator."""
super().__init__("", None, "separator")

View File

@ -101,3 +101,23 @@ Button {
width: 100%;
height: 100%;
}
/* MenuBar { */
.menu_bar {
layout: horizontal;
background: $panel;
height: auto;
dock: top;
/* border-bottom: hkey $panel-darken-2; */
}
/* MenuItem { */
.menu_item {
width: auto;
height: auto;
}
.menu Button {
border: none;
height: 3;
/* This seems to be the only way to get the button to shrink? */
max-width: 8;
}

View File

@ -16,6 +16,7 @@ from textual.reactive import var, reactive
from textual.strip import Strip
from textual.widget import Widget
from textual.widgets import Button, Static
from menus import MenuBar, Menu, MenuItem, Separator
class Tool(Enum):
"""The tools available in the Paint app."""
@ -581,6 +582,26 @@ class PaintApp(App):
def compose(self) -> ComposeResult:
"""Add our widgets."""
with Container(id="paint"):
yield MenuBar([
MenuItem("File", submenu=Menu([
# MenuItem("New", self.file_new),
# MenuItem("Open", self.file_open),
MenuItem("Save", self.file_save),
# MenuItem("Save As", self.file_save_as),
# MenuItem("Exit", self.exit),
])),
MenuItem("Edit", submenu=Menu([
MenuItem("Undo", self.undo),
MenuItem("Redo", self.redo),
])),
MenuItem("View", submenu=Menu([
# MenuItem("Tools", self.toggle_tools_box),
# MenuItem("Colors", self.toggle_colors_box),
])),
MenuItem("Image"),
MenuItem("Colors"),
MenuItem("Help"),
])
yield Container(
ToolsBox(),
Container(