Source code for flexicon.code.Discourse.ConstChartCellTagOperations

#
#   ConstChartCellTagOperations.py
#
#   Class: ConstChartCellTagOperations
#          Per-cell tag (IConstChartTag) operations for constituent
#          charts in FieldWorks Language Explorer projects via SIL
#          Language and Culture Model (LCM) API.
#
#   Platform: Python.NET
#             FieldWorks Version 9+
#
#   Copyright 2026
#

from ..BaseOperations import BaseOperations, OperationsMethod, wrap_enumerable

from SIL.LCModel import (
    IConstChartTag,
    IConstChartTagFactory,
    IConstChartRow,
    ICmPossibility,
)

from ..FLExProject import (
    FP_ParameterError,
)


[docs] class ConstChartCellTagOperations(BaseOperations): """ Operations for managing per-cell chart tags (``IConstChartTag``) -- the annotation surface in a constituent chart. Each chart row owns a sequence of cell-parts; a ``IConstChartTag`` is one cell-part subtype. Each tag is positioned in a column (``ColumnRA``) and references a marker from the project-wide vocabulary (``TagRA``). The vocabulary itself is managed by ``ConstChartMarkerOperations``. Typical workflow:: row = list(chart.RowsOS)[0] col = list(template.ColumnsOS)[1] topic = project.ConstChartMarkers.Find("Topic") tag = project.ConstChartCellTags.Create(row, col, topic) assert project.ConstChartCellTags.GetMarker(tag) is topic Access via ``FLExProject.ConstChartCellTags``. """ def __init__(self, project): super().__init__(project) # --- Core CRUD Operations ------------------------------------------ @OperationsMethod def Create(self, row_or_hvo, column, marker, index=None): """ Add a new IConstChartTag cell-part to ``row.CellsOS``. Args: row_or_hvo: The ``IConstChartRow`` (or HVO) that will own the new cell-part. column: The ``ICmPossibility`` representing the column this tag occupies. Stored as ``ColumnRA``. marker: The ``ICmPossibility`` from the project's ChartMarkers vocabulary. Stored as ``TagRA``. index (int, optional): Position to insert at within ``row.CellsOS``. When None (default) the tag is appended at the end. Returns: IConstChartTag: The newly created cell-part. Raises: FP_ReadOnlyError: If the project is not writeEnabled. FP_NullParameterError: If any of row_or_hvo / column / marker is None. FP_ParameterError: If index is out of range. """ self._EnsureWriteEnabled() self._ValidateParam(row_or_hvo, "row_or_hvo") self._ValidateParam(column, "column") self._ValidateParam(marker, "marker") row = self.__ResolveRow(row_or_hvo) cell_count = row.CellsOS.Count if index is None: index = cell_count if index < 0 or index > cell_count: raise FP_ParameterError( f"index {index} out of range for CellsOS of size {cell_count}" ) factory = self.project.project.ServiceLocator.GetService( IConstChartTagFactory ) return factory.Create(row, index, column, marker) @OperationsMethod def Delete(self, tag_or_hvo): """ Delete a cell-tag from its owning row. Args: tag_or_hvo: ``IConstChartTag`` or its HVO. """ self._EnsureWriteEnabled() self._ValidateParam(tag_or_hvo, "tag_or_hvo") tag = self.__ResolveTag(tag_or_hvo) tag.Delete() @OperationsMethod def Find(self, row_or_hvo, column): """ Find the first cell-tag in ``row`` positioned in ``column``. Args: row_or_hvo: ``IConstChartRow`` or HVO. column: ``ICmPossibility`` representing the column. Returns: IConstChartTag or None: First matching tag, or None when the row has no tag in that column. """ self._ValidateParam(row_or_hvo, "row_or_hvo") self._ValidateParam(column, "column") row = self.__ResolveRow(row_or_hvo) column_hvo = column.Hvo for cell in row.CellsOS: if not isinstance(cell, IConstChartTag): continue if cell.ColumnRA is not None and cell.ColumnRA.Hvo == column_hvo: return cell return None @wrap_enumerable @OperationsMethod def GetAll(self, row_or_hvo): """ Iterate every IConstChartTag in ``row.CellsOS`` (other cell-part subtypes are filtered out). Args: row_or_hvo: ``IConstChartRow`` or HVO. Returns: list[IConstChartTag]: Tags in CellsOS order. """ self._ValidateParam(row_or_hvo, "row_or_hvo") row = self.__ResolveRow(row_or_hvo) return [c for c in row.CellsOS if isinstance(c, IConstChartTag)] # --- Tag Properties ------------------------------------------------ @OperationsMethod def GetMarker(self, tag_or_hvo): """Return ``tag.TagRA`` -- the referenced marker (or None).""" self._ValidateParam(tag_or_hvo, "tag_or_hvo") tag = self.__ResolveTag(tag_or_hvo) return tag.TagRA @OperationsMethod def SetMarker(self, tag_or_hvo, marker): """Set ``tag.TagRA`` to a marker from the project vocabulary.""" self._EnsureWriteEnabled() self._ValidateParam(tag_or_hvo, "tag_or_hvo") self._ValidateParam(marker, "marker") tag = self.__ResolveTag(tag_or_hvo) tag.TagRA = marker @OperationsMethod def GetColumn(self, tag_or_hvo): """Return ``tag.ColumnRA`` -- the column the tag occupies.""" self._ValidateParam(tag_or_hvo, "tag_or_hvo") tag = self.__ResolveTag(tag_or_hvo) return tag.ColumnRA # --- Private Helpers ----------------------------------------------- def __ResolveRow(self, row_or_hvo): if isinstance(row_or_hvo, int): obj = self.project.Object(row_or_hvo) if not isinstance(obj, IConstChartRow): raise FP_ParameterError( "HVO does not refer to an IConstChartRow" ) return obj return row_or_hvo def __ResolveTag(self, tag_or_hvo): if isinstance(tag_or_hvo, int): obj = self.project.Object(tag_or_hvo) if not isinstance(obj, IConstChartTag): raise FP_ParameterError( "HVO does not refer to an IConstChartTag" ) return obj return tag_or_hvo