109 lines
3.2 KiB
Python
109 lines
3.2 KiB
Python
import os
|
|
import re
|
|
from tkinter import TclError
|
|
|
|
import customtkinter as ctk
|
|
|
|
try:
|
|
import arabic_reshaper
|
|
from bidi.algorithm import get_display
|
|
except ImportError:
|
|
arabic_reshaper = None
|
|
get_display = None
|
|
|
|
|
|
ctk.set_appearance_mode("light")
|
|
ctk.set_default_color_theme("blue")
|
|
|
|
|
|
PRIMARY = "#175B4B"
|
|
PRIMARY_DARK = "#0E4236"
|
|
PRIMARY_SOFT = "#DFF1E8"
|
|
ACCENT = "#E8A04D"
|
|
ACCENT_DARK = "#C97E2D"
|
|
BACKGROUND = "#F5EFE7"
|
|
CARD = "#FFFDFC"
|
|
SURFACE = "#FBF7F2"
|
|
INPUT_BG = "#FFFCF8"
|
|
TEXT = "#16312A"
|
|
MUTED = "#6B7A77"
|
|
DANGER = "#B6465F"
|
|
WARNING = "#9A6C3C"
|
|
BORDER = "#E5DCCE"
|
|
|
|
KEYBOARD_BG = "#D4DCE2"
|
|
KEY_FACE = "#FFFFFF"
|
|
KEY_MUTED = "#BCC1C9"
|
|
KEY_TEXT = "#000000"
|
|
|
|
SIDEBAR = "#1B5A4A"
|
|
SIDEBAR_SOFT = "#245E4E"
|
|
|
|
FONT_BODY = "Tahoma" if os.name == "nt" else "DejaVu Sans"
|
|
FONT_TITLE = "Tahoma" if os.name == "nt" else "DejaVu Sans"
|
|
|
|
RTL_PATTERN = re.compile(r"[\u0600-\u06FF]")
|
|
|
|
|
|
def ui_text(value):
|
|
if not isinstance(value, str) or not value:
|
|
return value
|
|
if arabic_reshaper is None or get_display is None or not RTL_PATTERN.search(value):
|
|
return value
|
|
return get_display(arabic_reshaper.reshape(value))
|
|
|
|
|
|
class _RTLTextMixin:
|
|
@staticmethod
|
|
def _normalize_kwargs(kwargs):
|
|
normalized = dict(kwargs)
|
|
if "text" in normalized:
|
|
normalized["text"] = ui_text(normalized["text"])
|
|
if "placeholder_text" in normalized:
|
|
normalized["placeholder_text"] = ui_text(normalized["placeholder_text"])
|
|
if "label_text" in normalized:
|
|
normalized["label_text"] = ui_text(normalized["label_text"])
|
|
return normalized
|
|
|
|
|
|
class RTLLabel(_RTLTextMixin, ctk.CTkLabel):
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **self._normalize_kwargs(kwargs))
|
|
|
|
def configure(self, require_redraw=False, **kwargs):
|
|
return super().configure(require_redraw=require_redraw, **self._normalize_kwargs(kwargs))
|
|
|
|
|
|
class RTLButton(_RTLTextMixin, ctk.CTkButton):
|
|
def __init__(self, *args, **kwargs):
|
|
kwargs.setdefault("corner_radius", 16)
|
|
super().__init__(*args, **self._normalize_kwargs(kwargs))
|
|
|
|
def configure(self, require_redraw=False, **kwargs):
|
|
return super().configure(require_redraw=require_redraw, **self._normalize_kwargs(kwargs))
|
|
|
|
|
|
class RTLEntry(_RTLTextMixin, ctk.CTkEntry):
|
|
def __init__(self, *args, **kwargs):
|
|
kwargs.setdefault("justify", "right")
|
|
kwargs.setdefault("fg_color", INPUT_BG)
|
|
kwargs.setdefault("border_color", BORDER)
|
|
kwargs.setdefault("corner_radius", 16)
|
|
super().__init__(*args, **self._normalize_kwargs(kwargs))
|
|
|
|
def configure(self, require_redraw=False, **kwargs):
|
|
return super().configure(require_redraw=require_redraw, **self._normalize_kwargs(kwargs))
|
|
|
|
|
|
class RTLTextbox(ctk.CTkTextbox):
|
|
def insert(self, index, text, *tags):
|
|
return super().insert(index, ui_text(text), *tags)
|
|
|
|
|
|
class RTLScrollableFrame(_RTLTextMixin, ctk.CTkScrollableFrame):
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **self._normalize_kwargs(kwargs))
|
|
|
|
def configure(self, require_redraw=False, **kwargs):
|
|
return super().configure(require_redraw=require_redraw, **self._normalize_kwargs(kwargs))
|