@@ -450,6 +450,7 @@ def __init__(
450
450
451
451
self ._styles_cache = StylesCache ()
452
452
self ._rich_style_cache : dict [tuple [str , ...], tuple [Style , Style ]] = {}
453
+ self ._visual_style_cache : dict [tuple [str , ...], VisualStyle ] = {}
453
454
454
455
self ._tooltip : RenderableType | None = None
455
456
"""The tooltip content."""
@@ -1043,7 +1044,7 @@ def get_component_rich_style(self, *names: str, partial: bool = False) -> Style:
1043
1044
1044
1045
return partial_style if partial else style
1045
1046
1046
- def get_visual_style (self , component_classes : Iterable [ str ] ) -> VisualStyle :
1047
+ def get_visual_style (self , * component_classes : str ) -> VisualStyle :
1047
1048
"""Get the visual style for the widget, including any component styles.
1048
1049
1049
1050
Args:
@@ -1053,46 +1054,51 @@ def get_visual_style(self, component_classes: Iterable[str]) -> VisualStyle:
1053
1054
A Visual style instance.
1054
1055
1055
1056
"""
1056
- background = Color (0 , 0 , 0 , 0 )
1057
- color = Color (255 , 255 , 255 , 0 )
1058
-
1059
- style = Style ()
1060
- opacity = 1.0
1061
-
1062
- def iter_styles () -> Iterable [StylesBase ]:
1063
- """Iterate over the styles from the DOM and additional components styles."""
1064
- for node in reversed (self .ancestors_with_self ):
1065
- yield node .styles
1066
- for name in component_classes :
1067
- yield node .get_component_styles (name )
1068
-
1069
- for styles in iter_styles ():
1070
- has_rule = styles .has_rule
1071
- opacity *= styles .opacity
1072
- if has_rule ("background" ):
1073
- text_background = background + styles .background .tint (
1074
- styles .background_tint
1075
- )
1076
- background += (
1077
- styles .background .tint (styles .background_tint )
1078
- ).multiply_alpha (opacity )
1079
- else :
1080
- text_background = background
1081
- if has_rule ("color" ):
1082
- color = styles .color
1083
- style += styles .text_style
1084
- if has_rule ("auto_color" ) and styles .auto_color :
1085
- color = text_background .get_contrast_text (color .a )
1086
-
1087
- visual_style = VisualStyle (
1088
- background ,
1089
- color ,
1090
- bold = style .bold ,
1091
- dim = style .dim ,
1092
- italic = style .italic ,
1093
- underline = style .underline ,
1094
- strike = style .strike ,
1095
- )
1057
+ if (
1058
+ visual_style := self ._visual_style_cache .get (component_classes , None )
1059
+ ) is None :
1060
+ # TODO: cache this?
1061
+ background = Color (0 , 0 , 0 , 0 )
1062
+ color = Color (255 , 255 , 255 , 0 )
1063
+
1064
+ style = Style ()
1065
+ opacity = 1.0
1066
+
1067
+ def iter_styles () -> Iterable [StylesBase ]:
1068
+ """Iterate over the styles from the DOM and additional components styles."""
1069
+ for node in reversed (self .ancestors_with_self ):
1070
+ yield node .styles
1071
+ for name in component_classes :
1072
+ yield node .get_component_styles (name )
1073
+
1074
+ for styles in iter_styles ():
1075
+ has_rule = styles .has_rule
1076
+ opacity *= styles .opacity
1077
+ if has_rule ("background" ):
1078
+ text_background = background + styles .background .tint (
1079
+ styles .background_tint
1080
+ )
1081
+ background += (
1082
+ styles .background .tint (styles .background_tint )
1083
+ ).multiply_alpha (opacity )
1084
+ else :
1085
+ text_background = background
1086
+ if has_rule ("color" ):
1087
+ color = styles .color
1088
+ style += styles .text_style
1089
+ if has_rule ("auto_color" ) and styles .auto_color :
1090
+ color = text_background .get_contrast_text (color .a )
1091
+
1092
+ visual_style = VisualStyle (
1093
+ background ,
1094
+ color ,
1095
+ bold = style .bold ,
1096
+ dim = style .dim ,
1097
+ italic = style .italic ,
1098
+ underline = style .underline ,
1099
+ strike = style .strike ,
1100
+ )
1101
+ self ._visual_style_cache [component_classes ] = visual_style
1096
1102
1097
1103
return visual_style
1098
1104
@@ -4270,6 +4276,8 @@ async def broker_event(self, event_name: str, event: events.Event) -> bool:
4270
4276
4271
4277
def notify_style_update (self ) -> None :
4272
4278
self ._rich_style_cache .clear ()
4279
+ self ._visual_style_cache .clear ()
4280
+ super ().notify_style_update ()
4273
4281
4274
4282
async def _on_mouse_down (self , event : events .MouseDown ) -> None :
4275
4283
await self .broker_event ("mouse.down" , event )
0 commit comments