"""Base Styles class"""
# pylint: disable=too-many-lines
# pylint: disable=broad-exception-raised
# pylint: disable=unused-import
# pylint: disable=useless-import-alias
# region Imports
from __future__ import annotations
from typing import Any, Dict, NamedTuple, Tuple, TYPE_CHECKING, Type, TypeVar, cast, overload
import contextlib
try:
# python 3.12+
from typing import override # noqa # type: ignore
except ImportError:
from typing_extensions import override # noqa # type: ignore
from com.sun.star.beans import XPropertySet
from com.sun.star.container import XNameContainer
from com.sun.star.lang import XMultiServiceFactory
# import random
# import string
from ooodev.utils import props as mProps
from ooodev.utils import info as mInfo
from ooodev.loader import lo as mLo
from ooodev.events.lo_events import Events, event_ctx
from ooodev.events.props_named_event import PropsNamedEvent
from ooodev.events.args.key_val_cancel_args import KeyValCancelArgs as KeyValCancelArgs
from ooodev.events.args.key_val_args import KeyValArgs as KeyValArgs
from ooodev.events.args.cancel_event_args import CancelEventArgs as CancelEventArgs
from ooodev.events.args.event_args import EventArgs as EventArgs
from ooodev.utils.type_var import EventCallback
from ooodev.format.inner.kind.format_kind import FormatKind
from ooodev.events.format_named_event import FormatNamedEvent as FormatNamedEvent
from ooodev.exceptions import ex as mEx
from ooodev.format.inner.common.props.prop_pair import PropPair
from ooodev.units.unit_obj import UnitT
from ooodev.units.unit_mm100 import UnitMM100
if TYPE_CHECKING:
from com.sun.star.beans import PropertyValue
from com.sun.star.style import CellStyle
from ooodev.proto.event_observer import EventObserver
from ooodev.format.proto.style_t import StyleT
else:
PropertyValue = Any
CellStyle = Any
StyleT = Any
# endregion Imports
# region Type Vars
TStyleBase = TypeVar("TStyleBase", bound="StyleBase") # pylint: disable=invalid-name
TStyleMulti = TypeVar("TStyleMulti", bound="StyleMulti") # pylint: disable=invalid-name
TStyleName = TypeVar("TStyleName", bound="StyleName") # pylint: disable=invalid-name
_TStyleModifyMulti = TypeVar("_TStyleModifyMulti", bound="StyleModifyMulti") # pylint: disable=invalid-name
# endregion Type Vars
# region Meta
class MetaStyle(type):
"""Meta class for styles"""
def __call__(cls, *args, **kw):
# sourcery skip: instance-method-first-arg-name
custom_args = kw.pop("_cattribs", None)
obj = cls.__new__(cls, *args, **kw) # type: ignore
# unique_id = "".join(random.choices(string.ascii_uppercase + string.digits, k=12))
# object.__setattr__(obj, "_unique_id", unique_id)
_events = Events(source=obj)
object.__setattr__(obj, "_internal_events", _events)
if custom_args:
for key, value in cast(Dict[str, Any], custom_args).items():
object.__setattr__(obj, key, value)
obj.__init__(*args, **kw)
return obj
# endregion Meta
# region Style Base Class
[docs]class StyleBase(metaclass=MetaStyle):
"""
Base Styles class
.. versionadded:: 0.9.0
"""
# region Init
[docs] def __init__(self, **kwargs) -> None:
# this property is used in child classes that have default instances
# self._events = Events(source=self)
# self._unique_id = "".join(random.choices(string.ascii_uppercase + string.digits, k=12))
self._is_default_inst = False
self._prop_parent: Any = None
self.__update_obj = None
self._dv = {}
self._dv_bak = None
for key, value in kwargs.items():
if key.startswith("__"):
# internal and not consider a property
continue
if value is not None:
self._dv[key] = value
super().__init__()
self._set_style_internal_events()
# region Update Methods
[docs] def has_update_obj(self) -> bool:
"""
Gets if the update object is set for the style instance.
Returns:
bool: ``True`` if the update object is set; Otherwise, ``False``.
.. versionadded:: 0.27.0
"""
return self.__update_obj is not None
[docs] def get_update_obj(self) -> Any:
"""
Gets the update object for the style instance.
Returns:
Any: The update object if set; Otherwise, ``None``.
.. versionadded:: 0.28.2
"""
return self.__update_obj
[docs] def set_update_obj(self, obj: Any) -> None:
"""
Sets the update object for the style instance.
Args:
obj (Any): Object used to apply style to when update is called.
Returns:
None:
.. versionadded:: 0.27.0
"""
# cannot set a weak ref to to a pyuno object.
self.__update_obj = obj
@overload
def update(self) -> bool:
"""
Applies the style to the update object.
Returns:
bool: Returns ``True`` if the update object is set and the style is applied; Otherwise, ``False``.
"""
...
@overload
def update(self, **kwargs: Any) -> bool:
"""
Applies the style to the update object.
Returns:
bool: Returns ``True`` if the update object is set and the style is applied; Otherwise, ``False``.
kwargs: Expandable list of key value pairs that may be used in child classes.
"""
...
[docs] def update(self, **kwargs: Any) -> bool:
"""
Applies the style to the update object.
Returns:
bool: Returns ``True`` if the update object is set and the style is applied; Otherwise, ``False``.
kwargs: Expandable list of key value pairs that may be used in child classes.
Note:
If the ``apply()`` method has been called then usually the style will set the update object.
For some style it may be necessary to set the update object manually using the ``set_update_obj()`` method.
The ``has_update_obj()`` method can be used to get the update object as been set
.. versionadded:: 0.27.0
"""
if self.__update_obj is None:
return False
self.apply(obj=self.__update_obj, **kwargs)
return True
# endregion Update Methods
def _get_mm100_obj_from_mm(self, value: UnitT | float, min_value: int = -9999) -> UnitMM100:
"""
Gets a UnitMM100 object from mm.
Args:
value (UnitT | float): Units in mm or UnitT
min_value (int, optional): The min value in ``1/100 mm`.
If not != -9999 then value must be greater than or equal to ``min_val``.
Defaults to -9999.
Raises:
ValueError: If min_val != -9999 and value < min_val
Returns:
UnitMM100: MM 100 units.
"""
with contextlib.suppress(AttributeError):
result = value.get_value_mm100() # type: ignore
if min_value != -9999 and result < min_value:
raise ValueError("Value must be positive")
return UnitMM100(result)
result = UnitMM100.from_mm(value) # type: ignore
if min_value != -9999 and result.value < min_value:
raise ValueError("Value must be positive")
return result
def _set_style_internal_events(self):
self._fn_on_getting_cattribs = self._on_getting_cattribs
self._fn_on_clearing = self._on_clearing
self._fn_on_removing = self._on_removing
self._fn_on_setting = self._on_setting
self._fn_on_copying = self._on_copying
self._fn_on_backing_up = self.on_property_backing_up
self._fn_on_backed_up = self.on_property_backed_up
self._fn_on_applying = self.on_applying
self._fn_on_applied = self.on_applied
self._events.on("internal_cattribs", self._fn_on_getting_cattribs)
self._events.on(FormatNamedEvent.STYLE_CLEARING, self._fn_on_clearing)
self._events.on(FormatNamedEvent.STYLE_REMOVING, self._fn_on_removing)
self._events.on(FormatNamedEvent.STYLE_SETTING, self._fn_on_setting)
self._events.on(FormatNamedEvent.STYLE_COPYING, self._fn_on_copying)
self._events.on(FormatNamedEvent.STYLE_BACKING_UP, self._fn_on_backing_up)
self._events.on(FormatNamedEvent.STYLE_BACKED_UP, self._fn_on_backed_up)
self._events.on(FormatNamedEvent.STYLE_APPLYING, self._fn_on_applying)
self._events.on(FormatNamedEvent.STYLE_APPLIED, self._fn_on_applied)
# endregion Init
# region Events
[docs] def add_event_observer(self, *args: EventObserver) -> None:
"""
Adds observers that gets their ``trigger`` method called when this class ``trigger`` method is called.
Parameters:
args (EventObserver): One or more observers to add.
Returns:
None:
Note:
Observers are removed automatically when they are out of scope.
"""
self._events.add_observer(*args)
[docs] def add_event_listener(self, event_name: str, callback: EventCallback) -> None:
"""
Add an event listener to current instance.
Args:
event_name (str): Event Name.
callback (EventCallback): Callback of the event listener.
Returns:
None:
See Also:
- :py:class:`~.format_named_event.FormatNamedEvent`
- :py:meth:`.remove_event_listener`
Note:
This method is generally only used in the context of child classes.
"""
self._events.on(event_name, callback)
[docs] def remove_event_listener(self, event_name: str, callback: EventCallback) -> None:
"""
Remove an event listener from current instance.
Args:
event_name (str): Event Name.
callback (EventCallback): Callback of the event listener.
Returns:
None:
See Also:
- :py:class:`~.format_named_event.FormatNamedEvent`
- :py:meth:`.add_event_listener`
Note:
This method is generally only used in the context of child classes.
"""
self._events.remove(event_name, callback)
[docs] def remove_event_observer(self, observer: EventObserver) -> bool:
"""
Removes an observer.
Args:
observer (EventObserver): Observers to remove.
Returns:
bool: ``True`` if observer has been removed; Otherwise, ``False``.
.. versionadded:: 0.30.1
"""
return self._events.remove_observer(observer)
# endregion Events
# region style property methods
def _get_properties(self) -> Dict[str, Any]:
"""Gets Key value pairs for the instance."""
return self._dv
def _get(self, key: str) -> Any:
"""Gets the property value"""
return self._get_properties().get(key)
def _set(self, key: str, val: Any) -> bool:
"""Sets a property value"""
kvargs = KeyValCancelArgs("style_base", key=key, value=val)
cargs = CancelEventArgs.from_args(kvargs) # type: ignore
self._events.trigger(FormatNamedEvent.STYLE_SETTING, kvargs)
self._events.trigger(FormatNamedEvent.STYLE_MODIFYING, cargs)
if kvargs.cancel:
return False
if cargs.cancel:
return False
data_values = self._get_properties()
data_values[kvargs.key] = kvargs.value
self._events.trigger(FormatNamedEvent.STYLE_SET, KeyValArgs.from_args(kvargs)) # type: ignore
return True
def _clear(self) -> None:
"""Clears all properties"""
cargs = CancelEventArgs("style_base")
self._events.trigger(FormatNamedEvent.STYLE_MODIFYING, cargs)
self._events.trigger(FormatNamedEvent.STYLE_CLEARING, cargs)
if cargs.cancel:
return
data_values = self._get_properties()
data_values.clear()
def _has(self, key: str) -> bool:
"""Gets if a property exist"""
return key in self._get_properties()
def _remove(self, key: str) -> bool:
"""Removes a property if it exist"""
cargs = CancelEventArgs("style_base")
cargs.event_data = key
self._events.trigger(FormatNamedEvent.STYLE_REMOVING, cargs)
self._events.trigger(FormatNamedEvent.STYLE_MODIFYING, cargs)
if cargs.cancel:
return False
if self._has(key):
data_values = self._get_properties()
del data_values[key]
return True
return False
def _del_attribs(self, *attribs: str) -> None:
"""Delete Attributes from instance if exist. Calls ``_on_deleting_attrib()``"""
for attrib in attribs:
if hasattr(self.__class__, attrib):
kvargs = KeyValCancelArgs("style_base", key=attrib, value=getattr(self, attrib, None))
self._on_deleting_attrib(self, kvargs)
if kvargs.cancel:
continue
delattr(self.__class__, attrib) # type: ignore
for attrib in attribs:
if hasattr(self, attrib):
kvargs = KeyValCancelArgs("style_base", key=attrib, value=getattr(self, attrib, None))
self._on_deleting_attrib(self, kvargs)
if kvargs.cancel:
continue
delattr(self, attrib)
def _update(self, value: Dict[str, Any] | StyleBase) -> None:
"""Updates properties"""
cargs = CancelEventArgs("style_base")
cargs.event_data = value
self._events.trigger(FormatNamedEvent.STYLE_UPDATING, cargs)
self._events.trigger(FormatNamedEvent.STYLE_MODIFYING, cargs)
if cargs.cancel:
return
data_dict = self._get_properties()
if isinstance(cargs.event_data, StyleBase):
# pylint: disable=protected-access
data_dict.update(cargs.event_data._dv)
return
data_dict.update(cargs.event_data)
# endregion style property methods
# region Services
[docs] def support_service(self, *service: str) -> bool:
"""
Gets if service is supported.
Args:
service: expandable list of service names of UNO services such as ``com.sun.star.text.TextFrame``.
Returns:
bool: ``True`` if service is supported; Otherwise, ``False``.
"""
services = self._supported_services()
return any(s in services for s in service)
def _supported_services(self) -> Tuple[str, ...]:
"""
Gets a tuple of supported services for the style such as (``com.sun.star.style.ParagraphProperties``,)
Raises:
NotImplementedError: If not implemented in child class
Returns:
Tuple[str, ...]: Supported services
"""
raise NotImplementedError
def _is_valid_obj(self, obj: Any) -> bool:
"""
Gets if ``obj`` supports one of the services required by style class
Args:
obj (Any): UNO object that must have requires service
Returns:
bool: ``True`` if has a required service; Otherwise, ``False``
"""
return self._is_obj_service(obj)
def _is_obj_service(self, obj: Any) -> bool:
"""
Gets if ``obj`` supports one of the services required by style class
Args:
obj (Any): UNO object that must have requires service
Returns:
bool: ``True`` if has a required service; Otherwise, ``False``
"""
if services := self._supported_services():
return mInfo.Info.support_service(obj, *services)
# if style class has no required services then return True
return True
def _print_not_valid_srv(self, method_name: str = ""):
"""
Prints via ``Lo.print()`` notice that required service is missing
Args:
method_name (str, optional): Calling method name.
"""
services = self._supported_services()
rs_len = len(services)
name = f".{method_name}()" if method_name else ""
if rs_len == 0:
mLo.Lo.print(f"{self.__class__.__name__}{name}: object is not valid.")
return
services = ", ".join(services)
srv = "service" if rs_len == 1 else "services"
mLo.Lo.print(f"{self.__class__.__name__}{name}: object must support {srv}: {services}")
# endregion Services
# region Internal Methods
def _props_set(self, obj: Any, **kwargs: Any) -> None:
"""Lo Safe Method."""
# set properties. Can be overridden in child classes
# may be useful to wrap in try statements in child classes
try:
mProps.Props.set(obj, **kwargs)
except mEx.MultiError as multi_err:
mLo.Lo.print(f"{self.__class__.__name__}.apply(): Unable to set Property")
for err in multi_err.errors:
mLo.Lo.print(f" {err}")
def _copy_missing_attribs(self, src: TStyleBase, dst: TStyleBase, *args: str) -> None:
"""
Copies attribs from source to dst if dst does not already have the attrib.
Args:
src (TStyleBase): Source
dst (TStyleBase): Destination
Returns:
None:
"""
for arg in args:
if not hasattr(dst, arg) and hasattr(src, arg):
setattr(dst, arg, getattr(src, arg))
# region _props methods
def _get_internal_cattribs(self) -> dict:
cattribs = {
"_props_internal_attributes": self._props,
"_supported_services_values": self._supported_services(),
"_format_kind_prop": self.prop_format_kind,
}
cargs = CancelEventArgs(self)
cargs.event_data = cattribs
self._events.trigger("internal_cattribs", cargs)
return {} if cargs.cancel else cargs.event_data
# endregion _props methods
# endregion Internal Methods
# region Methods
[docs] def get_attrs(self) -> Tuple[str, ...]:
"""
Gets the attributes that are slated for change in the current instance
Returns:
Tuple(str, ...): Tuple of attributes
"""
# get current keys in internal dictionary
return tuple(self._get_properties().keys())
[docs] def apply(self, obj: Any, **kwargs: Any) -> None:
"""
Applies styles to object
Args:
obj (Any): UNO Object that styles are to be applied.
kwargs (Any, optional): Expandable list of key value pairs that may be used in child classes.
Keyword Arguments:
override_dv (Dic[str, Any], optional): if passed in this dictionary is used to set properties instead of internal dictionary of property values.
validate (bool, optional): if ``False`` then ``obj`` is not validated. Defaults to ``True``.
:events:
.. cssclass:: lo_event
- :py:attr:`~.events.format_named_event.FormatNamedEvent.STYLE_APPLYING` :eventref:`src-docs-event-cancel`
- :py:attr:`~.events.format_named_event.FormatNamedEvent.STYLE_APPLIED` :eventref:`src-docs-event`
Returns:
None:
Note:
If Event data ``obj``, ``data_values`` or ``allow_update`` are changed then the new values are used.
Add update object to instance if not already set and ``allow_update`` is ``True`` (default).
.. versionchanged:: 0.27.0
Event data is now a dictionary with keys ``source``, ``obj``, ``data_values`` and ``allow_update``.
.. versionchanged:: 0.9.4
Added ``validate`` keyword arguments.
"""
allow_update = True
validate = bool(kwargs.get("validate", True))
if "override_dv" in kwargs:
data_values = kwargs["override_dv"]
else:
data_values = self._get_properties()
if len(data_values) > 0:
if not validate or self._is_valid_obj(obj):
cargs = CancelEventArgs(source=f"{self.apply.__qualname__}")
event_data = {"source": self, "obj": obj, "data_values": data_values, "allow_update": allow_update}
cargs.event_data = event_data
self._events.trigger(FormatNamedEvent.STYLE_APPLYING, cargs)
if cargs.cancel:
return
data_values = cargs.event_data["data_values"]
the_obj = cargs.event_data["obj"]
allow_update = cargs.event_data.get("allow_update", allow_update)
with event_ctx(
(PropsNamedEvent.PROP_SETTING, _on_props_setting),
(PropsNamedEvent.PROP_SET, _on_props_set),
(PropsNamedEvent.PROP_SET_ERROR, _on_props_set_error),
source=self,
lo_observe=True,
):
self._props_set(the_obj, **data_values)
# set for update.
if allow_update is True and not self.has_update_obj():
self.set_update_obj(the_obj)
eargs = EventArgs.from_args(cargs)
self._events.trigger(FormatNamedEvent.STYLE_APPLIED, eargs)
else:
self._print_not_valid_srv("apply")
[docs] def get_props(self) -> Tuple[PropertyValue, ...]:
"""
Gets instance properties
Returns:
Tuple[PropertyValue, ...]: Tuple of properties.
"""
# see: setPropertyValues([in] sequence< com::sun::star::beans::PropertyValue > aProps)
# https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1beans_1_1XPropertyAccess.html#a5ac97dfa6d796f4c794e2350e9130692
return () if len(self._dv) == 0 else mProps.Props.make_props(**self._dv)
# region Copy()
@overload
def copy(self: TStyleBase) -> TStyleBase: ...
@overload
def copy(self: TStyleBase, **kwargs) -> TStyleBase: ...
[docs] def copy(self: TStyleBase, **kwargs) -> TStyleBase:
"""Gets a copy of instance as a new instance"""
# sourcery skip: low-code-quality
# pylint: disable=protected-access
cargs = CancelEventArgs(self)
self._events.trigger(FormatNamedEvent.STYLE_COPYING, cargs)
if cargs.cancel:
if cargs.handled:
return cargs.event_data
else:
raise mEx.CancelEventError(cargs)
new_class = self.__class__(**kwargs)
new_class._prop_parent = self._prop_parent
# pylint: disable=unused-variable
if self._get_properties():
# it is possible that that a new instance will have different property names then the current instance.
# This can happen because this class inherits from MetaStyle.
# if ne contains a _props attribute (tuple of prop names) then use them to remap keys.
# For instance a key of BorderLength may become ParaBorderLength.
key_map = None
p_len = len(new_class._props)
if p_len > 0 and p_len == len(self._props):
key_map = {}
for i, p_val in enumerate(self._props):
if p_val == "":
# some prop value may not be used in which case they are empty strings.
continue
if isinstance(p_val, PropPair):
nu_pair = cast(PropPair, new_class._props[i])
if p_val.first:
key_map[p_val.first] = nu_pair.first
if p_val.second:
key_map[p_val.second] = nu_pair.second
else:
key_map[p_val] = new_class._props[i]
if key_map:
for key, nu_val in key_map.items():
if self._has(key):
new_class._set(nu_val, self._get(key))
else:
new_class._update(self._get_properties())
if self.__update_obj is not None:
new_class.set_update_obj(self.__update_obj)
return new_class
# endregion Copy()
# endregion Methods
# region Backup/Restore
[docs] def backup(self, obj: Any) -> None:
"""
Backs up Attributes that are to be changed by apply.
If used method should be called before apply.
Args:
obj (Any): Object to backup properties from.
Returns:
None:
:events:
.. cssclass:: lo_event
- :py:attr:`~.events.format_named_event.FormatNamedEvent.STYLE_BACKING_UP` :eventref:`src-docs-key-event-cancel`
- :py:attr:`~.events.format_named_event.FormatNamedEvent.STYLE_BACKED_UP` :eventref:`src-docs-key-event`
See Also:
:py:meth:`~.style_base.StyleBase.restore`
"""
if not self._is_valid_obj(obj):
self._print_not_valid_srv("Backup")
return
if self._dv_bak is None:
self._dv_bak = {}
for attr in self.get_attrs():
val = mProps.Props.get(obj, attr, None)
cargs = KeyValCancelArgs("style_base", key=attr, value=val)
self._events.trigger(FormatNamedEvent.STYLE_BACKING_UP, cargs)
if cargs.cancel:
continue
self._dv_bak[attr] = val
eargs = KeyValArgs.from_args(cargs) # type: ignore
self._events.trigger(FormatNamedEvent.STYLE_BACKED_UP, eargs)
[docs] def restore(self, obj: Any, clear: bool = False) -> None:
"""
Restores ``obj`` properties from backed up setting if any exist.
Restore can only be effective if ``backup()`` has be run before calling this method.
Args:
obj (Any): Object to restore properties on.
clear (bool): Determines if backup is cleared after restore. Default ``False``
Returns:
None:
:events:
.. cssclass:: lo_event
- :py:attr:`~.events.format_named_event.FormatNamedEvent.STYLE_PROPERTY_RESTORING` :eventref:`src-docs-key-event-cancel`
- :py:attr:`~.events.format_named_event.FormatNamedEvent.STYLE_PROPERTY_RESTORED` :eventref:`src-docs-key-event`
See Also:
:py:meth:`~.style_base.StyleBase.backup`
"""
if self._dv_bak is None:
return
if len(self._dv_bak) > 0:
with event_ctx(
(PropsNamedEvent.PROP_SETTING, _on_props_restore_setting),
(PropsNamedEvent.PROP_SET, _on_props_restore_set),
source=self,
lo_observe=True,
):
mProps.Props.set(obj, **self._dv_bak)
if clear:
self._dv_bak.clear()
# endregion Backup/Restore
# region Event Methods
def _on_setting(self, source: Any, event_args: KeyValCancelArgs) -> None:
# can be overridden in child classes to manage or modify setting
# called by _set()
pass
def _on_removing(self, source: Any, event_args: CancelEventArgs) -> None:
# can be overridden in child classes to manage or modify setting
# called by _remove()
pass
def _on_getting_cattribs(self, source: Any, event_args: CancelEventArgs) -> None:
# can be overridden in child classes to manage or modify setting
# called by _remove()
pass
def _on_clearing(self, source: Any, event_args: CancelEventArgs) -> None:
# can be overridden in child classes to manage or modify setting
# called by _clear()
pass
def _on_modifying(self, source: Any, event_args: CancelEventArgs) -> None:
# can be overridden in child classes to manage or modify setting
# called by _set(), _remove(), _clear(), _update()
pass
def _on_copying(self, source: Any, event_args: CancelEventArgs) -> None:
# can be overridden in child classes to manage or modify setting
pass
def _on_deleting_attrib(self, source: Any, event_args: KeyValCancelArgs) -> None:
# can be overridden in child classes to manage or modify setting
pass
[docs] def on_property_setting(self, source: Any, event_args: KeyValCancelArgs) -> None:
"""
Triggers for each property that is set
Args:
source (Any): Event Source.
event_args (KeyValueCancelArgs): Event Args
"""
# can be overridden in child classes.
pass
[docs] def on_property_set(self, source: Any, event_args: KeyValArgs) -> None:
"""
Triggers for each property that is set.
Args:
source (Any): Event Source.
event_args (KeyValArgs): Event Args
"""
# can be overridden in child classes.
pass
[docs] def on_property_set_error(self, source: Any, event_args: KeyValCancelArgs) -> None:
"""
Triggers for each property that fails to set.
Args:
source (Any): Event Source.
event_args (KeyValArgs): Event Args
"""
# can be overridden in child classes.
pass
[docs] def on_property_backing_up(self, source: Any, event_args: KeyValCancelArgs) -> None:
"""
Triggers before each property that is about to be backup up during backup.
Args:
source (Any): Event Source.
event_args (KeyValueCancelArgs): Event Args.
"""
# can be overridden in child classes.
pass
[docs] def on_property_backed_up(self, source: Any, event_args: KeyValArgs) -> None:
"""
Triggers before each property that is about to be set during backup.
Args:
source (Any): Event Source.
event_args (KeyValArgs): Event Args
"""
# can be overridden in child classes.
pass
[docs] def on_property_restore_setting(self, source: Any, event_args: KeyValCancelArgs) -> None:
"""
Triggers before each property that is about to be set during restore
Args:
source (Any): Event Source.
event_args (KeyValueCancelArgs): Event Args
"""
# can be overridden in child classes.
event_args.set("on_property_restore_setting", True)
self.on_property_setting(source, event_args)
[docs] def on_property_restore_set(self, source: Any, event_args: KeyValArgs) -> None:
"""
Triggers for each property that has been set during restore
Args:
source (Any): Event Source.
event_args (KeyValArgs): Event Args
"""
# can be overridden in child classes.
event_args.set("on_property_restore_set", True)
self.on_property_set(source, event_args)
[docs] def on_applying(self, source: Any, event_args: CancelEventArgs) -> None:
"""
Triggers before style/format is applied.
Args:
source (Any): Event Source.
event_args (CancelEventArgs): Event Args
"""
# can be overridden in child classes.
pass
[docs] def on_applied(self, source: Any, event_args: EventArgs) -> None:
"""
Triggers after style/format is applied.
Args:
source (Any): Event Source.
event_args (KeyValArgs): Event Args
"""
# can be overridden in child classes.
pass
# endregion Event Methods
# region Dunder Methods
def __eq__(self, oth: object) -> bool:
if not isinstance(oth, StyleBase):
return NotImplemented
result = False
try:
for key, value in self._get_properties().items():
if oth._get(key) != value:
return False
result = True
except Exception: # pylint: disable=broad-exception-caught
return False
return result
# endregion Dunder Methods
# region Named Container Methods
def _container_get_service_name(self) -> str:
raise NotImplementedError
def _container_get_inst(self) -> XNameContainer:
return mLo.Lo.create_instance_msf(
XNameContainer,
service_name=self._container_get_service_name(),
msf=self._container_get_msf(),
raise_err=True,
)
def _container_get_msf(self) -> XMultiServiceFactory | None:
return None
def _container_add_value(
self,
name: str,
obj: Any,
allow_update: bool = True,
nc: XNameContainer | None = None, # pylint: disable=invalid-name
) -> None:
if nc is None:
nc = self._container_get_inst()
if nc.hasByName(name):
if allow_update:
nc.replaceByName(name, obj)
return
else:
nc.insertByName(name, obj)
def _container_get_unique_el_name(
self, prefix: str, nc: XNameContainer | None = None # pylint: disable=invalid-name
) -> str:
"""
Gets the next name that does not exist in the container.
Lets say ``prefix`` is ``Transparency `` then names are search in sequence.
``Transparency 1``, ``Transparency 3``, ``Transparency 3``, etc until a unique name is found.
Args:
prefix (str): Any string such as ``Transparency ``
nc (XNameContainer | None, optional): Container. Defaults to None.
Returns:
str: Unique name
"""
if nc is None:
nc = self._container_get_inst()
names = nc.getElementNames()
i = 1
name = f"{prefix}{i}"
while name in names:
i += 1
name = f"{prefix}{i}"
return name
def _container_get_value(self, name: str, nc: XNameContainer | None = None) -> Any: # pylint: disable=invalid-name
if not name:
raise ValueError("Name is empty value. Expected a string name.")
if nc is None:
nc = self._container_get_inst()
return nc.getByName(name) if nc.hasByName(name) else None
# endregion Named Container Methods
# region Properties
@property
def prop_has_attribs(self) -> bool:
"""Gets If instance has any attributes set."""
return len(self._dv) > 0
@property
def prop_has_backup(self) -> bool:
"""Gets If instance has backup data set."""
return False if self._dv_bak is None else len(self._dv_bak) > 0
@property
def prop_format_kind(self) -> FormatKind:
"""Gets the kind of style"""
return FormatKind.UNKNOWN
@property
def prop_parent(self) -> StyleBase | None:
"""Gets Parent Class"""
return self._prop_parent
@property
def _props(self) -> Tuple[str, ...]:
# placeholder for child classes. Usd in copy method.
return ()
@property
def _events(self) -> Events:
# pylint: disable=no-member
return self._internal_events # type: ignore
# endregion Properties
# endregion Style Base Class
# region Module Internal Helper Classes
class _StyleMultiArgs:
"""Generic Args"""
def __init__(self, *attrs, **kwargs):
"""
Constructor
"""
self._args = attrs[:]
self._kwargs = kwargs.copy()
@property
def attrs(self) -> tuple:
"""
Gets attribs tuple.
This is a copy of ``args`` passed into constructor.
"""
return self._args
@property
def kwargs(self) -> Dict[str, Any]:
"""
Gets kwargs Dictionary
This is a copy of ``kwargs`` passed into constructor
"""
return self._kwargs
class _StyleInfo(NamedTuple):
style: StyleT
args: _StyleMultiArgs | None
# endregion Module Internal Helper Classes
# region Style Multi Class
[docs]class StyleMulti(StyleBase):
"""
Multi style class.
Supports appending styles via ``_append_style()`` (protected) method.
When ``apply_style()`` is call all internal style instances are also applied.
.. versionadded:: 0.9.0
"""
# region Init
[docs] def __init__(self, **kwargs) -> None:
self._styles: Dict[str, _StyleInfo] = {}
self._all_attributes = True
super().__init__(**kwargs)
# endregion Init
# region Overrides
def _get_service_name(self) -> str:
raise NotImplementedError
def _supported_services(self) -> Tuple[str, ...]:
raise NotImplementedError
def _set_style_internal_events(self) -> None:
super()._set_style_internal_events()
self._fn_on_multi_style_setting = self._on_multi_style_setting
self._fn_on_multi_style_set = self._on_multi_style_set
self._fn_on_multi_style_removing = self._on_multi_style_removing
self._fn_on_multi_style_removed = self._on_multi_style_removed
self._fn_on_multi_style_updating = self._on_multi_style_updating
self._fn_on_multi_style_updated = self._on_multi_style_updated
self._fn_on_multi_child_style_applying = self._on_multi_child_style_applying
self._fn_on_multi_child_style_applied = self._on_multi_child_style_applied
self._events.on(FormatNamedEvent.MULTI_STYLE_SETTING, self._fn_on_multi_style_setting)
self._events.on(FormatNamedEvent.MULTI_STYLE_SET, self._fn_on_multi_style_set)
self._events.on(FormatNamedEvent.MULTI_STYLE_REMOVING, self._fn_on_multi_style_removing)
self._events.on(FormatNamedEvent.MULTI_STYLE_REMOVED, self._fn_on_multi_style_removed)
self._events.on(FormatNamedEvent.MULTI_STYLE_UPDATING, self._fn_on_multi_style_updating)
self._events.on(FormatNamedEvent.MULTI_STYLE_UPDATED, self._fn_on_multi_style_updated)
self._events.on(FormatNamedEvent.STYLE_MULTI_CHILD_APPLYING, self._fn_on_multi_child_style_applying)
self._events.on(FormatNamedEvent.STYLE_MULTI_CHILD_APPLIED, self._fn_on_multi_child_style_applied)
# region Update Methods
[docs] @override
def set_update_obj(self, obj: Any) -> None:
"""
Sets the update object for the styles instances.
Args:
obj (Any): Object used to apply style to when update is called.
"""
super().set_update_obj(obj)
styles = self._get_multi_styles()
for style, _ in styles.values():
style.set_update_obj(obj)
[docs] @override
def update(self, **kwargs: Any) -> bool:
"""
Applies the styles to the update object.
Returns:
bool: Returns ``True`` if the update object is set and the style is applied; Otherwise, ``False``.
kwargs: Expandable list of key value pairs that may be used in child classes.
"""
result = True
styles = self._get_multi_styles()
for style, _ in styles.values():
result = result and style.update(**kwargs)
result = result and super().update(**kwargs)
return result
# endregion Update Methods
# region apply()
def _apply_direct(self, obj: Any, **kwargs) -> None:
"""Calls super apply directly"""
super().apply(obj, **kwargs)
[docs] @override
def apply(self, obj: Any, **kwargs) -> None:
"""
Applies style of current instance and all other internal style instances.
Args:
obj (Any): UNO Object that styles are to be applied.
"""
styles = self._get_multi_styles()
for key, info in styles.items():
kvargs = KeyValCancelArgs("StyleMulti.apply", key=key, value=info)
self._events.trigger(FormatNamedEvent.STYLE_MULTI_CHILD_APPLYING, kvargs)
if kvargs.cancel:
continue
style, key_word = info
if key_word:
style.apply(obj, **key_word.kwargs)
else:
style.apply(obj)
self._events.trigger(FormatNamedEvent.STYLE_MULTI_CHILD_APPLIED, KeyValArgs.from_args(kvargs)) # type: ignore
# apply this instance properties after all others styles.
# allows this instance to overwrite properties set by multi styles if needed.
super().apply(obj, **kwargs)
# endregion apply()
# region Copy()
@overload
def copy(self: TStyleMulti) -> TStyleMulti: ...
@overload
def copy(self: TStyleMulti, **kwargs) -> TStyleMulti: ...
[docs] @override
def copy(self: TStyleMulti, **kwargs) -> TStyleMulti: # type: ignore
"""Gets a copy of instance as a new instance"""
# pylint: disable=protected-access
instance_copy = super().copy(**kwargs)
styles = self._get_multi_styles()
for key, info in styles.items():
style, key_words = info
if key_words:
instance_copy._set_style(key, style.copy(**kwargs), **key_words.kwargs)
else:
instance_copy._set_style(key, style.copy(**kwargs))
return instance_copy
# endregion Copy()
def __eq__(self, oth: object) -> bool:
if not isinstance(oth, StyleMulti):
return NotImplemented
result = super().__eq__(oth)
if result is False:
return False
styles = self._get_multi_styles()
for key, info in styles.items():
style, _ = info
style_other = oth._get_style(key)
if style_other is None:
result = False
break
result = style == style_other[0]
if not result:
break
return result
# endregion Overrides
# region Internal Methods
def _set_style(self, key: str, style: StyleT, *attrs, **kwargs) -> None:
"""
Sets style
Args:
key (str): key store style info
style (StyleBase): style
attrs: Expandable list attributes that style sets.
The values added here are added when get_attrs() method is called.
This is used for backup and restore in Write Module.
kwargs: Expandable key value args to that are to be passed to style when ``apply_style()`` is called.
"""
# pylint: disable=protected-access
kvargs = KeyValCancelArgs("_set_style", key=key, value=style)
self._events.trigger(FormatNamedEvent.MULTI_STYLE_SETTING, kvargs)
if kvargs.cancel:
return
styles = self._get_multi_styles()
if style._prop_parent is None: # type: ignore
style._prop_parent = self # type: ignore
if len(attrs) + len(kwargs) == 0:
styles[key] = _StyleInfo(style, None)
else:
styles[key] = _StyleInfo(style, _StyleMultiArgs(*attrs, **kwargs))
self._events.trigger(FormatNamedEvent.MULTI_STYLE_SET, KeyValArgs.from_args(kvargs)) # type: ignore
def _update_style(self, value: StyleMulti) -> None:
# pylint: disable=protected-access
cargs = CancelEventArgs("_update_style")
cargs.event_data = value
self._events.trigger(FormatNamedEvent.MULTI_STYLE_UPDATING, cargs)
if cargs.cancel:
return
self._get_multi_styles().update(value._styles)
self._events.trigger(FormatNamedEvent.MULTI_STYLE_UPDATED, EventArgs.from_args(cargs))
def _remove_style(self, key: str) -> bool:
cargs = CancelEventArgs("_set_style")
cargs.event_data = key
self._events.trigger(FormatNamedEvent.MULTI_STYLE_REMOVING, cargs)
if cargs.cancel:
return False
result = False
styles = self._get_multi_styles()
if key in styles:
del styles[key]
result = True
# only trigger if removed
self._events.trigger(FormatNamedEvent.MULTI_STYLE_REMOVED, EventArgs.from_args(cargs))
return result
def _get_style(self, key: str) -> _StyleInfo | None:
return self._get_multi_styles().get(key)
def _get_style_inst(self, key: str) -> StyleT | None:
style = self._get_style(key)
return None if style is None else style.style
def _has_style(self, key: str) -> bool:
return key in self._get_multi_styles()
def _get_multi_styles(self) -> Dict[str, _StyleInfo]:
return self._styles
# endregion Internal Methods
# region Methods
[docs] @override
def backup(self, obj: Any) -> None:
"""
Backs up Attributes that are to be changed by apply.
If used method should be called before apply.
Args:
obj (Any): Object to backup properties from.
Returns:
None:
:events:
.. cssclass:: lo_event
- :py:attr:`~.events.format_named_event.FormatNamedEvent.STYLE_BACKING_UP` :eventref:`src-docs-key-event-cancel`
- :py:attr:`~.events.format_named_event.FormatNamedEvent.STYLE_BACKED_UP` :eventref:`src-docs-key-event`
See Also:
:py:meth:`~.style_base.StyleMulti.restore`
"""
if not self._is_valid_obj(obj):
self._print_not_valid_srv("Backup")
return
try:
self._all_attributes = False
super().backup(obj)
styles = self._get_multi_styles()
for _, info in styles.items():
style, _ = info
style.backup(obj)
finally:
self._all_attributes = True
[docs] @override
def restore(self, obj: Any, clear: bool = False) -> None:
"""
Restores ``obj`` properties from backed up setting if any exist.
Restore can only be effective if ``backup()`` has be run before calling this method.
Args:
obj (Any): Object to restore properties on.
clear (bool): Determines if backup is cleared after restore. Default ``False``
Returns:
None:
:events:
.. cssclass:: lo_event
- :py:attr:`~.events.format_named_event.FormatNamedEvent.STYLE_PROPERTY_RESTORING` :eventref:`src-docs-key-event-cancel`
- :py:attr:`~.events.format_named_event.FormatNamedEvent.STYLE_PROPERTY_RESTORED` :eventref:`src-docs-key-event`
See Also:
:py:meth:`~.style_base.StyleMulti.backup`
"""
super().restore(obj=obj, clear=clear)
styles = self._get_multi_styles()
for _, info in styles.items():
style, _ = info
style.restore(obj=obj, clear=clear)
[docs] @override
def get_attrs(self) -> Tuple[str, ...]:
"""
Gets the attributes that are slated for change in the current instance
Returns:
Tuple(str, ...): Tuple of attributes
"""
# get current keys in internal dictionary
props = self._get_properties()
attrs = set(props.keys())
if self._all_attributes:
if styles := self._get_multi_styles():
for _, info in styles.items():
_, args = info
if args:
attrs.update(args.attrs)
return tuple(attrs)
# endregion Methods
# region event handlers
def _on_multi_style_setting(self, source: Any, event_args: KeyValCancelArgs) -> None:
pass
def _on_multi_style_set(self, source: Any, event_args: KeyValArgs) -> None:
pass
def _on_multi_style_removing(self, source: Any, event_args: CancelEventArgs) -> None:
pass
def _on_multi_style_removed(self, source: Any, event_args: EventArgs) -> None:
pass
def _on_multi_style_updating(self, source: Any, event_args: CancelEventArgs) -> None:
pass
def _on_multi_style_updated(self, source: Any, event_args: EventArgs) -> None:
pass
def _on_multi_child_style_applying(self, source: Any, event_args: KeyValCancelArgs) -> None:
pass
def _on_multi_child_style_applied(self, source: Any, event_args: KeyValArgs) -> None:
pass
# endregion event handlers
# region Properties
@property
@override
def prop_has_attribs(self) -> bool:
"""Gets If instance has any attributes set."""
return len(self._dv) + len(self._styles) > 0
@property
@override
def prop_has_backup(self) -> bool:
"""Gets If instance or any added style has backup data set."""
result = False
styles = self._get_multi_styles()
for _, info in styles.items():
style, _ = info
if style.prop_has_backup:
result = True
break
if result:
return True
return False if self._dv_bak is None else len(self._dv_bak) > 0
# endregion Properties
# endregion Style Multi Class
# region Style Modify Multi class
[docs]class StyleModifyMulti(StyleMulti):
"""
Para Style Base
.. versionadded:: 0.9.0
"""
# region Init
[docs] def __init__(self, **kwargs) -> None:
super().__init__(**kwargs)
self._style_family_name = ""
# endregion Init
# region Overrides
def _supported_services(self) -> Tuple[str, ...]:
return (
"com.sun.star.style.Style",
"com.sun.star.style.ParagraphStyle",
"com.sun.star.beans.PropertySet",
)
def _is_valid_obj(self, obj: Any) -> bool:
if mLo.Lo.is_uno_interfaces(obj, "com.sun.star.style.XStyle"):
return self._is_obj_service(obj)
# pylint: disable=unused-variable
if self._is_obj_service(obj):
return True
return mInfo.Info.is_doc_type(obj, mLo.Lo.Service.WRITER)
def _props_set(self, obj: Any, **kwargs: Any) -> None:
try:
super()._props_set(obj, **kwargs)
except mEx.MultiError as multi_err:
mLo.Lo.print(f"{self.__class__.__name__}.apply(): Unable to set Property")
for err in multi_err.errors:
mLo.Lo.print(f" {err}")
# region apply()
# pylint: disable=arguments-differ
@overload
def apply(self, obj: Any) -> None: ...
@overload
def apply(self, obj: Any, **kwargs) -> None: ...
[docs] @override
def apply(self, obj: Any, **kwargs) -> None:
"""
Applies padding to ``obj``
Args:
obj (Any): UNO Object such as a Document, Spreadsheet, or ``XStyle``
Returns:
None:
"""
if mLo.Lo.is_uno_interfaces(obj, "com.sun.star.style.XStyle"):
if not self._is_obj_service(obj):
self._print_not_valid_srv(method_name="apply")
return
props = mLo.Lo.qi(XPropertySet, obj)
if props is None:
mLo.Lo.print(
f"{self.__class__.__name__}.apply(): Not a UNO Object for style. Unable to set Style Properties"
)
return
else:
if not self._is_valid_doc(obj):
mLo.Lo.print(
f"{self.__class__.__name__}.apply(): Not a UNO Object for style. Unable to set Style Properties"
)
return
props = self.get_style_props(obj)
super().apply(props, **kwargs)
# endregion apply()
# region copy()
@overload
def copy(self: _TStyleModifyMulti) -> _TStyleModifyMulti: ...
@overload
def copy(self: _TStyleModifyMulti, **kwargs) -> _TStyleModifyMulti: ...
[docs] @override
def copy(self: _TStyleModifyMulti, **kwargs) -> _TStyleModifyMulti: # type: ignore
"""Gets a copy of instance as a new instance"""
inst_copy = super().copy(**kwargs)
inst_copy.prop_style_name = self.prop_style_name
return inst_copy
# endregion copy()
# endregion Overrides
# region internal methods
def _is_valid_doc(self, obj: Any) -> bool: # pylint: disable=unused-argument
return True
# return mInfo.Info.is_doc_type(obj, mLo.Lo.Service.WRITER)
def _get_style_family_name(self) -> str:
if not self._style_family_name:
raise ValueError("Must set internal property _style_family_name")
return self._style_family_name
# endregion internal methods
# region Methods
[docs] def get_style_props(self, doc: Any) -> XPropertySet:
"""
Gets the Style Properties
Args:
doc (Any): UNO Document Object.
Raises:
NotSupportedDocumentError: If document is not supported.
Returns:
XPropertySet: Styles properties property set.
"""
if not self._is_valid_doc(doc):
raise mEx.NotSupportedDocumentError
return mInfo.Info.get_style_props(doc, self._get_style_family_name(), self.prop_style_name)
# endregion Methods
# region Properties
@property
@override
def prop_format_kind(self) -> FormatKind:
"""Gets the kind of style"""
try:
return self._format_kind_prop
except AttributeError:
self._format_kind_prop = FormatKind.DOC | FormatKind.STYLE
return self._format_kind_prop
@property
def prop_style_name(self) -> str:
"""
Gets/Sets property Style Name.
Raises:
NotImplementedError:
"""
raise NotImplementedError
@prop_style_name.setter
def prop_style_name(self, value: str):
raise NotImplementedError
@property
def prop_style_family_name(self) -> str:
"""Gets/Set Style Family Name"""
return self._style_family_name
@prop_style_family_name.setter
def prop_style_family_name(self, value: str):
self._style_family_name = value
# endregion Properties
# endregion Style Modify Multi class
# region StyleName Class
[docs]class StyleName(StyleBase):
"""Style Name Base Class"""
# region Init
[docs] def __init__(self, name: Any, **kwargs) -> None:
"""
Constructor
Args:
name (Any): Style Name.
Raises:
ValueError: If Name is ``None`` or empty string.
"""
# sourcery skip: dict-assign-update-to-union
if not name and name != "":
raise ValueError("Name is required.")
init_vars = {self._get_property_name(): str(name)}
init_vars.update(kwargs)
super().__init__(**init_vars)
# endregion Init
# region methods
[docs] def get_style_props(self) -> XPropertySet:
"""
Gets Style as ``XPropertySet`` that contains all style properties.
Returns:
XPropertySet: Returns result also implements ``com.sun.star.style.XStyle``
.. versionadded:: 0.9.2
"""
doc = mLo.Lo.this_component
if doc is None:
# most likely in headless mode with option dynamic set to True
doc = mLo.Lo.lo_component
return mInfo.Info.get_style_props(
doc=doc, family_style_name=self._get_family_style_name(), prop_set_nm=self.prop_name
)
# endregion methods
# region internal methods
def _get_family_style_name(self) -> str:
raise NotImplementedError
def _get_property_name(self) -> str:
# sourcery skip: raise-from-previous-error
try:
return self._style_property_name # type: ignore
except AttributeError:
# pylint: disable=raise-missing-from
raise NotImplementedError
# endregion internal methods
# region Overrides
def _on_modifying(self, source: Any, event_args: CancelEventArgs) -> None:
if self._is_default_inst:
raise ValueError("Modifying a default instance is not allowed")
return super()._on_modifying(source, event_args)
# endregion Overrides
# region Static Methods
# region from_obj()
@overload
@classmethod
def from_obj(cls: Type[TStyleName], obj: Any) -> TStyleName: ...
@overload
@classmethod
def from_obj(cls: Type[TStyleName], obj: Any, **kwargs) -> TStyleName: ...
[docs] @classmethod
def from_obj(cls: Type[TStyleName], obj: Any, **kwargs) -> TStyleName:
"""
Gets instance from object
Args:
obj (Any): UNO object.
Raises:
NotSupportedError: If ``obj`` is not supported.
Returns:
TStyleName: ``TStyleName`` instance that represents ``obj`` style.
"""
# pylint: disable=protected-access
inst = cls(**kwargs)
if mInfo.Info.support_service(obj, "com.sun.star.style.CellStyle"):
cell_style = cast("CellStyle", obj)
name = cell_style.getName()
inst.prop_name = name
return inst
if not inst._is_valid_obj(obj):
raise mEx.NotSupportedError(f'Object is not supported for conversion to "{cls.__name__}"')
if name := mProps.Props.get(obj, inst._get_property_name(), ""):
inst.prop_name = name
return inst
# endregion from_obj()
# endregion Static Methods
# region Properties
@property
def prop_format_kind(self) -> FormatKind:
"""Gets the kind of style"""
try:
return self._format_kind_prop
except AttributeError:
self._format_kind_prop = FormatKind.STYLE | FormatKind.STATIC
return self._format_kind_prop
@property
def prop_name(self) -> str:
"""Gets/Sets style name"""
return self._get(self._get_property_name())
@prop_name.setter
def prop_name(self, value: Any) -> None:
if not value:
raise ValueError("Value must not be None or Empty string.")
self._set(self._get_property_name(), str(value))
# endregion Properties
# endregion StyleName Class
# region Props Property event handlers
def _on_props_setting(
source: Any, event_args: KeyValCancelArgs, *args, **kwargs # pylint: disable=unused-argument
) -> None:
# pylint: disable=protected-access
instance = cast(StyleBase, event_args.event_source)
instance.on_property_setting(source, event_args)
instance._events.trigger(FormatNamedEvent.STYLE_PROPERTY_APPLYING, event_args)
def _on_props_set(source: Any, event_args: KeyValArgs, *args, **kwargs) -> None: # pylint: disable=unused-argument
# pylint: disable=protected-access
instance = cast(StyleBase, event_args.event_source)
instance.on_property_set(source, event_args)
instance._events.trigger(FormatNamedEvent.STYLE_PROPERTY_APPLIED, event_args)
def _on_props_set_error(
source: Any, event_args: KeyValCancelArgs, *args, **kwargs # pylint: disable=unused-argument
) -> None:
# pylint: disable=protected-access
instance = cast(StyleBase, event_args.event_source)
instance.on_property_set_error(source, event_args)
instance._events.trigger(FormatNamedEvent.STYLE_PROPERTY_ERROR, event_args)
def _on_props_restore_setting(
source: Any, event_args: KeyValCancelArgs, *args, **kwargs # pylint: disable=unused-argument
) -> None:
# pylint: disable=protected-access
instance = cast(StyleBase, event_args.event_source)
instance.on_property_restore_setting(source, event_args)
instance._events.trigger(FormatNamedEvent.STYLE_PROPERTY_RESTORING, event_args)
def _on_props_restore_set(
source: Any, event_args: KeyValArgs, *args, **kwargs # pylint: disable=unused-argument
) -> None:
# pylint: disable=protected-access
instance = cast(StyleBase, event_args.event_source)
instance.on_property_restore_set(source, event_args)
instance._events.trigger(FormatNamedEvent.STYLE_PROPERTY_RESTORED, event_args)
# endregion Props Property event handlers
__all__ = ("StyleBase", "StyleMulti", "StyleModifyMulti", "StyleName", "TStyleBase", "TStyleMulti", "TStyleName")