Source code for ooodev.format.inner.direct.write.para.tabs.tabs

"""
Module for managing paragraph Tabs.

.. versionadded:: 0.9.0
"""

# region Import
from __future__ import annotations
import contextlib
from typing import Any, Tuple, cast, Type, TypeVar, overload

from com.sun.star.beans import XPropertySet
from ooo.dyn.style.tab_align import TabAlign
from ooo.dyn.style.tab_stop import TabStop

from ooodev.events.args.cancel_event_args import CancelEventArgs
from ooodev.format.inner.direct.structs.tab_stop_struct import FillCharKind
from ooodev.format.inner.direct.structs.tab_stop_struct import TabStopStruct
from ooodev.loader import lo as mLo
from ooodev.meta.static_prop import static_prop
from ooodev.units.unit_obj import UnitT
from ooodev.utils import info as mInfo
from ooodev.utils import props as mProps

# endregion Import

_TTabs = TypeVar("_TTabs", bound="Tabs")


[docs]class Tabs(TabStopStruct): """ Paragraph Tabs Any properties starting with ``prop_`` set or get current instance values. All methods starting with ``fmt_`` can be used to chain together properties. .. seealso:: - :ref:`help_writer_format_direct_para_tabs` .. versionadded:: 0.9.0 """
[docs] def __init__( self, *, position: float | UnitT = 0.0, align: TabAlign = TabAlign.LEFT, decimal_char: str = ".", fill_char: FillCharKind | str = FillCharKind.NONE, ) -> None: """ Constructor Args: position (float, UnitT, optional): Specifies the position of the tabulator in relation to the left border (in ``mm`` units) or :ref:`proto_unit_obj`. Defaults to ``0.0`` align (TabAlign, optional): Specifies the alignment of the text range before the tabulator. Defaults to ``TabAlign.LEFT`` decimal_char (str, optional): Specifies which delimiter is used for the decimal. Argument is expected to be a single character string. This argument is only used when ``align`` is set to ``TabAlign.DECIMAL``. fill_char (FillCharKind, str, optional): specifies the character that is used to fill up the space between the text in the text range and the tabulators. If string value then argument is expected to be a single character string. Defaults to ``FillCharKind.NONE`` Returns: None: Note: If argument ``type`` is ``None`` then all other argument are ignored See Also: - :ref:`help_writer_format_direct_para_tabs` """ super().__init__(position=position, align=align, decimal_char=decimal_char, fill_char=fill_char)
# region methods def _supported_services(self) -> Tuple[str, ...]: try: return self._supported_services_values except AttributeError: self._supported_services_values = ( "com.sun.star.style.ParagraphProperties", "com.sun.star.style.ParagraphStyle", ) 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 _get_property_name(self) -> str: try: return self._property_name except AttributeError: self._property_name = "ParaTabStops" return self._property_name # region find() @overload @classmethod def find(cls: Type[_TTabs], obj: Any, position: float) -> _TTabs | None: ... @overload @classmethod def find(cls: Type[_TTabs], obj: Any, position: float, **kwargs) -> _TTabs | None: ...
[docs] @classmethod def find(cls: Type[_TTabs], obj: Any, position: float, **kwargs) -> _TTabs | None: """ Gets a Tab that matches position from obj such as a cursor. Args: obj (object): UNO Object. position (float): position of tab stop (in mm units). Returns: Tab | None: ``Tab`` instance if found; Otherwise, ``None`` """ # pylint: disable=protected-access # pylint: disable=no-member nu = cls(**kwargs) if not nu._is_valid_obj(obj): return None key = Tabs.default._get_property_name() pos = round(position * 100) tss = cast(Tuple[TabStop, ...], mProps.Props.get(obj, key)) if tss is None: return None match = -1 # often Writer will change Position values, 800 to 801 etc. # for this reason using a range to check plus or minus 2 pos_rng = range(pos - 2, pos + 3) # plus or minus 2 for i, ts in enumerate(tss): if pos == ts.Position: # also covers 0 match = i break if ts.Position in pos_rng: match = i break if match == -1: return None ts = tss[match] # type: ignore return cls.from_uno_struct(ts, **kwargs)
# endregion find() # region remove_by_pos() @overload @classmethod def remove_by_pos(cls, obj: Any, position: float) -> bool: ... @overload @classmethod def remove_by_pos(cls, obj: Any, position: float, **kwargs) -> bool: ...
[docs] @classmethod def remove_by_pos(cls, obj: Any, position: float, **kwargs) -> bool: """ Removes a Tab Stop from ``obj`` Args: obj (object): Object that supports ``com.sun.star.style.ParagraphProperties`` position (float): position of tab stop (in mm units). Returns: bool: ``True`` if a Tab Stop has been removed; Otherwise, ``False`` """ # pylint: disable=protected-access tb = cls.find(obj, position, **kwargs) if tb is None: return False # tb will contain the exact Position number so no need to plus or minus pos = cast(int, tb._get("Position")) return cls._remove_by_position(obj, pos, **kwargs)
@classmethod def _remove_by_position(cls, obj: Any, position: int, **kwargs) -> bool: """ Removes a Tab Stop from ``obj`` Args: obj (object): Object that supports ``com.sun.star.style.ParagraphProperties`` position (int): position of tab stop. Returns: None: """ # pylint: disable=protected-access inst = cls(**kwargs) tss = cast(Tuple[TabStop, ...], mProps.Props.get(obj, inst._get_property_name())) if tss is None: return False lst = [ts for ts in tss if position != ts.Position] # type: ignore if len(lst) == len(tss): return False inst._set_obj_tabs(obj, lst) return True # endregion remove_by_pos() # region remove() @overload @classmethod def remove(cls, obj: Any, tab: TabStop | TabStopStruct) -> bool: ... @overload @classmethod def remove(cls, obj: Any, tab: TabStop | TabStopStruct, **kwargs) -> bool: ...
[docs] @classmethod def remove(cls, obj: Any, tab: TabStop | TabStopStruct, **kwargs) -> bool: """ Removes a Tab Stop from ``obj`` ``ParaTabStops`` property. Args: obj (object): Object that supports ``com.sun.star.style.ParagraphProperties`` tab (TabStop | Tab): Tab or Tab Stop to remove. Returns: bool: ``True`` if a Tab has been removed; Otherwise, ``False`` """ # pylint: disable=protected-access inst = cls(**kwargs) if not inst._is_valid_obj(obj): return False if isinstance(tab, TabStopStruct): return inst._remove_by_position(obj, tab._get("Position"), **kwargs) ts = cast(TabStop, tab) return inst._remove_by_position(obj, ts.Position, **kwargs)
# endregion remove() # region remove_all() @overload @classmethod def remove_all(cls, obj: Any) -> None: ... @overload @classmethod def remove_all(cls, obj: Any, **kwargs) -> None: ...
[docs] @classmethod def remove_all(cls, obj: Any, **kwargs) -> None: """ Removes all tab from ``obj`` ``ParaTabStops`` property. Args: obj (object): UNO Object. """ # pylint: disable=protected-access inst = cls(**kwargs) if not inst._is_valid_obj(obj): return tss = cast(Tuple[TabStop, ...], mProps.Props.get(obj, inst._get_property_name())) if tss is None: return try: inst._set_obj_tabs(obj, [inst.get_uno_struct()]) except Exception: # if for any reason can't get default it is ok to just remove all. inst._set_obj_tabs(obj, [])
# endregion remove_all()
[docs] def get_uno_struct(self) -> TabStop: """ Gets tab stop for instance Returns: TabStop: Tab stop instance """ ts = super().get_uno_struct() with contextlib.suppress(Exception): # not critical if self is Tabs.default: ts.DecimalChar = "." return ts
# endregion methods # region Properties @static_prop def default() -> Tabs: # type: ignore[misc] """Gets ``Tabs`` default. Static Property.""" # pylint: disable=protected-access try: return Tabs._DEFAULT_INST # type: ignore except AttributeError: inst = Tabs(align=TabAlign.DEFAULT) # this commented section works if not in macro mode # mInfo.Info.get_reg_item_prop() imports lxml # ts_val: str = mInfo.Info.get_reg_item_prop( # "Writer/Layout/Other/TabStop", kind=mInfo.Info.RegPropKind.VALUE, idx=1 # ) # inst._set("Position", int(ts_val)) props = mLo.Lo.qi( XPropertySet, mInfo.Info.get_config(node_str="Other", node_path="/org.openoffice.Office.Writer/Layout/"), True, ) ts_val = props.getPropertyValue("TabStop") inst._set("Position", ts_val) inst._set("DecimalChar", ".") inst._is_default_inst = True Tabs._DEFAULT_INST = inst # type: ignore return Tabs._DEFAULT_INST # type: ignore
# endregion Properties