## /ctk_extender/notification/position.py
from abc import ABC, abstractmethod
from EJIO.utils import SystemProperties
import customtkinter as ctk
__all__ = [
'NotificationPosition',
'get_position_strategy',
]
[документация]
class NotificationPosition(ABC):
"""Абстрактный класс стратегии позиционирования уведомлений (In-App и Desktop)."""
__slots__ = ()
[документация]
@abstractmethod
def apply_in_app(self, widget: ctk.CTkFrame, offset_y: int) -> None:
"""Применяет координаты .place() внутри главного окна."""
...
[документация]
@abstractmethod
def apply_desktop(self, window: ctk.CTkToplevel, offset_y: int, win_w: int, win_h: int) -> None:
"""Применяет координаты .geometry() на рабочем столе ОС."""
...
class TopRight(NotificationPosition):
__slots__ = ()
def apply_in_app(self, widget: ctk.CTkFrame, offset_y: int) -> None:
widget.place(relx=0.98, y=offset_y, anchor="ne")
def apply_desktop(self, window: ctk.CTkToplevel, offset_y: int, win_w: int, win_h: int) -> None:
scr_w = SystemProperties.screen_width
x = scr_w - win_w - 20
window.geometry(f"{win_w}x{win_h}+{x}+{offset_y}")
class TopLeft(NotificationPosition):
__slots__ = ()
def apply_in_app(self, widget: ctk.CTkFrame, offset_y: int) -> None:
widget.place(relx=0.02, y=offset_y, anchor="nw")
def apply_desktop(self, window: ctk.CTkToplevel, offset_y: int, win_w: int, win_h: int) -> None:
window.geometry(f"{win_w}x{win_h}+20+{offset_y}")
class BottomRight(NotificationPosition):
__slots__ = ()
def apply_in_app(self, widget: ctk.CTkFrame, offset_y: int) -> None:
widget.place(relx=0.98, rely=0.95, y=-offset_y, anchor="se")
def apply_desktop(self, window: ctk.CTkToplevel, offset_y: int, win_w: int, win_h: int) -> None:
scr_w = SystemProperties.screen_width
scr_h = SystemProperties.screen_height
x = scr_w - win_w - 20
y = scr_h - 60 - win_h - offset_y
window.geometry(f"{win_w}x{win_h}+{x}+{y}")
class BottomLeft(NotificationPosition):
__slots__ = ()
def apply_in_app(self, widget: ctk.CTkFrame, offset_y: int) -> None:
widget.place(relx=0.02, rely=0.95, y=-offset_y, anchor="sw")
def apply_desktop(self, window: ctk.CTkToplevel, offset_y: int, win_w: int, win_h: int) -> None:
scr_h = SystemProperties.screen_height
y = scr_h - 60 - win_h - offset_y
window.geometry(f"{win_w}x{win_h}+20+{y}")
class MidTopRight(NotificationPosition):
__slots__ = ()
def apply_in_app(self, widget: ctk.CTkFrame, offset_y: int) -> None:
widget.place(relx=0.98, rely=0.25, y=offset_y, anchor="ne")
def apply_desktop(self, window: ctk.CTkToplevel, offset_y: int, win_w: int, win_h: int) -> None:
scr_w = SystemProperties.screen_width
scr_h = SystemProperties.screen_height
x = scr_w - win_w - 20
y = int(scr_h * 0.25) + offset_y
window.geometry(f"{win_w}x{win_h}+{x}+{y}")
class MidTopLeft(NotificationPosition):
__slots__ = ()
def apply_in_app(self, widget: ctk.CTkFrame, offset_y: int) -> None:
widget.place(relx=0.02, rely=0.25, y=offset_y, anchor="nw")
def apply_desktop(self, window: ctk.CTkToplevel, offset_y: int, win_w: int, win_h: int) -> None:
scr_h = SystemProperties.screen_height
y = int(scr_h * 0.25) + offset_y
window.geometry(f"{win_w}x{win_h}+20+{y}")
# Локальная рантайм-карта маппинга строк в стратегии
_POSITION_MAP: dict[str, NotificationPosition] = {
"top_right": TopRight(),
"top_left": TopLeft(),
"bottom_right": BottomRight(),
"bottom_left": BottomLeft(),
"mid_top_right": MidTopRight(),
"mid_top_left": MidTopLeft()
}
[документация]
def get_position_strategy(name: str) -> NotificationPosition:
"""Извлекает стратегию по её текстовому маркеру."""
return _POSITION_MAP.get(name.lower(), TopRight())