Source code for ooodev.format.inner.partial.factory_styler

from __future__ import annotations
from typing import Any, cast, Dict, TYPE_CHECKING, Callable

from ooodev.events.args.cancel_event_args import CancelEventArgs
from ooodev.events.args.event_args import EventArgs
from ooodev.events.gbl_named_event import GblNamedEvent
from ooodev.events.style_named_event import StyleNameEvent
from ooodev.exceptions import ex as mEx
from ooodev.utils.context.lo_context import LoContext
from ooodev.format.inner.partial.factory_name_base import FactoryNameBase

if TYPE_CHECKING:
    from ooodev.loader.inst.lo_inst import LoInst
    from ooodev.format.proto.style_t import StyleT
else:
    LoInst = Any
    StyleT = Any


[docs]class FactoryStyler(FactoryNameBase): """ Class for Generic Styler. This class is generally used as a helper to create partial classes that can style components, such as, ``ooodev.format.inner.partial.font.font_only_partial.FontOnlyPartial``. """
[docs] def __init__(self, factory_name: str, component: Any, lo_inst: LoInst | None = None) -> None: """ Constructor. Args: factory_name (str): The name that the factory will use to get a style object. component (Any): The component the style will be applied to. lo_inst (LoInst | None, optional): Loader instance. Defaults to None. Used in multi-document environments. """ super().__init__(factory_name, component, lo_inst)
# self.before_event_name = "before_style_border_line" # self.after_event_name = "after_style_border_line"
[docs] def style(self, factory: Callable[[str], Any], **kwargs: Any) -> Any: """ Style Font. Raises: CancelEventError: If the ``before_*`` event is cancelled and not handled. Returns: Any: Style instance or ``None`` if cancelled. """ comp = self._component factory_name = self._factory_name cancel_apply = False cargs = self._pre_style(**kwargs) if cargs is None: return None event_data = cast(Dict[str, Any], cargs.event_data.copy()) comp = event_data.pop("this_component", comp) factory_name = event_data.pop("factory_name", factory_name) cancel_apply = event_data.pop("cancel_apply", cancel_apply) fe = event_data.pop("styler_object", None) styler = factory(factory_name) if fe is None: fe = styler(**event_data) # fe.factory_name = factory_name fe.add_event_observer(self.event_observer) # type: ignore backup = False if not cancel_apply: event_data["factory_name"] = factory_name event_data["this_component"] = comp event_data["styler_object"] = fe c_backup_args = self._style_backup(fe, event_data) backup = not c_backup_args.cancel with LoContext(self._lo_inst): fe.apply(comp) if backup: _ = self._style_restore(style=fe, event_data=event_data, c_backup_args=c_backup_args) fe.set_update_obj(comp) if cancel_apply is False: event_data["styler_object"] = fe event_data["this_component"] = comp self._post_style(event_data) return fe
def _pre_style(self, **kwargs) -> CancelEventArgs | None: comp = self._component factory_name = self._factory_name event_data = kwargs.copy() cancel_apply = False cargs = CancelEventArgs(self._pre_style.__qualname__) event_data["factory_name"] = factory_name event_data["this_component"] = comp event_data["cancel_apply"] = cancel_apply event_data["styler_object"] = None cargs.event_data = event_data self.trigger_event(StyleNameEvent.STYLE_APPLYING, cargs) self.trigger_event(self.before_event_name, cargs) if cargs.cancel is True: if cargs.handled is not False: return None cargs.set("initial_event", self.before_event_name) self.trigger_event(GblNamedEvent.EVENT_CANCELED, cargs) if cargs.handled is False: raise mEx.CancelEventError(cargs, "Style has been cancelled.") else: return None return cargs def _post_style(self, event_data: Dict[str, Any]): event_args = EventArgs(source=self._post_style.__qualname__) event_args.event_data = event_data self.trigger_event(self.after_event_name, EventArgs.from_args(event_args)) # type: ignore self.trigger_event(StyleNameEvent.STYLE_APPLIED, EventArgs.from_args(event_args)) # type: ignore def _style_backup(self, style: StyleT, event_data: dict[str, Any]) -> CancelEventArgs: comp = event_data["this_component"] c_backup_args = CancelEventArgs(source=self._style_backup.__qualname__, cancel=True) c_backup_args.event_data = event_data self.trigger_event(StyleNameEvent.STYLE_BACKING_UP, c_backup_args) self.trigger_event(f"{self.before_event_name}_backup", c_backup_args) backup = not c_backup_args.cancel if backup: with LoContext(self._lo_inst): style.backup(comp) self.trigger_event(StyleNameEvent.STYLE_BACKED_UP, EventArgs.from_args(c_backup_args)) return c_backup_args def _style_restore( self, style: StyleT, event_data: Dict[str, Any], c_backup_args: CancelEventArgs ) -> CancelEventArgs: clear_on_restore = True comp = event_data["this_component"] event_data["clear_on_restore"] = clear_on_restore c_restore_args = CancelEventArgs(source=self.style.__qualname__, cancel=True) c_restore_args.event_data = event_data self.trigger_event(StyleNameEvent.STYLE_RESTORING, c_restore_args) self.trigger_event(f"{self.before_event_name}_restore", c_backup_args) if c_restore_args.cancel is False: clear_on_restore = c_restore_args.event_data.get("clear_on_restore", clear_on_restore) with LoContext(self._lo_inst): style.restore(comp, clear_on_restore) self.trigger_event(StyleNameEvent.STYLE_RESTORED, EventArgs.from_args(c_restore_args)) return c_restore_args
[docs] def style_apply(self, style: StyleT, **kwargs: Any) -> StyleT | None: """ Applies a know style to this component. Args: style (StyleT): Style to Apply. Returns: StyleT | None: Style that was Applied or None if cancelled. """ comp = self._component factory_name = self._factory_name cancel_apply = False cargs = self._pre_style(**kwargs) if cargs is None: return None event_data = cast(Dict[str, Any], cargs.event_data.copy()) comp = event_data.pop("this_component", comp) factory_name = event_data.pop("factory_name", factory_name) cancel_apply = event_data.pop("cancel_apply", cancel_apply) style.remove_event_observer(self.event_observer) # type: ignore style.add_event_observer(self.event_observer) # type: ignore backup = False if not cancel_apply: event_data["factory_name"] = factory_name event_data["this_component"] = comp event_data["styler_object"] = style c_backup_args = self._style_backup(style, event_data) backup = not c_backup_args.cancel with LoContext(self._lo_inst): style.apply(comp) if backup: _ = self._style_restore(style=style, event_data=event_data, c_backup_args=c_backup_args) style.set_update_obj(comp) if cancel_apply is False: event_data["styler_object"] = style event_data["this_component"] = comp self._post_style(event_data) return style
[docs] def style_get( self, factory: Callable[[str], Any], call_method_name: str = "from_obj", event_name_suffix: str = "_get", obj_arg_name: str = "obj", **kwargs: Any, ) -> Any: """ Gets the Style. Args: factory (Callable[[str], Any]): Factory function. call_method_name (str): Method name to call. Defaults to "from_obj". event_name_suffix (str): Event name suffix. Defaults to "_get". obj_arg_name (str): Object argument name. Defaults to "obj". If empty, the object is not passed to the method. kwargs: Keyword arguments to pass to factory method. Raises: CancelEventError: If the event is cancelled and not handled. Returns: TransparencyT | None: Area transparency style or ``None`` if cancelled. """ # general method for calling style methods. # see ooodev.format.inner.partial.chart2.numbers.numbers_numbers_partial.NumbersNumbersPartial # for an example of how to use this method. def call_method(style_obj, obj, method_name, **kwargs): method = getattr(style_obj, method_name, None) if method is not None and callable(method): if obj is not None: kwargs[obj_arg_name] = obj return method(**kwargs) else: raise AttributeError(f"Method {method_name} not found.") event_name = f"{self.before_event_name}{event_name_suffix}" comp = self._component factory_name = self._factory_name cargs = None cargs = CancelEventArgs(self.style_get.__qualname__) event_data = { "factory_name": factory_name, "this_component": comp, } cargs.event_data = event_data self.trigger_event(event_name, cargs) if cargs.cancel is True: if cargs.handled is not False: return None cargs.set("initial_event", event_name) self.trigger_event(GblNamedEvent.EVENT_CANCELED, cargs) if cargs.handled is False: raise mEx.CancelEventError(cargs, "Style get has been cancelled.") else: return None factory_name = cargs.event_data.get("factory_name", factory_name) comp = cargs.event_data.get("this_component", comp) styler = factory(factory_name) obj = kwargs.pop("obj", comp) if not obj_arg_name: obj = None try: # style = styler.from_obj(obj=comp, **kwargs) style = call_method(style_obj=styler, obj=obj, method_name=call_method_name, **kwargs) except mEx.DisabledMethodError: return None style.set_update_obj(comp) return style