started work on right click menus

This commit is contained in:
SpookyDervish
2025-10-30 20:21:41 +11:00
parent 806957ecb0
commit a5ee621b46
3 changed files with 152 additions and 2 deletions

119
context_menu.py Normal file
View File

@@ -0,0 +1,119 @@
# totally not stolen from my code for my chat app Portal ;)
from __future__ import annotations
from textual.screen import ModalScreen
from textual.containers import Container
from textual.widgets import Static
from textual.geometry import Offset
from textual.message import Message
from textual.visual import VisualType
from textual import on, events
class NoSelectStatic(Static):
"""This class is used in window.py and windowbar.py to create buttons."""
@property
def allow_select(self) -> bool:
return False
class ButtonStatic(NoSelectStatic):
"""This class is used in window.py, windowbar.py, and switcher.py to create buttons."""
class Pressed(Message):
def __init__(self, button: ButtonStatic) -> None:
super().__init__()
self.button = button
@property
def control(self) -> ButtonStatic:
return self.button
def __init__(
self,
content: VisualType = "",
*,
expand: bool = False,
shrink: bool = False,
markup: bool = True,
name: str | None = None,
id: str | None = None,
classes: str | None = None,
disabled: bool = False,
) -> None:
super().__init__(
content=content,
expand=expand,
shrink=shrink,
markup=markup,
name=name,
id=id,
classes=classes,
disabled=disabled,
)
self.click_started_on: bool = False
def on_mouse_down(self, event: events.MouseDown) -> None:
self.add_class("pressed")
self.click_started_on = True
def on_mouse_up(self, event: events.MouseUp) -> None:
self.remove_class("pressed")
if self.click_started_on:
self.post_message(self.Pressed(self))
self.click_started_on = False
def on_leave(self, event: events.Leave) -> None:
self.remove_class("pressed")
self.click_started_on = False
class ContextMenu(ModalScreen):
DEFAULT_CSS = """
ContextMenu {
background: $background 0%;
align: left top;
}
#menu_container {
padding: 0 1;
background: $surface;
width: 21;
border: hkey $panel;
& > ButtonStatic {
content-align: left middle;
&:hover { background: $panel-lighten-2; }
&.pressed { background: $primary; }
}
}
"""
def __init__(self, options: list[str], offset: Offset):
super().__init__()
self.options = options
self.mouse_offset = offset
def on_mouse_up(self, event: events.MouseUp):
if not self.query_one("#menu_container").region.contains(event.screen_x, event.screen_y):
self.dismiss(None)
@on(ButtonStatic.Pressed)
async def thingy(self, event: ButtonStatic.Pressed):
self.dismiss(event.button.content)
def compose(self):
with Container(id="menu_container"):
for option in self.options:
if isinstance(option, str):
yield ButtonStatic(option)
else:
yield option
def on_mount(self):
menu_container = self.query_one("#menu_container")
menu_container.styles.height = len(menu_container.children) + 2
menu_container.offset = self.mouse_offset

31
directory_tree_custom.py Normal file
View File

@@ -0,0 +1,31 @@
from textual.widgets import DirectoryTree, Rule
from textual.widgets.tree import TreeNode
from textual.events import MouseDown
from context_menu import ContextMenu, NoSelectStatic
class CustomDirectoryTree(DirectoryTree):
def __init__(self, path, *, name = None, id = None, classes = None, disabled = False):
super().__init__(path, name=name, id=id, classes=classes, disabled=disabled)
self.right_clicked_node: TreeNode | None = None
def context_menu_chosen(self, result):
self.right_clicked_node = None
def on_mouse_down(self, event: MouseDown):
if event.button != 3 or not "line" in event.style.meta:
return
selected_node = self.get_node_at_line(event.style.meta["line"])
self.right_clicked_node = selected_node
options = None
if self._safe_is_dir(self.right_clicked_node.data.path):
options = ["New Folder", "New File", NoSelectStatic(f'[d]{"-" * 17}[/]'), "Delete", "Rename", "Open"]
else:
options = ["Delete", "Rename", "Open"]
self.app.push_screen(ContextMenu(
[NoSelectStatic(f"[b]{self.right_clicked_node.label}[/]"), NoSelectStatic(f'[d]{"-" * 17}[/]')] + options,
event.screen_offset
), self.context_menu_chosen)

View File

@@ -12,11 +12,11 @@ from assets.theme_mappings import theme_mappings
from plugin_loader import PluginLoader
from settings import SettingsScreen
from settings_store import ConfigHandler
from directory_tree_custom import CustomDirectoryTree
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import subprocess
import os
@@ -56,7 +56,7 @@ class Berry(App):
with ContentSwitcher(initial="files", id="sidebar-switcher"):
with Vertical(id="files"):
yield Static("EXPLORER")
yield DirectoryTree(self.path, id="directory")
yield CustomDirectoryTree(self.path, id="directory")
with Vertical(id="editor"):
first_tab = Tab("New File")