Skip to content

Commit

Permalink
Reformat, started components, moved to ubuntu
Browse files Browse the repository at this point in the history
  • Loading branch information
ken-morel committed Dec 20, 2024
1 parent f5fa1ce commit a6081a4
Show file tree
Hide file tree
Showing 4 changed files with 314 additions and 53 deletions.
58 changes: 44 additions & 14 deletions src/taktk/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,53 @@
import efus.namespace
import typing

from efus.types import ENil as Nil
from efus.types import ENilType as NilT

from pyoload import annotate


class TkComponent(efus.component.Component):
namespace: efus.namespace.Namespace
widget_config = ()
has_parent = True

def __init_subclass__(cls):
if hasattr(cls, "ParamsClass"):
cls.params = efus.component.CompParams.from_class(cls.ParamsClass)
cls.params = efus.component.CompParams.from_class(
cls.ParamsClass, cls.__name__
)

def prerender(self):
self.outlet = self.inlet = self.widget = self.WidgetClass(
**self.filter_widget_config()
)
if self.parent is not None and self.has_parent:
self.outlet = self.inlet = self.widget = self.WidgetClass(
self.parent.outlet, **self.filter_widget_config()
)
else:
self.outlet = self.inlet = self.widget = self.WidgetClass(
**self.filter_widget_config()
)
if self.parent is not None:
self.parent.child_geometry(self, self.inlet, self.args["pos"])
return self.widget

def filter_widget_config(self):
return {
k: v
for k, v in self.args.items()
if k in self.widget_config and v is not efus.types.ENil
} | {
a: self.args[k]
for k, a in self.widget_config_aliasses.items()
if self.args[k] is not efus.types.ENil
}
try:
return {
k: v
for k, v in self.args.items()
if k in self.widget_config and v is not efus.types.ENil
} | {
a: self.args[k]
for k, a in self.widget_config_aliasses.items()
if self.args[k] is not efus.types.ENil
}
except KeyError as e:
raise KeyError(
f"Key {e!s} not found. Please check {type(self).__name__}'s"
+ " configs and aliasses and make sure they are in the "
+ "ClassParams."
) from e

@classmethod
@annotate
Expand All @@ -40,10 +58,22 @@ def create(
attrs: dict[str, efus.types.EObject],
pc: typing.Optional[efus.component.Component],
) -> efus.component.Component:
print("received", attrs, "in", id(attrs))
return cls(np, cls.params.bind(attrs, np), pc)

def child_geometry(self, child, widget, args):
if args.get("pack"):
args = args.copy()
args.pop("pack")
widget.pack(**args)
widget.pack(**{k: v for k, v in args.items() if v is not Nil})
print("did> ", end="")
print("gridded", child, widget, args)

def update(self):
self.widget.configure(**self.filter_widget_config())


class PosSpec:
pack: bool = False
side: str | NilT
fill: str | NilT
154 changes: 135 additions & 19 deletions src/taktk/components/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,52 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""

from .. import menu
from efus.types import Binding
from efus.types import ENil as Nil
from efus.types import ENilType as NilT
from efus.types import ESize

from .. import component
from .. import subscribe


import ttkbootstrap
import typing


class Menu(component.TkComponent):
class ParamsClass:
structure: dict
translation: str

def prerender(self):
self.menu = menu.Menu(
self.args["structure"],
None
if self.args["translation"] is Nil
else self.args["translation"],
)
self.menu.toplevel(self.parent.widget)
return self.menu

from ttkbootstrap import Label
from ttkbootstrap import Window
def update(self):
self.menu.update()


class Window(component.TkComponent):
class ParamsClass:
title: NilT | str = Nil
themename: NilT | str = Nil
iconphoto: NilT | str = Nil
size: NilT | ESize = Nil
pos: NilT | ESize = Nil
minsize: NilT | ESize = Nil
maxsize: NilT | ESize = Nil
hdpi: NilT | bool = Nil
overrideredirect: NilT | bool = Nil
alpha: NilT | float = Nil
title: str | NilT
themename: str | NilT
iconphoto: str | NilT
size: ESize | NilT
pos: ESize | NilT
minsize: ESize | NilT
maxsize: ESize | NilT
hdpi: bool | NilT
overrideredirect: bool | NilT
alpha: float | NilT
menu: dict | NilT

widget_config = (
"title",
Expand All @@ -52,16 +74,110 @@ class ParamsClass:
)
widget_config_aliasses = {"pos": "position"}

WidgetClass = Window
WidgetClass = ttkbootstrap.Window


class Label(component.TkComponent):
class ParamsClass:
bootstyle: NilT | str = Nil
text: NilT | str = Nil
pos: dict = {}
bootstyle: str | NilT
text: str | NilT
pos = component.PosSpec
padx: int | NilT
pady: int | NilT
foreground: str | NilT
background: str | NilT

widget_config = (
"bootstyle",
"text",
"foreground",
"background",
"padx",
"pady",
)
widget_config_aliasses = {}

WidgetClass = ttkbootstrap.Label


class Frame(component.TkComponent):
class ParamsClass:
bootstyle: str | NilT
padding: int | NilT
pos = component.PosSpec
padding: int | NilT
borderwidth: int | NilT
relief: str | NilT
width: int | NilT
height: int | NilT
font: str | NilT

widget_config = ("bootstyle", "text")
widget_config = (
"bootstyle",
"padding",
"borderwidth",
"relief",
"width",
"height",
"font",
)
widget_config_aliasses = {}

WidgetClass = Label
WidgetClass = ttkbootstrap.Frame


class Button(component.TkComponent):
class ParamsClass:
weight: dict = {}
pos = component.PosSpec
bootstyle: str | NilT
text: str | NilT
command: typing.Callable | NilT
padx: int | NilT
pady: int | NilT
image: NilT
compound: str | NilT
background: str | NilT
foreground: str | NilT

widget_config = (
"bootstyle",
"text",
"command",
"padx",
"pady",
"fg",
"bg",
"image",
"compound",
)
widget_config_aliasses = {}

WidgetClass = ttkbootstrap.Button


class Entry(component.TkComponent):
class ParamsClass:
pos = component.PosSpec
bootstyle: str | NilT
width: int | NilT
var: Binding | NilT

def prerender(self):
if self.args["var"] is not Nil:
self.args["textvariable"] = subscribe.TkStringBinding(
self.args["var"]
)
self.widget_config = self.widget_config + ("textvariable",)
widget = super().prerender()
# if self.args["var"] is not Nil:
# widget.setvar()
return widget

widget_config = ("bootstyle", "width")
widget_config_aliasses = {}

WidgetClass = ttkbootstrap.Entry


__all__ = [x for x in dir() if not x.startswith("_")]
54 changes: 34 additions & 20 deletions src/taktk/menu.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,40 @@
from logging import getLogger
"""Class to manage tk menu."""
from .component import TkComponent

from efus.subscribe import Subscriber
from pyoload import annotate
from ttkbootstrap import Menu as ttkMenu

log = getLogger(__name__)
from typing import Any
from typing import Optional


@annotate
class Menu:
menu = None
menu_structure = None
"""Taktk tk menu interface class."""

menu: Optional[ttkMenu] = None
menu_structure: Optional[dict] = None
subscriber: Subscriber

def __init__(self, structure, translations="menu"):
def __init__(self, structure: dict, translations: Optional[str] = None):
"""Create a taltl tk menu."""
from .dictionary import Dictionary

Dictionary.subscribe(self.update)
self.subscriber = Subscriber()
self.subscribe.subscribe_to(Dictionary)
self.structure = structure
self.translations = translations

def create(self):
def render(self):
"""Render the menu to tk menu."""
menubar = ttkMenu()
Menu.build_submenus(menubar, self.eval_structure())
Menu._build_submenus(menubar, self._eval_structure())
self.menu = menubar
self.menu_structure = self.eval_structure()
self.menu_structure = self._eval_structure()
return menubar

@classmethod
def build_submenus(cls, menu, structure):
def _build_submenus(cls, menu, structure):
from .dictionary import Translation
from .writeable import Writeable

Expand All @@ -40,7 +50,7 @@ def build_submenus(cls, menu, structure):
elif isinstance(contents, dict): # a submenu
submenu = ttkMenu(menu)
menu.add_cascade(menu=submenu, label=name, underline=idx)
cls.build_submenus(submenu, contents)
cls._build_submenus(submenu, contents)
elif isinstance(contents, Writeable):
val = contents.get()
if isinstance(val, bool):
Expand All @@ -54,17 +64,20 @@ def build_submenus(cls, menu, structure):
f"wrong menu dict field: {label!r}:{contents!r}",
)

def post(self, xpos, ypos):
if self.menu_structure != self.eval_structure():
@annotate
def post(self, xpos: int, ypos: int):
"""Post the menu at xpos and ypos."""
if self.menu_structure != self._eval_structure():
self.create()
self.menu.post(xpos, ypos)

def toplevel(self, root):
if self.menu_structure != self.eval_structure():
def toplevel(self, root: Any):
"""Attach the menu to the specified toplevel."""
if self.menu_structure != self._eval_structure():
self.create()
root["menu"] = self.menu

def __getitem__(self, item):
def __getitem__(self, item: str):
obj = self.structure
for x in item.split("/"):
obj = obj[x]
Expand All @@ -85,10 +98,11 @@ def __setitem__(self, item, val):
return val

def update(self):
self.menu.delete(0, 'end')
self.build_submenus(self.menu, self.eval_structure())
"""Update the tkinter menu."""
self.menu.delete(0, "end")
self._build_submenus(self.menu, self._eval_structure())

def eval_structure(self):
def _eval_structure(self):
def build_sub(alias, structure):
ret = {}
for child_name, child_contents in structure.items():
Expand Down
Loading

0 comments on commit a6081a4

Please sign in to comment.