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 import re
translations = {} 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): def load_language(language_code: str):
"""Load a language from the translations directory.""" """Load a language from the translations directory."""
@ -16,6 +23,7 @@ def load_language(language_code: str):
end = js.rfind("}") end = js.rfind("}")
# parse the JSON object # parse the JSON object
translations = json.loads(js[start:end + 1]) translations = json.loads(js[start:end + 1])
current_language = language_code
except FileNotFoundError: except FileNotFoundError:
print(f"Could not find language file for '{language_code}'.") print(f"Could not find language file for '{language_code}'.")
except json.decoder.JSONDecodeError as e: 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.reactive import var, reactive
from textual.widget import Widget from textual.widget import Widget
from textual.widgets import Button, Static 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): def to_snake_case(name):
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', 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 = parent_menu
self.parent_menu_item = parent_menu_item self.parent_menu_item = parent_menu_item
self.add_class("menu_popup") 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) 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 # Find the widest label
max_width = 0 max_width = 0