Position submenu

This commit is contained in:
Isaiah Odhner 2023-04-19 00:09:40 -04:00
parent 4cbafea3cb
commit 0ee058216e
2 changed files with 58 additions and 2 deletions

View File

@ -3,6 +3,13 @@ import json
import re
translations = {}
current_language = "en"
def get_direction() -> str:
"""Get the text direction for the current language."""
if current_language in ["ar", "he"]:
return "rtl"
return "ltr"
def load_language(language_code: str):
"""Load a language from the translations directory."""
@ -16,6 +23,7 @@ def load_language(language_code: str):
end = js.rfind("}")
# parse the JSON object
translations = json.loads(js[start:end + 1])
current_language = language_code
except FileNotFoundError:
print(f"Could not find language file for '{language_code}'.")
except json.decoder.JSONDecodeError as e:

View File

@ -9,7 +9,7 @@ from textual.geometry import Offset, Region, Size
from textual.reactive import var, reactive
from textual.widget import Widget
from textual.widgets import Button, Static
from localization.i18n import markup_hotkey
from localization.i18n import markup_hotkey, get_direction
def to_snake_case(name):
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
@ -81,7 +81,55 @@ class Menu(Container):
self.parent_menu = parent_menu
self.parent_menu_item = parent_menu_item
self.add_class("menu_popup")
if parent_menu.has_class("menu_bar"):
self.styles.offset = (parent_menu_item.region.x, parent_menu_item.region.y + parent_menu_item.region.height)
else:
# JS code for reference
# https://github.com/1j01/os-gui/blob/bb4df0f0c26969c089858118130975cd137cdac8/MenuBar.js#L618-L644
# submenu_popup_el corresponds to self
# submenu_popup_rect corresponds to self.region
# rect corresponds to parent_menu_item.region
# scroll offset doesn't apply here
# const rect = item_el.getBoundingClientRect();
# let submenu_popup_rect = submenu_popup_el.getBoundingClientRect();
# submenu_popup_el.style.left = `${(get_direction() === "rtl" ? rect.left - submenu_popup_rect.width : rect.right) + window.scrollX}px`;
# submenu_popup_el.style.top = `${rect.top + window.scrollY}px`;
# submenu_popup_rect = submenu_popup_el.getBoundingClientRect();
# if (get_direction() === "rtl") {
# if (submenu_popup_rect.left < 0) {
# submenu_popup_el.style.left = `${rect.right}px`;
# submenu_popup_rect = submenu_popup_el.getBoundingClientRect();
# if (submenu_popup_rect.right > innerWidth) {
# submenu_popup_el.style.left = `${innerWidth - submenu_popup_rect.width}px`;
# }
# }
# } else {
# if (submenu_popup_rect.right > innerWidth) {
# submenu_popup_el.style.left = `${rect.left - submenu_popup_rect.width}px`;
# submenu_popup_rect = submenu_popup_el.getBoundingClientRect();
# if (submenu_popup_rect.left < 0) {
# submenu_popup_el.style.left = "0";
# }
# }
# }
rect = parent_menu_item.region
self.styles.offset = (
rect.x - self.region.width if get_direction() == "rtl" else rect.x + rect.width,
rect.y
)
if get_direction() == "rtl":
if self.region.x < 0:
self.styles.offset = (rect.x + rect.width, rect.y)
if self.region.x + self.region.width > self.screen.size.width:
self.styles.offset = (self.screen.size.width - self.region.width, rect.y)
else:
if self.region.x + self.region.width > self.screen.size.width:
self.styles.offset = (rect.x - self.region.width, rect.y)
if self.region.x < 0:
self.styles.offset = (0, rect.y)
# Find the widest label
max_width = 0