Source code for ooodev.format.inner.direct.write.frame.frame_type.position

"""
Module for Fill Transparency.

.. versionadded:: 0.9.0
"""

from __future__ import annotations
from typing import Any, Tuple, Type, TypeVar, overload
from enum import Enum
import math
from ooo.dyn.text.hori_orientation import HoriOrientation
from ooo.dyn.text.vert_orientation import VertOrientation
from ooo.dyn.text.rel_orientation import RelOrientation

from ooodev.events.args.cancel_event_args import CancelEventArgs
from ooodev.exceptions import ex as mEx
from ooodev.format.inner.common.props.frame_type_position_props import FrameTypePositionProps
from ooodev.format.inner.kind.format_kind import FormatKind
from ooodev.format.inner.style_base import StyleBase
from ooodev.units.unit_convert import UnitConvert
from ooodev.units.unit_mm import UnitMM
from ooodev.units.unit_obj import UnitT
from ooodev.utils import props as mProps

_TPosition = TypeVar("_TPosition", bound="Position")


[docs]class HoriOrient(Enum): """Horizontal Orientation""" LEFT_OR_INSIDE = HoriOrientation.LEFT """The object is aligned at the left side. When frame is mirrored the value is ``Inside``; Otherwise, ``Left``.""" RIGHT_OR_OUTSIDE = HoriOrientation.RIGHT """The object is aligned at the right side. When frame is mirrored the value is ``Outside``; Otherwise, ``Right``.""" CENTER = HoriOrientation.CENTER """The object is aligned at the middle.""" FROM_LEFT_OR_INSIDE = HoriOrientation.NONE """No hard alignment is applied. When frame is mirrored the value is ``From Inside``; Otherwise, ``From Left``.""" def __int__(self) -> int: return self.value
[docs]class VertOrient(Enum): """Vertical Orientation""" TOP = VertOrientation.TOP """Aligned at the top""" CENTER = VertOrientation.CENTER """Aligned at the center""" BOTTOM = VertOrientation.BOTTOM """Aligned at the bottom""" FROM_TOP_OR_BOTTOM = VertOrientation.NONE """No hard alignment. From Top is only used when Anchor is ``To character``. From Bottom is only used when Anchor is ``To character`` or ``As character``.""" BELOW_CHAR = VertOrientation.CHAR_BOTTOM """Aligned at the bottom of a character (anchored to character). Only used when Anchor is set ``To character``."""
[docs]class RelHoriOrient(Enum): # when Anchor is set to page, the paragraph enums are not present in the Writer Dialog. # when Anchor is set to character. PARAGRAPH_AREA = RelOrientation.FRAME """Paragraph, including margins. Only used when Anchor is set ``To paragraph`` or ``To Character``.""" PARAGRAPH_TEXT_AREA = RelOrientation.PRINT_AREA """Paragraph, without margins. Only used when Anchor is set ``To paragraph`` or ``To Character``.""" LEFT_PARAGRAPH_BORDER = RelOrientation.FRAME_LEFT """Inside the left paragraph margin. Only used when Anchor is set ``To paragraph`` or ``To Character``.""" RIGHT_PARAGRAPH_BORDER = RelOrientation.FRAME_RIGHT """Inside the right paragraph margin. Only used when Anchor is set ``To paragraph`` or ``To Character``.""" LEFT_PAGE_BORDER = RelOrientation.PAGE_LEFT """Inside the left page margin.""" RIGHT_PAGE_BORDER = RelOrientation.PAGE_RIGHT """Inside the right page margin""" ENTIRE_PAGE = RelOrientation.PAGE_FRAME """Page includes margins for page-anchored frames identical with ``PARAGRAPH_AREA``.""" PAGE_TEXT_AREA = RelOrientation.PAGE_PRINT_AREA """Page without borders (for page anchored frames identical with ``PARAGRAPH_TEXT_AREA``).""" CHARACTER = RelOrientation.CHAR """As character. Only used when Anchor is set ``To character``."""
[docs]class RelVertOrient(Enum): MARGIN = RelOrientation.FRAME """Paragraph, including margins. Only used when Anchor is set ``To paragraph`` or ``To character``.""" PARAGRAPH_TEXT_AREA_OR_BASE_LINE = RelOrientation.PRINT_AREA """Paragraph, without margins. Only used when Anchor is set ``To paragraph``, ``To character`` or ``As character``.""" ENTIRE_PAGE_OR_ROW = RelOrientation.PAGE_FRAME """Page includes margins for page-anchored frames identical with ``PARAGRAPH_AREA``. Only used when Anchor is set ``To page``, ``To paragraph``, ``To character`` or ``As character``.""" PAGE_TEXT_AREA = RelOrientation.PAGE_PRINT_AREA """Page without borders (for page anchored frames identical with ``PARAGRAPH_TEXT_AREA``). Only used when Anchor is set ``To page``, ``To paragraph`` or ``To character``.""" CHARACTER = RelOrientation.CHAR """As character. Only used when Anchor is set ``To character``.""" LINE_OF_TEXT = RelOrientation.TEXT_LINE """at the top of the text line, only sensible for vertical orientation. Only used when Anchor ``To character`` and ``VertOrient`` is ``TOP``, ``BOTTOM``, ``CENTER`` or ``FROM_TOP_OR_BOTTOM``."""
[docs]class Horizontal: """Horizontal Frame Position. Not used when Anchor is set to ``As Character``.""" # region Init
[docs] def __init__(self, position: HoriOrient, rel: RelHoriOrient, amount: float | UnitT = 0.0) -> None: """ Constructor Args: position (HoriOrient): Specifies Horizontal Position. rel (RelHoriOrient): Specifies Relative Orientation. amount (float, UnitT, optional): Specifies Amount in ``mm`` units or :ref:`proto_unit_obj`. Only effective when position is ``HoriOrient.FROM_LEFT``. Defaults to ``0.0``. """ self._position = position self._rel = rel try: self._amount = amount.get_value_mm() # type: ignore except AttributeError: self._amount = float(amount) # type: ignore
# endregion Init # region Dunder Methods def __eq__(self, oth: object) -> bool: if isinstance(oth, Horizontal): result = True result = result and self.position == oth.position result = result and self.rel == oth.rel if not result: return False return math.isclose(self.amount.value, oth.amount.value, abs_tol=0.02) return NotImplemented # endregion Dunder Methods # region Methods
[docs] def copy(self) -> Horizontal: """Gets a copy of instance as a new instance""" inst = super(Horizontal, self.__class__).__new__(self.__class__) inst.__init__(position=self.position, rel=self.rel, amount=self.amount) return inst
# endregion Methods # region Properties @property def position(self) -> HoriOrient: """ Gets/Sets Horizontal Position. """ return self._position @position.setter def position(self, value: HoriOrient): self._position = value @property def rel(self) -> RelHoriOrient: """ Gets/Sets Relative Orientation """ return self._rel @rel.setter def rel(self, value: RelHoriOrient): self._rel = value @property def amount(self) -> UnitMM: """ Gets/Sets Amount in ``mm`` units. Only effective when position is ``HoriOrient.FROM_LEFT``. Setting also allows ``Unit100MM`` instance. """ return UnitMM(self._amount) @amount.setter def amount(self, value: float | UnitT): try: self._amount = value.get_value_mm() # type: ignore except AttributeError: self._amount = float(value) # type: ignore
# endregion Properties
[docs]class Vertical: """Vertical Frame Position.""" # region Init
[docs] def __init__(self, position: VertOrient, rel: RelVertOrient, amount: float | UnitT = 0.0) -> None: """ Constructor Args: position (VertOrient): Specifies Vertical Position. rel (RelVertOrient): Specifies Relative Orientation. amount (float, UnitT, optional): Specifies Amount in ``mm`` units or :ref:`proto_unit_obj`. Only effective when position is ``VertOrient.FROM_TOP``. Defaults to ``0.0``. """ self._position = position self._rel = rel try: self._amount = amount.get_value_mm() # type: ignore except AttributeError: self._amount = float(amount) # type: ignore
# endregion Init # region Dunder Methods def __eq__(self, oth: object) -> bool: if isinstance(oth, Vertical): result = True result = result and self.position == oth.position result = result and self.rel == oth.rel if not result: return False return math.isclose(self.amount.value, oth.amount.value, abs_tol=0.02) return NotImplemented # endregion Dunder Methods # region Methods
[docs] def copy(self) -> Vertical: """Gets a copy of instance as a new instance""" inst = super(Vertical, self.__class__).__new__(self.__class__) inst.__init__(position=self.position, rel=self.rel, amount=self.amount) return inst
# endregion Methods # region Properties @property def position(self) -> VertOrient: """ Gets/Sets Vertical Position. """ return self._position @position.setter def position(self, value: VertOrient): self._position = value @property def rel(self) -> RelVertOrient: """ Gets/Sets Relative Orientation """ return self._rel @rel.setter def rel(self, value: RelVertOrient): self._rel = value @property def amount(self) -> UnitMM: """ Gets/Sets Amount in ``mm`` units. Only effective when position is ``VertOrient.FROM_TOP``. Setting also allows ``Unit100MM`` instance. """ return UnitMM(self._amount) @amount.setter def amount(self, value: float | UnitT): try: self._amount = value.get_value_mm() # type: ignore except AttributeError: self._amount = float(value) # type: ignore
# endregion Properties
[docs]class Position(StyleBase): """ Fill Transparency .. versionadded:: 0.9.0 """
[docs] def __init__( self, *, horizontal: Horizontal | None = None, vertical: Vertical | None = None, keep_boundaries: bool | None = None, mirror_even: bool | None = None, ) -> None: """ Constructor Args: horizontal (Horizontal, optional): Specifies the Horizontal position options. Not used when Anchor is set to ``As Character``. vertical (Vertical, optional): Specifies the Vertical position options. keep_boundaries (bool, optional): Specifies keep inside text boundaries. mirror_even (bool, optional): Specifies mirror on even pages. Not used when Anchor is set to ``As Character``. """ super().__init__() if horizontal is not None: self._set_horizontal(horizontal) if vertical is not None: self._set_vertical(vertical) if keep_boundaries is not None: self.prop_keep_boundaries = keep_boundaries if mirror_even is not None: self.prop_mirror_even = mirror_even self._horizontal = horizontal self._vertical = vertical
# region Internal Methods def _set_horizontal(self, horizontal: Horizontal | None) -> None: if horizontal is None: self._remove(self._props.hori_orient) self._remove(self._props.hori_pos) self._remove(self._props.hori_rel) return if horizontal.position == HoriOrient.FROM_LEFT_OR_INSIDE: self._set(self._props.hori_pos, horizontal.amount.get_value_mm100()) else: self._set(self._props.hori_pos, 0) self._set(self._props.hori_orient, horizontal.position.value) self._set(self._props.hori_rel, horizontal.rel.value) def _set_vertical(self, vertical: Vertical | None) -> None: if vertical is None: self._remove(self._props.vert_orient) self._remove(self._props.vert_pos) self._remove(self._props.vert_rel) return if vertical.position == VertOrient.FROM_TOP_OR_BOTTOM: self._set(self._props.vert_pos, vertical.amount.get_value_mm100()) else: self._set(self._props.vert_pos, 0) self._set(self._props.vert_orient, vertical.position.value) self._set(self._props.vert_rel, vertical.rel.value) # endregion Internal Methods # region Overrides # region copy() @overload def copy(self: _TPosition) -> _TPosition: ... @overload def copy(self: _TPosition, **kwargs) -> _TPosition: ...
[docs] def copy(self: _TPosition, **kwargs) -> _TPosition: """Gets a copy of instance as a new instance""" cp = super().copy(**kwargs) cp._horizontal = None if self._horizontal is None else self._horizontal.copy() cp._vertical = None if self._vertical is None else self._vertical.copy() return cp
# endregion copy() def _supported_services(self) -> Tuple[str, ...]: try: return self._supported_services_values except AttributeError: self._supported_services_values = ( "com.sun.star.style.Style", "com.sun.star.text.BaseFrameProperties", "com.sun.star.text.BaseFrame", "com.sun.star.text.TextEmbeddedObject", "com.sun.star.text.TextFrame", "com.sun.star.text.TextGraphicObject", "com.sun.star.text.Shape", ) return self._supported_services_values def _on_modifying(self, source: Any, event: CancelEventArgs) -> None: if self._is_default_inst: raise ValueError("Modifying a default instance is not allowed") return super()._on_modifying(source, event) 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`` """ if super()._is_valid_obj(obj): return True # check if obj has matching property # Some objects such as 'com.sun.star.drawing.shape' sometime support this style. # Such is the case when a shape is added to a Writer drawing page. # Assume if on attribute matches then they all match. return hasattr(obj, self._props.hori_orient) # endregion Overrides # region from_obj() @overload @classmethod def from_obj(cls: Type[_TPosition], obj: Any) -> _TPosition: ... @overload @classmethod def from_obj(cls: Type[_TPosition], obj: Any, **kwargs) -> _TPosition: ...
[docs] @classmethod def from_obj(cls: Type[_TPosition], obj: Any, **kwargs) -> _TPosition: """ Gets instance from object Args: obj (object): UNO Object. Returns: Position: Instance that represents Frame Position. """ # pylint: disable=protected-access inst = cls(**kwargs) if not inst._is_valid_obj(obj): raise mEx.NotSupportedError(f'Object is not supported for conversion to "{cls.__name__}"') pp = inst._props hori_orient = int(mProps.Props.get(obj, pp.hori_orient, HoriOrient.CENTER.value)) inst._set(pp.hori_orient, hori_orient) hori_pos = int(mProps.Props.get(obj, pp.hori_pos, 0)) inst._set(pp.hori_pos, hori_pos) hori_rel = int(mProps.Props.get(obj, pp.hori_rel, RelHoriOrient.PARAGRAPH_TEXT_AREA.value)) inst._set(pp.hori_rel, hori_rel) vert_orient = int(mProps.Props.get(obj, pp.vert_orient, VertOrient.TOP.value)) inst._set(pp.vert_orient, vert_orient) vert_pos = int(mProps.Props.get(obj, pp.vert_pos, 0)) inst._set(pp.vert_pos, vert_pos) vert_rel = int(mProps.Props.get(obj, pp.vert_rel, RelVertOrient.PARAGRAPH_TEXT_AREA_OR_BASE_LINE.value)) inst._set(pp.hori_rel, vert_rel) txt_flow = bool(mProps.Props.get(obj, pp.txt_flow, False)) inst._set(pp.txt_flow, txt_flow) page_toggle = bool(mProps.Props.get(obj, pp.page_toggle, False)) inst._set(pp.page_toggle, page_toggle) inst._horizontal = Horizontal( position=HoriOrient(hori_orient), rel=RelHoriOrient(hori_rel), amount=UnitConvert.convert_mm100_mm(hori_pos), ) inst._vertical = Vertical( position=VertOrient(vert_orient), rel=RelVertOrient(vert_rel), amount=UnitConvert.convert_mm100_mm(vert_pos), ) return inst
# endregion from_obj() @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.DOC | FormatKind.STYLE return self._format_kind_prop @property def prop_keep_boundaries(self) -> bool | None: """Gets/Sets keep inside text boundaries""" return self._get(self._props.txt_flow) @prop_keep_boundaries.setter def prop_keep_boundaries(self, value: bool | None) -> None: if value is None: self._remove(self._props.txt_flow) return self._set(self._props.txt_flow, value) @property def prop_mirror_even(self) -> bool | None: """Gets/Sets Mirror on even pages""" return self._get(self._props.page_toggle) @prop_mirror_even.setter def prop_mirror_even(self, value: bool | None) -> None: if value is None: self._remove(self._props.page_toggle) return self._set(self._props.page_toggle, value) @property def prop_horizontal(self) -> Horizontal | None: """Gets/Sets horizontal value""" return self._horizontal @prop_horizontal.setter def prop_horizontal(self, value: Horizontal | None) -> None: self._set_horizontal(value) @property def prop_vertical(self) -> Vertical | None: """Gets/Sets vertical value""" return self._vertical @prop_vertical.setter def prop_vertical(self, value: Vertical | None) -> None: self._set_vertical(value) @property def _props(self) -> FrameTypePositionProps: try: return self._props_internal_attributes except AttributeError: self._props_internal_attributes = FrameTypePositionProps( hori_orient="HoriOrient", hori_pos="HoriOrientPosition", hori_rel="HoriOrientRelation", vert_orient="VertOrient", vert_pos="VertOrientPosition", vert_rel="VertOrientRelation", txt_flow="IsFollowingTextFlow", page_toggle="PageToggle", ) return self._props_internal_attributes