Source code for ooodev.format.inner.direct.write.table.props.table_properties

# region Imports
from __future__ import annotations
from typing import Any, Tuple, Type, TypeVar, NamedTuple, Union, cast, overload
from enum import Enum
import math
from ooo.dyn.text.hori_orientation import HoriOrientation

from ooodev.events.args.key_val_cancel_args import KeyValCancelArgs
from ooodev.exceptions import ex as mEx
from ooodev.loader import lo as mLo
from ooodev.utils import props as mProps
from ooodev.utils.data_type.intensity import Intensity
from ooodev.utils.data_type.size import Size
from ooodev.units.unit_obj import UnitT
from ooodev.units.unit_mm import UnitMM
from ooodev.format.inner.common.abstract.abstract_document import AbstractDocument
from ooodev.format.inner.kind.format_kind import FormatKind
from ooodev.format.inner.style_base import StyleMulti
from ooodev.format.inner.common.props.table_properties_props import TablePropertiesProps

from ooodev.units.unit_convert import UnitConvert

# endregion Imports

# region Types

_TTableProperties = TypeVar("_TTableProperties", bound="TableProperties")
_TSharedAuto = TypeVar("_TSharedAuto", bound="_SharedAuto")
_TTblAuto = TypeVar("_TTblAuto", bound="_TblAuto")
_TTblRelLeftByWidth = TypeVar("_TTblRelLeftByWidth", bound="_TblRelLeftByWidth")
TblAbsUnit = Union[float, UnitT]
TblRelUnit = Union[int, Intensity]

# endregion Types


# region Enums
[docs]class TableAlignKind(Enum): MANUAL = HoriOrientation.NONE """No hard alignment is applied.""" AUTO = HoriOrientation.FULL """The object uses the full space (for text tables only).""" CENTER = HoriOrientation.CENTER """The object is aligned at the middle.""" LEFT = HoriOrientation.LEFT """The object is aligned at the left side.""" RIGHT = HoriOrientation.RIGHT """The object is aligned at the right side.""" FROM_LEFT = HoriOrientation.LEFT_AND_WIDTH """ The left offset and the width of the object are defined. For text tables this means that the tables position is defined by the left margin and the width. """
# endregion Enums # region Tuples class _RelVals(NamedTuple): """Relative values. Total expected to add up to ``100``""" left: int right: int balance: int # endregion Tuples # region Module Methods def _get_default_tbl_props() -> TablePropertiesProps: return TablePropertiesProps( name="Name", width="Width", left="LeftMargin", top="TopMargin", right="RightMargin", bottom="BottomMargin", is_rel="IsWidthRelative", rel_width="RelativeWidth", hori_orient="HoriOrient", ) def _get_default_tbl_services() -> Tuple[str]: return ("com.sun.star.text.TextTable",) # endregion Module Methods class _SharedAuto(AbstractDocument): """ Automatically set table width. """ # region Init def __init__( self, *, width: TblAbsUnit | TblRelUnit | None = None, left: TblAbsUnit | TblRelUnit | None = None, right: TblAbsUnit | TblRelUnit | None = None, above: TblAbsUnit | TblRelUnit | None = None, below: TblAbsUnit | TblRelUnit | None = None, ) -> None: """ Constructor Args: width (TblAbsUnit, optional): Table width value in ``mm`` units or :ref:`proto_unit_obj`. Default ``0``. left (TblAbsUnit, optional): Spacing Left value in ``mm`` units or :ref:`proto_unit_obj`. Default ``0``. right (TblAbsUnit, optional): Spacing Right value in ``mm`` units or :ref:`proto_unit_obj`. Default ``0``. above (TblAbsUnit, optional): Spacing Above value in ``mm`` units or :ref:`proto_unit_obj`. Default ``0``. below (TblAbsUnit, optional): Spacing Below value in ``mm`` units or :ref:`proto_unit_obj`. Default ``0``. """ # only Above and Below properties are used in this class super().__init__() self.prop_width = width self.prop_left = left self.prop_right = right if above is not None: self.prop_above = above if below is not None: self.prop_below = below self._post_init() # endregion Init # region internal methods def _post_init(self) -> None: self._set(self._props.hori_orient, TableAlignKind.AUTO.value) def _get_relative_values(self) -> _RelVals: left100: int = self._get(self._props.left) right100: int = self._get(self._props.right) page_txt_width = self._prop_page_text_size.width left = 0 if left100 == 0 else round((left100 / page_txt_width) * 100) right = 0 if right100 == 0 else round((right100 / page_txt_width) * 100) width = 100 - (left + right) return _RelVals(left=left, right=right, balance=width) def _set_props_from_obj(self, obj: Any) -> None: if not self._is_valid_obj(obj): raise mEx.NotSupportedError(f'Object is not supported for conversion to "{self.__class__.__name__}"') self._set(self._props.left, mProps.Props.get(obj, self._props.left)) self._set(self._props.right, mProps.Props.get(obj, self._props.right)) self._set(self._props.top, mProps.Props.get(obj, self._props.top)) self._set(self._props.bottom, mProps.Props.get(obj, self._props.bottom)) self._set(self._props.width, mProps.Props.get(obj, self._props.width)) self._set(self._props.hori_orient, mProps.Props.get(obj, self._props.hori_orient)) self._set(self._props.is_rel, mProps.Props.get(obj, self._props.is_rel)) self._set(self._props.rel_width, mProps.Props.get(obj, self._props.rel_width)) self._prop_width = int(self._get(self._props.width)) self._prop_left = int(self._get(self._props.left)) self._prop_right = int(self._get(self._props.right)) def _get_prop_width(self) -> UnitMM | None: if self._prop_width is None: return None return UnitMM.from_mm100(self._prop_width) def _set_prop_width(self, value: TblAbsUnit | TblRelUnit | None) -> None: if value is None: self._prop_width = None return try: val = value.get_value_mm100() # type: ignore except AttributeError: val = UnitConvert.convert_mm_mm100(value) # type: ignore # min table width seems to be in the area of 1.22 mm val = max(val, 122) self._prop_width = val def _get_prop_left(self) -> UnitMM | None: return None if self._prop_left is None else UnitMM.from_mm100(self._prop_left) def _set_prop_left(self, value: TblAbsUnit | TblRelUnit | None) -> None: if value is None: self._prop_left = None return try: val = value.get_value_mm100() # type: ignore except AttributeError: val = UnitConvert.convert_mm_mm100(value) # type: ignore self._prop_left = val def _get_prop_right(self) -> UnitMM | None: if self._prop_right is None: return None return UnitMM.from_mm100(self._prop_right) def _set_prop_right(self, value: TblAbsUnit | TblRelUnit | None) -> None: if value is None: self._prop_right = None return try: val = value.get_value_mm100() # type: ignore except AttributeError: val = UnitConvert.convert_mm_mm100(value) # type: ignore self._prop_right = val def _get_prop_above(self) -> UnitMM | None: pv = self._get(self._props.top) return None if pv is None else UnitMM.from_mm100(pv) def _set_prop_above(self, value: TblAbsUnit | TblRelUnit | None) -> None: if value is None: self._remove(self._props.top) return try: val = value.get_value_mm100() # type: ignore except AttributeError: val = UnitConvert.convert_mm_mm100(value) # type: ignore self._set(self._props.top, val) def _get_prop_below(self) -> UnitMM | None: pv = self._get(self._props.bottom) return None if pv is None else UnitMM.from_mm100(pv) def _set_prop_below(self, value: TblAbsUnit | TblRelUnit | None) -> None: if value is None: self._remove(self._props.bottom) return try: val = value.get_value_mm100() # type: ignore except AttributeError: val = UnitConvert.convert_mm_mm100(value) # type: ignore self._set(self._props.bottom, val) # endregion internal methods # region overrides def copy(self: _TSharedAuto, **kwargs) -> _TSharedAuto: """Gets a copy of the instance""" cp = super().copy(**kwargs) cp._prop_width = self._prop_width cp._prop_left = self._prop_left cp._prop_right = self._prop_right return cp def _supported_services(self) -> Tuple[str, ...]: try: return self._supported_services_values except AttributeError: self._supported_services_values = _get_default_tbl_services() return self._supported_services_values def _set_defaults(self) -> None: if not self._has(self._props.width): self._set(self._props.width, self._prop_page_text_size.width) self._prop_width = self._prop_page_text_size.width if not self._has(self._props.left): self._set(self._props.left, 0) self._prop_left = 0 if not self._has(self._props.right): self._set(self._props.right, 0) self._prop_right = 0 if not self._has(self._props.rel_width): self._set(self._props.rel_width, 0) def apply(self, obj: Any, **kwargs) -> None: """ Applies Styling to object Args: obj (object): UNO Table Object Returns: None: """ self._set_defaults() super().apply(obj, **kwargs) try: self._set_props_from_obj(obj) except Exception as e: mLo.Lo.print(f"Unable to set property values for {self.__class__.__name__} after apply method.") mLo.Lo.print(f" {e}") # endregion overrides # region static methods # region from_obj() @overload @classmethod def from_obj(cls: Type[_TSharedAuto], obj: Any) -> _TSharedAuto: ... @overload @classmethod def from_obj(cls: Type[_TSharedAuto], obj: Any, **kwargs) -> _TSharedAuto: ... @classmethod def from_obj(cls: Type[_TSharedAuto], obj: Any, **kwargs) -> _TSharedAuto: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblAuto: ``TblAuto`` Instance. """ return _SharedAuto._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TSharedAuto], obj: Any, **kwargs) -> _TSharedAuto: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: Options: Instance that represents Frame Wrap Settings. """ # pylint: disable=protected-access inst = clazz(**kwargs) if not inst._is_valid_obj(obj): raise mEx.NotSupportedError(f'Object is not supported for conversion to "{clazz.__name__}"') inst._set_props_from_obj(obj) inst.set_update_obj(obj) 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.TABLE return self._format_kind_prop @property def prop_width(self) -> UnitMM | None: """ Gets/Sets Width. """ return self._get_prop_width() @prop_width.setter def prop_width(self, value: TblAbsUnit | TblRelUnit | None): self._set_prop_width(value) @property def prop_left(self) -> UnitMM | None: """ Gets/Sets Left. """ return self._get_prop_left() @prop_left.setter def prop_left(self, value: TblAbsUnit | TblRelUnit | None): self._set_prop_left(value) @property def prop_right(self) -> UnitMM | None: """ Gets/Sets Right. """ return self._get_prop_right() @prop_right.setter def prop_right(self, value: TblAbsUnit | TblRelUnit | None): self._set_prop_right(value) @property def prop_above(self) -> UnitMM | None: """ Gets/Sets above. """ return self._get_prop_above() @prop_above.setter def prop_above(self, value: TblAbsUnit | TblRelUnit | None): self._set_prop_above(value) @property def prop_below(self) -> UnitMM | None: """ Gets/Sets below. """ return self._get_prop_below() @prop_below.setter def prop_below(self, value: TblAbsUnit | TblRelUnit | None): self._set_prop_below(value) @property def _props(self) -> TablePropertiesProps: try: return self._props_internal_attributes except AttributeError: self._props_internal_attributes = _get_default_tbl_props() return self._props_internal_attributes @property def _prop_page_text_size(self) -> Size: """Page Text Size in ``1/100th mm``: Only Call In ``apply()`` Method""" # keep private. Not available until writer doc is created. try: return self._prop_page_text_size_attrib except AttributeError: self._prop_page_text_size_attrib = self.get_page_text_size() return self._prop_page_text_size_attrib @property def _prop_page_size(self) -> Size: """Page Size in ``1/100th mm``: Only Call In ``apply()`` Method""" # keep private. Not available until writer doc is created. try: return self._prop_page_size_attrib except AttributeError: self._prop_page_size_attrib = self.get_page_size() return self._prop_page_size_attrib # endregion Properties # region Table size in MM units class _TblAuto(_SharedAuto): def __init__( self, *, width: TblAbsUnit | None = None, left: TblAbsUnit | None = None, right: TblAbsUnit | None = None, above: TblAbsUnit | None = None, below: TblAbsUnit | None = None, ) -> None: """ Constructor Args: width (TblAbsUnit, optional): Table width value in ``mm`` units or :ref:`proto_unit_obj`. Default ``0``. left (TblAbsUnit, optional): Spacing Left value in ``mm`` units or :ref:`proto_unit_obj`. Default ``0``. right (TblAbsUnit, optional): Spacing Right value in ``mm`` units or :ref:`proto_unit_obj`. Default ``0``. above (TblAbsUnit, optional): Spacing Above value in ``mm`` units or :ref:`proto_unit_obj`. Default ``0``. below (TblAbsUnit, optional): Spacing Below value in ``mm`` units or :ref:`proto_unit_obj`. Default ``0``. """ # only Above and Below properties are used in this class super().__init__(width=width, left=left, right=right, above=above, below=below) # region Static Methods # region from_obj() @overload @classmethod def from_obj(cls: Type[_TTblAuto], obj: Any) -> _TTblAuto: ... @overload @classmethod def from_obj(cls: Type[_TTblAuto], obj: Any, **kwargs) -> _TTblAuto: ... @classmethod def from_obj(cls: Type[_TTblAuto], obj: Any, **kwargs) -> _TTblAuto: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblAuto: ``TblAuto`` Instance. """ return _TblAuto._from_obj(cls, obj, **kwargs) # endregion from_obj() @staticmethod def _from_obj(clazz: Type[_TTblAuto], obj: Any, **kwargs) -> _TTblAuto: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: Options: Instance that represents Frame Wrap Settings. """ inst = clazz(**kwargs) if not inst._is_valid_obj(obj): raise mEx.NotSupportedError(f'Object is not supported for conversion to "{clazz.__name__}"') inst._set_props_from_obj(obj) return inst # endregion Static Methods # region Properties @property def prop_width(self) -> UnitMM | None: """ Gets/Sets Width. """ return self._get_prop_width() @prop_width.setter def prop_width(self, value: TblAbsUnit | None): self._set_prop_width(value) @property def prop_left(self) -> UnitMM | None: """ Gets/Sets Left. """ return self._get_prop_left() @prop_left.setter def prop_left(self, value: TblAbsUnit | None): self._set_prop_left(value) @property def prop_right(self) -> UnitMM | None: """ Gets/Sets Right. """ return self._get_prop_right() @prop_right.setter def prop_right(self, value: TblAbsUnit | None): self._set_prop_right(value) @property def prop_above(self) -> UnitMM | None: """ Gets/Sets above. """ return self._get_prop_above() @prop_above.setter def prop_above(self, value: TblAbsUnit | None): self._set_prop_above(value) @property def prop_below(self) -> UnitMM | None: """ Gets/Sets below. """ return self._get_prop_below() @prop_below.setter def prop_below(self, value: TblAbsUnit | None): self._set_prop_below(value) # endregion Properties class _TblCenterWidth(_TblAuto): """ Sets the table width using a width value and centers the table. """ # Only width, above and below properties are used in this class # only width is used directly # region internal Methods def _set_width_properties(self, obj: Any) -> None: # max right value is the neg value of page text area # max width is page text area * 2 if self.prop_width is None: return page_txt_width = self._prop_page_text_size.width width100 = self.prop_width.get_value_mm100() if width100 > page_txt_width * 2: width100 = page_txt_width * 2 margin = -page_txt_width else: # calculate the margins # if width100 is greater then page_txt_width then margins are negative. margin = page_txt_width - width100 if margin == 0: left_margin = 0 right_margin = 0 else: left_margin = round(margin / 2) right_margin = left_margin if margin > 0: while right_margin + left_margin > margin: # just in case rounding add a digit or two right_margin -= 1 elif margin < 0: while right_margin + left_margin < margin: # just in case rounding add a digit or two right_margin += 1 self._set(self._props.left, left_margin) self._set(self._props.right, right_margin) self._set(self._props.width, width100) # endregion internal Methods # region overrides def _post_init(self) -> None: self._set(self._props.hori_orient, TableAlignKind.CENTER.value) def apply(self, obj: Any, **kwargs) -> None: """ Applies Styling to object Args: obj (object): UNO Table Object Returns: None: """ self._set_width_properties(obj) super().apply(obj, **kwargs) # endregion overrides # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblCenterWidth: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblCenterWidth: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblCenterWidth: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblCenterWidth: ``TblCenterWidth`` Instance. """ return _TblCenterWidth._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblAuto], obj: Any, **kwargs) -> _TTblAuto: return _TblAuto._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods class _TblLeft(_TblCenterWidth): """ Sets the right table margin. """ # right, above, and below properties are used in this class. # only right is used directly in this class. # region internal Methods def _set_width_properties(self, obj: Any) -> None: # max right value is the neg value of page text area # max width is page text area * 2 if self.prop_right is None: return self._set(self._props.left, 0) page_txt_width = self._prop_page_text_size.width margin = self.prop_right.get_value_mm100() if margin == 0: self._set(self._props.right, 0) self._set(self._props.width, page_txt_width) return if margin > 0: # minimum width allowed for table seems to be 1.22 mm min_width100 = 122 if margin > page_txt_width + min_width100: margin = page_txt_width - min_width100 width100 = page_txt_width - margin self._set(self._props.width, width100) self._set(self._props.right, margin) return # margin is negative if abs(margin) > page_txt_width: margin = -page_txt_width width100 = abs(margin) + page_txt_width self._set(self._props.width, width100) self._set(self._props.right, margin) # endregion internal Methods # region Overrides def _post_init(self) -> None: self._set(self._props.hori_orient, TableAlignKind.LEFT.value) # endregion Overrides # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblLeft: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblLeft: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblLeft: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblLeft: ``TblLeft`` Instance. """ return _TblLeft._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblAuto], obj: Any, **kwargs) -> _TTblAuto: return _TblCenterWidth._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods class _TblLeftWidth(_TblLeft): """ Sets the right table margin. """ # right, above, and below properties are used in this class. # only right is used directly in this class. # region internal Methods def _set_width_properties(self, obj: Any) -> None: # max right value is the neg value of page text area # max width is page text area * 2 if self.prop_width is None: return self._set(self._props.left, 0) tbl_min_width = 122 page_txt_width = self._prop_page_text_size.width width = self.prop_width.get_value_mm100() if width <= tbl_min_width: self._set(self._props.right, page_txt_width - tbl_min_width) self._set(self._props.width, tbl_min_width) return if width >= page_txt_width: self._set(self._props.right, 0) self._set(self._props.width, page_txt_width) return right = page_txt_width - width self._set(self._props.right, right) self._set(self._props.width, width) # endregion internal Methods # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblLeftWidth: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblLeftWidth: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblLeftWidth: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblLeftWidth: ``TblLeftWidth`` Instance. """ return _TblLeftWidth._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblAuto], obj: Any, **kwargs) -> _TTblAuto: return _TblLeft._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods class _TblRight(_TblLeft): """ Sets the left table margin. """ # left, above, and below properties are used in this class. # only left is used directly in this class. # region override Methods def _post_init(self) -> None: self._set(self._props.hori_orient, TableAlignKind.RIGHT.value) def _set_width_properties(self, obj: Any) -> None: # max right value is the neg value of page text area # max width is page text area * 2 if self.prop_left is None: return self._set(self._props.right, 0) page_txt_width = self._prop_page_text_size.width margin = self.prop_left.get_value_mm100() if margin == 0: self._set(self._props.left, 0) self._set(self._props.width, page_txt_width) return if margin > 0: # minimum width allowed for table seems to be 1.22 mm min_width100 = 122 if margin > page_txt_width + min_width100: margin = page_txt_width - min_width100 width100 = page_txt_width - margin self._set(self._props.width, width100) self._set(self._props.left, margin) return # margin is negative if abs(margin) > page_txt_width: margin = -page_txt_width width100 = abs(margin) + page_txt_width self._set(self._props.width, width100) self._set(self._props.left, margin) # endregion override Methods # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblRight: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRight: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRight: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblRight: ``TblRight`` Instance. """ return _TblRight._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblAuto], obj: Any, **kwargs) -> _TTblAuto: return _TblLeft._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods class _TblRightWidth(_TblRight): """ Sets the left table margin. """ # region override Methods def _set_width_properties(self, obj: Any) -> None: if self.prop_width is None: return self._set(self._props.right, 0) tbl_min_width = 122 page_txt_width = self._prop_page_text_size.width width = self.prop_width.get_value_mm100() if width <= tbl_min_width: self._set(self._props.left, page_txt_width - tbl_min_width) self._set(self._props.width, tbl_min_width) return if width >= page_txt_width: self._set(self._props.left, 0) self._set(self._props.width, page_txt_width) return left = page_txt_width - width self._set(self._props.left, left) self._set(self._props.width, width) # endregion override Methods # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblRightWidth: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRightWidth: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRightWidth: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblRightWidth: ``TblRightWidth`` Instance. """ return _TblRightWidth._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblAuto], obj: Any, **kwargs) -> _TTblAuto: return _TblRight._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods class _TblCenterLeft(_TblLeft): """ Sets the table width using a width value and centers the table. """ # left, above, and below properties are used in this class. # only left is used directly in this class. # region override Methods def _post_init(self) -> None: self._set(self._props.hori_orient, TableAlignKind.CENTER.value) def _set_width_properties(self, obj: Any) -> None: # max right value is the neg value of page text area # max width is page text area * 2 if self.prop_left is None: return page_txt_width = self._prop_page_text_size.width margin = self.prop_left.get_value_mm100() # minimum width allowed for table seems to be 1.22 mm min_width100 = 122 if margin == 0: self._set(self._props.left, 0) self._set(self._props.right, 0) self._set(self._props.width, page_txt_width) return # left_margin = round(abs(margin) / 2) width = page_txt_width - (margin * 2) if width < min_width100: self._set(self._props.left, round(page_txt_width - (min_width100 / 2))) self._set(self._props.right, round(page_txt_width - (min_width100 / 2))) self._set(self._props.width, min_width100) return self._set(self._props.width, width) self._set(self._props.left, margin) self._set(self._props.right, margin) # endregion override Methods # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblCenterLeft: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblCenterLeft: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblCenterLeft: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblCenterLeft: ``TblCenterLeft`` Instance. """ return _TblCenterLeft._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblAuto], obj: Any, **kwargs) -> _TTblAuto: return _TblLeft._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods class _TblFromLeft(_TblLeft): """ Sets the table width from left using a margin value. """ # left, above, and below properties are used in this class. # only left is used directly in this class. # region override Methods def _post_init(self) -> None: self._set(self._props.hori_orient, TableAlignKind.FROM_LEFT.value) def _set_width_properties(self, obj: Any) -> None: # the total of width + left + right = page_txt_width # when left changes the width remains the same and right can become a neg value # if width exceeds page_txt_width then is set to page_txt_width, left and right become 0 # min table width 1.22 mm # if left exceeds page_txt_width then left is set to page_txt_width, width is unchanged and right is set to neg width if self.prop_left is None: return page_txt_width = self._prop_page_text_size.width margin = self.prop_left.get_value_mm100() tbl_width = int(mProps.Props.get(obj, self._props.width)) if margin >= page_txt_width: self._set(self._props.left, page_txt_width) self._set(self._props.right, -tbl_width) return right = page_txt_width - tbl_width - margin assert right + margin + tbl_width == page_txt_width self._set(self._props.left, margin) self._set(self._props.right, right) # endregion override Methods # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblFromLeft: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblFromLeft: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblFromLeft: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblFromLeft: ``TblFromLeft`` Instance. """ return _TblFromLeft._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblAuto], obj: Any, **kwargs) -> _TTblAuto: return _TblLeft._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods class _TblFromLeftWidth(_TblCenterWidth): """ Sets the table width from left using a width value. """ # width, above, and below properties are used in this class. # only width is used directly in this class. # region override Methods def _post_init(self) -> None: self._set(self._props.hori_orient, TableAlignKind.FROM_LEFT.value) def _set_width_properties(self, obj: Any) -> None: # sourcery skip: extract-duplicate-method # the total of width + left + right = page_txt_width. # when width changes left stays the same and right gets adjusted conditionally. # if right is 0 then width will reduce left. # if width exceeds page_txt_width then is set to page_txt_width, left and right become 0/ # min table width 1.22 mm. if self.prop_width is None: return page_txt_width = self._prop_page_text_size.width tbl_min_width = 122 width100 = self.prop_width.get_value_mm100() if width100 >= page_txt_width: self._set(self._props.right, 0) self._set(self._props.left, 0) self._set(self._props.width, page_txt_width) return if width100 < tbl_min_width: # min width: self._set(self._props.right, 0) self._set(self._props.left, page_txt_width - tbl_min_width) self._set(self._props.width, tbl_min_width) return left = page_txt_width - width100 self._set(self._props.right, 0) self._set(self._props.left, left) self._set(self._props.width, width100) # endregion override Methods # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblFromLeftWidth: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblFromLeftWidth: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblFromLeftWidth: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblFromLeftWidth: ``TblFromLeftWidth`` Instance. """ return _TblFromLeftWidth._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblAuto], obj: Any, **kwargs) -> _TTblAuto: return _TblCenterWidth._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods class _TblManualLeftRight(_TblCenterWidth): """ Sets the table width manually. """ # all properties of init are used in this class # region Overrides def _post_init(self) -> None: self._set(self._props.hori_orient, TableAlignKind.MANUAL.value) def _set_width_properties(self, obj: Any) -> None: # sourcery skip: extract-duplicate-method, use-assigned-variable # left, right, width must added up to page_txt_width if self.prop_left is None or self.prop_right is None: return page_txt_width = self._prop_page_text_size.width tbl_min_width = 122 left100 = self.prop_left.get_value_mm100() right100 = self.prop_right.get_value_mm100() width = page_txt_width - (left100 + right100) if width < tbl_min_width: # min width: left = round((page_txt_width / 2) + (tbl_min_width / 2)) right = left self._set(self._props.right, right) self._set(self._props.left, left) self._set(self._props.width, tbl_min_width) mLo.Lo.print( f"{self.__class__.__name__}. Unable to calculate proper table width. Result is less than min table width. Setting to full width." ) return self._set(self._props.right, right100) self._set(self._props.left, left100) self._set(self._props.width, width) # endregion Overrides # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblManualLeftRight: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblManualLeftRight: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblManualLeftRight: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblManualLeftRight: ``TblManualLeftRight`` Instance. """ return _TblManualLeftRight._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblAuto], obj: Any, **kwargs) -> _TTblAuto: return _TblCenterWidth._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods class _TblManualCenter(_TblManualLeftRight): """ Sets the table width manually. """ # all properties of init are used in this class # region Overrides def _set_width_properties(self, obj: Any) -> None: # get the left, right and center values. # Calculate the difference between current width and # existing width. Apply the values if self.prop_width is None: return page_txt_width = self._prop_page_text_size.width tbl_min_width = 122 width = self.prop_width.get_value_mm100() if width < tbl_min_width: mLo.Lo.print("Unable to change Table width. New Width is less then table min width.") return tbl_width = int(mProps.Props.get(obj, self._props.width)) tbl_left = int(mProps.Props.get(obj, self._props.left)) tbl_right = int(mProps.Props.get(obj, self._props.right)) diff = tbl_width - width left = tbl_left + round(diff / 2) right = tbl_right + round(diff / 2) # make and minor adjustments need from rounding. while width + left + right > page_txt_width: if left >= 0: left -= 1 else: left += 1 if width + left + right == page_txt_width: break if right >= 0: right -= 1 else: right += 1 while width + left + right < page_txt_width: if left >= 0: left += 1 else: left -= 1 if width + left + right == page_txt_width: break if right >= 0: right += 1 else: right -= 1 self._set(self._props.left, left) self._set(self._props.right, right) self._set(self._props.width, width) # endregion Overrides # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblManualCenter: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblManualCenter: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblManualCenter: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblManualCenter: ``TblManualCenter`` Instance. """ return _TblManualCenter._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblAuto], obj: Any, **kwargs) -> _TTblAuto: return _TblManualLeftRight._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods # endregion Table size in MM units # region Table size in percentage units class _TblRelLeftByWidth(_SharedAuto): """ Relative Table size. Set table right margin using width as a percentage value. """ # region Init def __init__( self, *, width: TblRelUnit = 100, left: TblRelUnit = 0, right: TblRelUnit = 0, above: TblRelUnit | None = None, below: TblRelUnit | None = None, ) -> None: """ Constructor Args: width (TblRelUnit, optional): Width value as a percentage from ``1`` and ``100``. Default ``100``. left (TblRelUnit, optional): Spacing Left value in ``mm`` units or :ref:`proto_unit_obj`. Default ``0``. right (TblRelUnit, optional): Spacing Right value in ``mm`` units or :ref:`proto_unit_obj`. Default ``0``. above (TblRelUnit, optional): Spacing Above value in ``mm`` units or :ref:`proto_unit_obj`. Default ``0``. below (TblRelUnit, optional): Spacing Below value in ``mm`` units or :ref:`proto_unit_obj`. Default ``0``. """ # right is omitted from constructor because it is (100 - width) # width and right are calculated and stored as 1/100th mm super().__init__(width=width, left=left, right=right, above=above, below=below) # endregion Init # region internal methods def _set_width_properties(self) -> None: page_width = self._prop_page_text_size.width self._set(self._props.left, 0) if self.prop_width.value == 100: self._set(self._props.width, page_width) self._set(self._props.right, 0) return width_factor = self.prop_width.value / 100 width = round(page_width * width_factor) right = round(page_width - width) while right + width > page_width: # just in case rounding caused total to be more than page_width right = right - 1 self._set(self._props.width, width) self._set(self._props.right, right) # endregion internal methods # region Overrides def _post_init(self) -> None: self._set(self._props.hori_orient, TableAlignKind.LEFT.value) def _set_defaults(self) -> None: if not self._has(self._props.rel_width): self._set(self._props.rel_width, self.prop_width.value) super()._set_defaults() def apply(self, obj: Any, **kwargs) -> None: self._set_width_properties() return super().apply(obj, **kwargs) def _set_props_from_obj(self, obj: Any) -> None: super()._set_props_from_obj(obj) rel = self._get_relative_values() self._prop_width = rel.balance self._prop_left = rel.left self._prop_right = rel.right # endregion Overrides # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblRelLeftByWidth: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRelLeftByWidth: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRelLeftByWidth: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblRelLeft: ``TblRelLeft`` Instance. """ return _TblRelLeftByWidth._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblRelLeftByWidth], obj: Any, **kwargs) -> _TTblRelLeftByWidth: return _SharedAuto._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods # region properties @property def prop_width(self) -> Intensity: """ Gets/Sets Width. """ return Intensity(self._prop_width) @prop_width.setter def prop_width(self, value: int | Intensity): val = Intensity(int(value)) self._prop_width = 1 if val.value == 0 else val.value @property def prop_left(self) -> Intensity: """ Gets/Sets Left. """ return Intensity(self._prop_left) @prop_left.setter def prop_left(self, value: int | Intensity): self._prop_left = Intensity(int(value)).value @property def prop_right(self) -> Intensity: """ Gets/Sets Right. """ return Intensity(self._prop_right) @prop_right.setter def prop_right(self, value: int | Intensity): self._prop_right = Intensity(int(value)).value # endregion properties class _TblRelLeftByRight(_TblRelLeftByWidth): """ Relative Table size. Set table right margin using right as a percentage value. """ # region internal methods def _set_width_properties(self) -> None: page_txt_width = self._prop_page_text_size.width tbl_min_width100 = 122 self._set(self._props.left, 0) if self.prop_right.value >= 99: self._set(self._props.rel_width, 1) self._set(self._props.width, tbl_min_width100) self._set(self._props.right, page_txt_width - tbl_min_width100) return right_factor = self.prop_right.value / 100 right = round(page_txt_width * right_factor) width = page_txt_width - right while width + right > page_txt_width: # just in case rounding caused total to be more than page_width width = width - 1 if width <= tbl_min_width100: self._set(self._props.rel_width, 1) self._set(self._props.width, tbl_min_width100) self._set(self._props.right, page_txt_width - tbl_min_width100) return # use ceil to make sure that width is at least 1 width_per = math.ceil((width / page_txt_width) * 100) self._set(self._props.right, right) self._set(self._props.width, width) self._set(self._props.rel_width, width_per) # endregion internal methods # region Overrides def _post_init(self) -> None: self._set(self._props.hori_orient, TableAlignKind.LEFT.value) def _set_defaults(self) -> None: if not self._has(self._props.rel_width): self._set(self._props.rel_width, self.prop_width.value) super()._set_defaults() # endregion Overrides # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblRelLeftByWidth: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRelLeftByWidth: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRelLeftByWidth: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblRelLeft: ``TblRelLeft`` Instance. """ return _TblRelLeftByRight._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblRelLeftByWidth], obj: Any, **kwargs) -> _TTblRelLeftByWidth: return _TblRelLeftByWidth._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods class _TblRelFromLeft(_TblRelLeftByWidth): """ Relative Table size. Sets the table relative width from left using percentage values. """ # width, left, above and below properties are used in this class # only width and left are used directly # region Overrides def _post_init(self) -> None: self._set(self._props.hori_orient, TableAlignKind.FROM_LEFT.value) def _set_width_properties(self) -> None: # if left = 0 then right is right = round(page_width - width) page_txt_width = self._prop_page_text_size.width if self.prop_width.value == 100: self._set(self._props.width, page_txt_width) self._set(self._props.right, 0) self._set(self._props.left, 0) return if self.prop_left.value + self.prop_width.value > 100: # total of left and width must not be more then 100 percent. left_per = 100 - self.prop_width.value else: left_per = self.prop_left.value width_factor = self.prop_width.value / 100 left_factor = 0 if left_per == 0 else left_per / 100 width = round(page_txt_width * width_factor) left = 0 if left_factor == 0 else round(page_txt_width * left_factor) while left + width > page_txt_width: # just in case rounding caused total to be more than page_width left -= 1 right = page_txt_width - (width + left) self._set(self._props.width, width) self._set(self._props.left, left) self._set(self._props.right, right) # endregion Overrides # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblRelFromLeft: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRelFromLeft: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRelFromLeft: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblRelFromLeft: ``TblRelFromLeft`` Instance. """ return _TblRelFromLeft._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblRelLeftByWidth], obj: Any, **kwargs) -> _TTblRelLeftByWidth: return _TblRelLeftByWidth._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods class _TblRelRightByWidth(_TblRelLeftByWidth): """ Relative Table size. Set table left margin using width as a percentage value. """ # width, left, above and below properties are used in this class # only width and left are used directly # region Overrides def _post_init(self) -> None: self._set(self._props.hori_orient, TableAlignKind.RIGHT.value) def _set_width_properties(self) -> None: # sourcery skip: extract-duplicate-method page_txt_width = self._prop_page_text_size.width if self.prop_width.value == 100: self._set(self._props.width, page_txt_width) self._set(self._props.left, 0) self._set(self._props.right, 0) return width_factor = self.prop_width.value / 100 width = round(page_txt_width * width_factor) left = round(page_txt_width - width) while left + width > page_txt_width: # just in case rounding caused total to be more than page_width left = left - 1 right = page_txt_width - width - left self._set(self._props.width, width) self._set(self._props.left, left) self._set(self._props.right, right) # endregion Overrides # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblRelRightByWidth: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRelRightByWidth: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRelRightByWidth: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblRelRight: ``TblRelRight`` Instance. """ return _TblRelRightByWidth._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblRelLeftByWidth], obj: Any, **kwargs) -> _TTblRelLeftByWidth: return _TblRelLeftByWidth._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods class _TblRelRightByLeft(_TblRelRightByWidth): """ Relative Table size. Set table left margin using left as a percentage value. """ # region internal methods def _set_width_properties(self) -> None: page_txt_width = self._prop_page_text_size.width self._set(self._props.right, 0) if self.prop_left.value >= 99: self._set(self._props.rel_width, 1) tbl_min_width100 = 122 self._set(self._props.width, tbl_min_width100) self._set(self._props.left, page_txt_width - tbl_min_width100) return left_factor = self.prop_left.value / 100 left = round(page_txt_width * left_factor) width = page_txt_width - left while width + left > page_txt_width: # just in case rounding caused total to be more than page_width width -= 1 # use ceil to make sure that width is at least 1 width_per = math.ceil((width / page_txt_width) * 100) self._set(self._props.left, left) self._set(self._props.width, width) self._set(self._props.rel_width, width_per) # endregion internal methods # region Overrides def _post_init(self) -> None: self._set(self._props.hori_orient, TableAlignKind.RIGHT.value) def _set_defaults(self) -> None: if not self._has(self._props.rel_width): self._set(self._props.rel_width, self.prop_width.value) super()._set_defaults() # endregion Overrides # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblRelLeftByWidth: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRelLeftByWidth: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRelLeftByWidth: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblRelLeft: ``TblRelLeft`` Instance. """ return _TblRelRightByLeft._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblRelLeftByWidth], obj: Any, **kwargs) -> _TTblRelLeftByWidth: return _TblRelRightByWidth._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods class _TblRelCenter(_TblRelLeftByWidth): """ Relative Table size. Set table left adn right margins using width as a percentage value. """ # width, left, above and below properties are used in this class # only width and left are used directly # region Overrides def _post_init(self) -> None: self._set(self._props.hori_orient, TableAlignKind.CENTER.value) def _set_width_properties(self) -> None: # sourcery skip: extract-duplicate-method page_width = self._prop_page_text_size.width if self.prop_width.value == 100: self._set(self._props.width, page_width) self._set(self._props.left, 0) self._set(self._props.right, 0) return width_factor = self.prop_width.value / 100 width = round(page_width * width_factor) left_right = round(page_width - width) if left_right == 0: left = 0 right = 0 else: left = round(left_right / 2) right = left while right + left + width > page_width: # just in case rounding caused total to be more than page_width width = width - 1 self._set(self._props.width, width) self._set(self._props.left, left) self._set(self._props.right, right) # endregion Overrides # region static methods # region from_obj() @overload @classmethod def from_obj(cls, obj: Any) -> _TblRelCenter: ... @overload @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRelCenter: ... @classmethod def from_obj(cls, obj: Any, **kwargs) -> _TblRelCenter: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TblRelCenter: ``TblRelCenter`` Instance. """ return _TblRelCenter._from_obj(cls, obj, **kwargs) @staticmethod def _from_obj(clazz: Type[_TTblRelLeftByWidth], obj: Any, **kwargs) -> _TTblRelLeftByWidth: return _TblRelLeftByWidth._from_obj(clazz, obj, **kwargs) # endregion from_obj() # endregion static methods # endregion Table size in percentage units # region TableProperties Class
[docs]class TableProperties(StyleMulti): """ Table options. Table horizontal position can be modified in many ways. This class generally follow how value are entered into the Table Properties dialog box of writer. ``name``, ``above`` and ``below`` parameters values are accepted for all states. When ``relative`` is ``True`` the following are required. .. cssclass:: ul-list - ``align=TableAlignKind.AUTO``, Not supported. Raises ``ValueError``. - ``align=TableAlignKind.CENTER``, ``width`` and ``left`` are required. - ``align=TableAlignKind.FROM_LEFT``, ``width`` and ``left`` are required. - ``align=TableAlignKind.LEFT``, ``width`` or ``right`` are required. - ``align=TableAlignKind.MANUAL``, Not supported. Raises ``ValueError``. - ``align=TableAlignKind.RIGHT``, ``width`` or ``left`` are required. When ``relative`` is ``False`` the following are required. .. cssclass:: ul-list - ``align=TableAlignKind.AUTO``, no extra parameters are required. - ``align=TableAlignKind.CENTER``, ``width`` or ``left`` are required. - ``align=TableAlignKind.FROM_LEFT``, ``width`` or ``left`` are required. - ``align=TableAlignKind.LEFT``, ``width`` or ``right`` is required. - ``align=TableAlignKind.MANUAL``, ``width``, ``left`` and ``right`` are required. - ``align=TableAlignKind.RIGHT``, ``width`` or ``left`` is required. .. versionadded:: 0.9.0 """ # region Init
[docs] def __init__( self, *, name: str | None = None, width: TblAbsUnit | TblRelUnit | None = None, left: TblAbsUnit | TblRelUnit | None = None, right: TblAbsUnit | TblRelUnit | None = None, above: TblAbsUnit | TblRelUnit | None = None, below: TblAbsUnit | TblRelUnit | None = None, align: TableAlignKind | None = None, relative: bool = False, ) -> None: """ Constructor Args: name (str, optional): Specifies frame name. Space are NOT allowed in names width (TblAbsUnit, TblRelUnit, optional): Specifies table Width. left (TblAbsUnit, TblRelUnit, optional): Specifies table Left. right (TblAbsUnit, TblRelUnit, optional): Specifies table Right. above (TblAbsUnit, TblRelUnit, optional): Specifies table spacing above. below (TblAbsUnit, TblRelUnit, optional): Specifies table spacing below. align (TableAlignKind, optional): Specifies table alignment. relative (bool, optional): Specifies if table horizontal values are in percentages or ``mm`` units. Raises: ValueError: If name contains spaces. Returns: None: """ super().__init__() if name: name = name.strip() if " " in name: raise ValueError("Name is not allow to contains space characters.") self.prop_name = name self._prop_align = align self._prop_relative = relative if align is not None: size_obj = self._get_size_class( relative=relative, align=align, width=width, left=left, right=right, above=above, below=below, ) self._set_style("size", size_obj)
# endregion Init # region Overrides
[docs] def apply(self, obj: Any, **kwargs) -> None: """ Applies styles to object Args: obj (object): UNO object. Returns: None: """ super().apply(obj, **kwargs) # for some reason setting Name property raises "UnknownPropertyException" when "setPropertyValue()" is used (Which Props.set() uses). # However, setting Name via setattr() works fine. # for this reason this class cancels setting of Name property and sets it via setattr() here. if self._has(self._props.name) and hasattr(obj, self._props.name): name = getattr(obj, self._props.name) if name != self.prop_name: # not case sensitive setattr(obj, self._props.name, self.prop_name)
[docs] def on_property_setting(self, source: Any, event_args: KeyValCancelArgs) -> None: if event_args.key == self._props.name: event_args.cancel = True event_args.handled = True # see bug specified in apply() method. super().on_property_setting(source, event_args)
def _supported_services(self) -> Tuple[str, ...]: try: return self._supported_services_values except AttributeError: self._supported_services_values = _get_default_tbl_services() return self._supported_services_values def _props_set(self, obj: Any, **kwargs: Any) -> None: try: return super()._props_set(obj, **kwargs) except mEx.MultiError as e: mLo.Lo.print(f"{self.__class__.__name__}.apply(): Unable to set Property") for err in e.errors: mLo.Lo.print(f" {err}") # endregion Overrides # region internal methods def _get_size_class( self, *, relative: bool, align: TableAlignKind, width: TblAbsUnit | TblRelUnit | None = None, left: TblAbsUnit | TblRelUnit | None = None, right: TblAbsUnit | TblRelUnit | None = None, above: TblAbsUnit | TblRelUnit | None = None, below: TblAbsUnit | TblRelUnit | None = None, ) -> _TblAuto: if relative: return self._get_size_rel_class( align=align, width=cast(Union[TblRelUnit, None], width), left=cast(Union[TblRelUnit, None], left), right=cast(Union[TblRelUnit, None], right), above=cast(Union[TblRelUnit, None], above), below=cast(Union[TblRelUnit, None], below), ) return self._get_size_abs_class( align=align, width=cast(Union[TblAbsUnit, None], width), left=cast(Union[TblAbsUnit, None], left), right=cast(Union[TblAbsUnit, None], right), above=cast(Union[TblAbsUnit, None], above), below=cast(Union[TblAbsUnit, None], below), ) def _get_size_abs_class( self, *, align: TableAlignKind, width: TblAbsUnit | None = None, left: TblAbsUnit | None = None, right: TblAbsUnit | None = None, above: TblAbsUnit | None = None, below: TblAbsUnit | None = None, ) -> _TblAuto: def check_req(*args: Any) -> bool: for arg in args: if arg is None: return False return True if align == TableAlignKind.AUTO: return _TblAuto(above=above, below=below, _cattribs=self._get_tbl_cattribs()) # type: ignore if align == TableAlignKind.CENTER: if width is None: ck = check_req(left) if not ck: raise ValueError( f"left or width are required when align is set to {align.name} and relative value is False." ) return _TblCenterLeft(above=above, below=below, left=left, _cattribs=self._get_tbl_cattribs()) # type: ignore else: return _TblCenterWidth(above=above, below=below, width=width, _cattribs=self._get_tbl_cattribs()) # type: ignore if align == TableAlignKind.FROM_LEFT: if width is None: ck = check_req(left) if not ck: raise ValueError( f"left or width are required when align is set to {align.name} and relative value is False." ) return _TblFromLeft(above=above, below=below, left=left, _cattribs=self._get_tbl_cattribs()) # type: ignore else: return _TblFromLeftWidth(above=above, below=below, width=width, _cattribs=self._get_tbl_cattribs()) # type: ignore if align == TableAlignKind.LEFT: if width is None: ck = check_req(right) if not ck: raise ValueError( f"right or width are required when align is set to {align.name} and relative value is False." ) return _TblLeft(above=above, below=below, right=right, _cattribs=self._get_tbl_cattribs()) # type: ignore else: return _TblLeftWidth(above=above, below=below, width=width, _cattribs=self._get_tbl_cattribs()) # type: ignore if align == TableAlignKind.RIGHT: if width is None: ck = check_req(left) if not ck: raise ValueError( f"left or width are required when align is set to {align.name} and relative value is False." ) return _TblRight(above=above, below=below, left=left, _cattribs=self._get_tbl_cattribs()) # type: ignore else: return _TblRightWidth(above=above, below=below, width=width, _cattribs=self._get_tbl_cattribs()) # type: ignore if align == TableAlignKind.MANUAL: if width is None: ck = check_req(left, right) if not ck: raise ValueError( f"left and right or width are required when align is set to {align.name} and relative value is False." ) return _TblManualLeftRight( above=above, below=below, left=left, right=right, _cattribs=self._get_tbl_cattribs() # type: ignore ) else: return _TblManualCenter(above=above, below=below, width=width, _cattribs=self._get_tbl_cattribs()) # type: ignore raise ValueError("Align Value is Unknown") def _get_size_rel_class( self, *, align: TableAlignKind, width: TblRelUnit | None = None, left: TblRelUnit | None = None, right: TblRelUnit | None = None, above: TblRelUnit | None = None, below: TblRelUnit | None = None, ) -> _TTblAuto | _TTblRelLeftByWidth: # type: ignore def check_req(*args: Any) -> bool: for arg in args: if arg is None: return False return True if align == TableAlignKind.CENTER: if width is None: ck = check_req(left) if not ck: raise ValueError( f"left or width are required when align is set to {align.name} and relative value is True." ) return cast( _TTblRelLeftByWidth, _TblRelCenter(above=above, below=below, left=left, _cattribs=self._get_tbl_cattribs()), # type: ignore ) else: return cast( _TTblAuto, _TblManualCenter(above=above, below=below, width=width, _cattribs=self._get_tbl_cattribs()), # type: ignore ) if align == TableAlignKind.FROM_LEFT: ck = check_req(width, left) if not ck: raise ValueError( f"width and left are required when align is set to {align.name} and relative value is True." ) return cast( _TTblRelLeftByWidth, _TblRelFromLeft(above=above, below=below, width=width, left=left, _cattribs=self._get_tbl_cattribs()), # type: ignore ) if align == TableAlignKind.LEFT: if width is None: ck = check_req(right) if not ck: raise ValueError( f"right or width are required when align is set to {align.name} and relative value is True." ) return cast( _TTblRelLeftByWidth, _TblRelLeftByRight(above=above, below=below, right=right, _cattribs=self._get_tbl_cattribs()), # type: ignore ) else: return cast( _TTblRelLeftByWidth, _TblRelLeftByWidth(above=above, below=below, width=width, _cattribs=self._get_tbl_cattribs()), # type: ignore ) if align == TableAlignKind.RIGHT: if width is None: ck = check_req(left) if not ck: raise ValueError( f"left or width are required when align is set to {align.name} and relative value is True." ) return cast( _TTblRelLeftByWidth, _TblRelRightByLeft(above=above, below=below, left=left, _cattribs=self._get_tbl_cattribs()), # type: ignore ) else: return cast( _TTblRelLeftByWidth, _TblRelRightByWidth(above=above, below=below, width=width, _cattribs=self._get_tbl_cattribs()), # type: ignore ) if align == TableAlignKind.AUTO: raise ValueError('align must not be set to "TableAlignKind.AUTO" when relative is set to False') if align == TableAlignKind.MANUAL: raise ValueError('align must not be set to "TableAlignKind.MANUAL" when relative is set to False') raise ValueError("Align Value is Unknown") def _get_tbl_cattribs(self) -> dict: return { "_supported_services_values": self._supported_services(), "_format_kind_prop": self.prop_format_kind, "_props_internal_attributes": self._props, } # endregion internal methods # region static methods # region from_obj() @overload @classmethod def from_obj(cls: Type[_TTableProperties], obj: Any) -> _TTableProperties: ... @overload @classmethod def from_obj(cls: Type[_TTableProperties], obj: Any, **kwargs) -> _TTableProperties: ...
[docs] @classmethod def from_obj(cls: Type[_TTableProperties], obj: Any, **kwargs) -> _TTableProperties: """ Gets instance from object Args: obj (object): UNO Object. Raises: NotSupportedError: If ``obj`` is not supported. Returns: TableProperties: Instance that represents Table options. """ # sourcery skip: merge-else-if-into-elif # this nu is only used to get Property Name inst = cls(**kwargs) if not inst._is_valid_obj(obj): raise mEx.NotSupportedError(f'Object is not supported for conversion to "{cls.__name__}"') try: inst._set(inst._props.name, mProps.Props.get(obj, inst._props.name)) except mEx.PropertyNotFoundError: # there is a bug. See apply() if hasattr(obj, inst._props.name): inst._set(inst._props.name, getattr(obj, inst._props.name)) else: raise hori = int(mProps.Props.get(obj, inst._props.hori_orient)) rel = bool(mProps.Props.get(obj, inst._props.is_rel)) inst._prop_relative = rel inst._prop_align = TableAlignKind(hori) if rel: if hori == HoriOrientation.LEFT: size_obj = _TblRelLeftByWidth.from_obj(obj, _cattribs=inst._get_tbl_cattribs()) elif hori == HoriOrientation.LEFT_AND_WIDTH: size_obj = _TblRelFromLeft.from_obj(obj, _cattribs=inst._get_tbl_cattribs()) elif hori == HoriOrientation.RIGHT: size_obj = _TblRelRightByWidth.from_obj(obj, _cattribs=inst._get_tbl_cattribs()) else: size_obj = _TblRelCenter.from_obj(obj, _cattribs=inst._get_tbl_cattribs()) else: if hori == HoriOrientation.FULL: size_obj = _TblAuto.from_obj(obj, _cattribs=inst._get_tbl_cattribs()) elif hori == HoriOrientation.CENTER: size_obj = _TblCenterWidth.from_obj(obj, _cattribs=inst._get_tbl_cattribs()) elif hori == HoriOrientation.LEFT: size_obj = _TblLeft.from_obj(obj, _cattribs=inst._get_tbl_cattribs()) elif hori == HoriOrientation.RIGHT: size_obj = _TblRight.from_obj(obj, _cattribs=inst._get_tbl_cattribs()) elif hori == HoriOrientation.LEFT_AND_WIDTH: size_obj = _TblFromLeft.from_obj(obj, _cattribs=inst._get_tbl_cattribs()) else: size_obj = _TblManualLeftRight.from_obj(obj, _cattribs=inst._get_tbl_cattribs()) inst._set_style("size", size_obj) # prev, next not currently working return inst
# endregion from_obj() # endregion static methods # region Methods
[docs] def get_width_mm(self) -> UnitMM | None: """ Gets Width in ``mm`` units. When class is constructed using relative values this method will still return ``mm`` units. Returns: UnitMM | None: Note: This method may return None if ``apply()`` has not yet been called. """ po = cast(_TSharedAuto, self._prop_obj) # type: ignore if po is None: return None pv = cast(int, po._get(self._props.width)) return None if pv is None else UnitMM.from_mm100(pv)
[docs] def get_left_mm(self) -> UnitMM | None: """ Gets left in ``mm`` units. When class is constructed using relative values this method will still return ``mm`` units. Returns: UnitMM | None: Note: This method may return None if ``apply()`` has not yet been called. """ po = cast(_TSharedAuto, self._prop_obj) # type: ignore if po is None: return None pv = cast(int, po._get(self._props.left)) return None if pv is None else UnitMM.from_mm100(pv)
[docs] def get_right_mm(self) -> UnitMM | None: """ Gets right in ``mm`` units. When class is constructed using relative values this method will still return ``mm`` units. Returns: UnitMM | None: Note: This method may return None if ``apply()`` has not yet been called. """ po = cast(_TSharedAuto, self._prop_obj) # type: ignore if po is None: return None pv = cast(int, po._get(self._props.right)) return None if pv is None else UnitMM.from_mm100(pv)
# endregion 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.TABLE return self._format_kind_prop @property def prop_name(self) -> str | None: """Gets/Sets name""" return self._get(self._props.name) @prop_name.setter def prop_name(self, value: str | None) -> None: if value is None: self._remove(self._props.name) return self._set(self._props.name, value) @property def _prop_obj(self) -> Any: """Gets inner instance if exist.""" try: return self._prop_inner_obj except AttributeError: val = self._get_style("size") self._prop_inner_obj = None if val is None else val.style return self._prop_inner_obj @property def prop_align(self) -> TableAlignKind | None: """Gets Alignment value""" return self._prop_align @property def prop_relative(self) -> bool: """Gets relative value""" return self._prop_relative @property def prop_width(self) -> UnitMM | Intensity | None: """ Gets width value. Returns: UnitMM | Intensity | None: When ``relative`` is ``True`` ``Intensity`` or ``None``; Otherwise, ``UnitMM`` or None. See Also: :py:meth:`~.table_properties.TableProperties.get_width_mm`. """ po = cast(_TSharedAuto, self._prop_obj) # type: ignore return None if po is None else po.prop_width @property def prop_left(self) -> UnitMM | Intensity | None: """ Gets left value. Returns: UnitMM | Intensity | None: When ``relative`` is ``True`` ``Intensity`` or ``None``; Otherwise, ``UnitMM`` or None. See Also: :py:meth:`~.table_properties.TableProperties.get_left_mm`. """ po = cast(_TSharedAuto, self._prop_obj) # type: ignore return None if po is None else po.prop_left @property def prop_right(self) -> UnitMM | Intensity | None: """ Gets right value. Returns: UnitMM | Intensity | None: When ``relative`` is ``True`` ``Intensity`` or ``None``; Otherwise, ``UnitMM`` or None. See Also: :py:meth:`~.table_properties.TableProperties.get_right_mm`. """ po = cast(_TSharedAuto, self._prop_obj) # type: ignore return None if po is None else po.prop_right @property def prop_above(self) -> UnitMM | None: """Gets above value""" po = cast(_TSharedAuto, self._prop_obj) # type: ignore if po is None: return None pv = cast(int, po._get(self._props.top)) return None if pv is None else UnitMM.from_mm100(pv) @property def prop_below(self) -> UnitMM | None: """Gets below value""" po = cast(_TSharedAuto, self._prop_obj) # type: ignore if po is None: return None pv = cast(int, po._get(self._props.bottom)) return None if pv is None else UnitMM.from_mm100(pv) @property def _props(self) -> TablePropertiesProps: try: return self._props_internal_attributes except AttributeError: self._props_internal_attributes = _get_default_tbl_props() return self._props_internal_attributes
# endregion properties # endregion TableProperties Class __all__ = ("TblAbsUnit", "TblRelUnit", "TableAlignKind", "TableProperties")