11
22from abc import ABC , abstractmethod
33from rlc .layout import Layout , Direction , FIT , Padding
4+ from typing import Dict
5+ from dataclasses import dataclass , field
46from rlc .text import Text
57
68_renderer_registry = {} # maps class name → class
@@ -9,14 +11,14 @@ def register_renderer(cls):
911 _renderer_registry [cls .__name__ ] = cls
1012 return cls
1113
14+ @dataclass (kw_only = True )
1215class Renderable (ABC ):
1316 """
1417 Base abstract renderer type.
1518 Each subclasss knows how to convert its types object into a Layout tree.
1619 """
17- def __init__ (self , rlc_type_name , style_policy : dict ):
18- self .rlc_type_name = rlc_type_name
19- self .style_policy = style_policy
20+ rlc_type_name : str
21+ style_policy : Dict = field (default_factory = dict )
2022
2123 def make_layout (self , direction = Direction .COLUMN , color = "white" , sizing = (FIT (), FIT ()), logger = None , padding = Padding (2 ,2 ,2 ,2 ), border = 3 , child_gap = 5 ) -> Layout :
2224 layout = Layout (sizing = sizing , direction = direction , color = color , padding = padding , border = border , child_gap = child_gap )
@@ -53,7 +55,7 @@ def update(self, layout, obj, elapsed_time: float = 0.0):
5355
5456 def __call__ (self , obj , parent_binding = None , ** kwds ):
5557 layout = self .build_layout (obj = obj , ** kwds )
56-
58+
5759 # If build_layout didn't set binding, ensure we add it
5860 if layout .binding is None :
5961 layout .binding = {
@@ -75,52 +77,7 @@ def __call__(self, obj, parent_binding=None, **kwds):
7577 child .binding ["parent" ] = layout .binding
7678
7779 return layout
78-
79-
80- # ---------- PUBLIC SERIALIZATION API ----------
81- def to_dict (self ):
82- return {
83- "renderer_class" : self .__class__ .__name__ ,
84- "rlc_type_name" : self .rlc_type_name ,
85- "data" : self ._to_dict_data (),
86- "style_policy" : self .style_policy
87- }
88-
89- @staticmethod
90- def from_dict (d ):
91- cls_name = d ["renderer_class" ]
92- if cls_name not in _renderer_registry :
93- raise ValueError (f"Unknown renderer class '{ cls_name } '" )
94- cls = _renderer_registry [cls_name ]
95- return cls ._from_dict_data (
96- d ["rlc_type_name" ],
97- d ["data" ]
98- )
99-
100- # ---------- SUBCLASS HOOKS ----------
101- @abstractmethod
102- def _to_dict_data (self ):
103- """Return subclass-specific dict data."""
104- pass
105-
106- @classmethod
107- @abstractmethod
108- def _from_dict_data (cls , rlc_type_name , data ):
109- """Recreate subclass instance."""
110- pass
111-
112- def print_tree (self , indent : int = 0 ):
113- prefix = " " * indent
114- print (f"{ prefix } { self .__class__ .__name__ } ({ self ._describe_self ()} )" )
115- for child in self ._iter_children ():
116- if isinstance (child , Renderable ):
117- child .print_tree (indent + 1 )
118- else :
119- print (f"{ ' ' * (indent + 1 )} { child } " )
12080
121- def _describe_self (self ) -> str :
122- """Subclasses can override to show additional info."""
123- return self .rlc_type_name + str (self .style_policy )
12481
12582 def _iter_children (self ):
12683 """Return iterable of child renderers, if any. Override per subclass."""
0 commit comments