uim.model.helpers.treeiterator API documentation

# Module `uim.model.helpers.treeiterator`

Expand source code

    # -*- coding: utf-8 -*-
    # Copyright © 2021 Wacom Authors. All Rights Reserved.
    #
    #  Licensed under the Apache License, Version 2.0 (the "License");
    #  you may not use this file except in compliance with the License.
    #  You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    #  Unless required by applicable law or agreed to in writing, software
    #  distributed under the License is distributed on an "AS IS" BASIS,
    #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    #  See the License for the specific language governing permissions and
    #  limitations under the License.
    from typing import List, Optional

    from uim.model.semantics.node import InkNode, StrokeGroupNode

    class StackItem(object):
        """
        Represents an item in the internal stack of the enumerator.

        Parameters
        ----------
        node - `InkNode`
            Reference to node
        index - `int`
            Index of the group node within its parent.
        """

        def __init__(self, node: InkNode, index: int):
            self.__node: InkNode = node
            self.__index: int = index

        @property
        def node(self) -> InkNode:
            """The element at the current position of the enumerator. (`InkNode`, read-only)"""
            return self.__node

        @property
        def index(self) -> int:
            """Index of the current node within its parent.  (`int`, read-only)"""
            return self.__index

        def __repr__(self):
            return f'<StackItem : [index:={self.index}, node-id:={self.node.id}]>'

    class PreOrderEnumerator(object):
        """
        Depth first pre-order traversal of the DOM tree.

        Parameters
        ----------
        node - `InkNode`
            Reference to root node
        """

        def __init__(self, root: InkNode):
            """
            Initializes new instance of the enumerator with the specified parameters.
            :param root: InkNode -
                The node that will be used as a root for the traversal.
            """
            self.__root: InkNode = root
            self.__stack: List[StackItem] = []
            self.__current: Optional[InkNode] = None
            self.__current_index_in_parent: int = 0

        def __iter__(self):
            return self

        def get_depth_level(self) -> int:
            """
            Returns the depth level within the tree.

            Returns
            -------
            depth: int
                Depth within in the resulting tree
            """
            return len(self.__stack)

        def __next__(self):
            """
            Updates the internal state, and update the one in list (current).

            Raises
            -------
            `StopIteration`
                Stops the iteration process
            """
            if self.__current is None:
                self.__current = self.__root  # Will be the root node
                self.__current_index_in_parent = 0
                return self.__current

            current_node: InkNode = self.__current

            if isinstance(current_node, StrokeGroupNode):
                current_group: StrokeGroupNode = current_node

                if (current_group is not None) and (len(current_group.children) > 0):
                    self.__stack.append(StackItem(current_group, self.__current_index_in_parent))
                    self.__current = current_group.children[0]
                    self.__current_index_in_parent = 0
                    return self.__current

            while len(self.__stack) > 0:

                # Get the parent group of the current node (from the top of the stack)
                cur_parent: InkNode = self.__stack[-1].node

                # Calculate the index of the next sibling
                sibling_index_in_parent: int = (self.__current_index_in_parent + 1)

                # Return the next sibling of the current node
                if isinstance(cur_parent, StrokeGroupNode) and sibling_index_in_parent < len(cur_parent.children):
                    self.__current = cur_parent.children[sibling_index_in_parent]
                    self.__current_index_in_parent = sibling_index_in_parent
                    return self.__current

                # No next sibling - pop from the stack
                parent: StackItem = self.__stack.pop()
                self.__current = parent.node
                self.__current_index_in_parent = parent.index
            raise StopIteration

## Classes

`class PreOrderEnumerator (root: InkNode)`

  Depth first pre-order traversal of the DOM tree.

  ## Parameters

  node - `InkNode` Reference to root node

  Initializes new instance of the enumerator with the specified parameters. :param root: InkNode - The node that will be used as a root for the traversal.

  Expand source code

      class PreOrderEnumerator(object):
          """
          Depth first pre-order traversal of the DOM tree.

          Parameters
          ----------
          node - `InkNode`
              Reference to root node
          """

          def __init__(self, root: InkNode):
              """
              Initializes new instance of the enumerator with the specified parameters.
              :param root: InkNode -
                  The node that will be used as a root for the traversal.
              """
              self.__root: InkNode = root
              self.__stack: List[StackItem] = []
              self.__current: Optional[InkNode] = None
              self.__current_index_in_parent: int = 0

          def __iter__(self):
              return self

          def get_depth_level(self) -> int:
              """
              Returns the depth level within the tree.

              Returns
              -------
              depth: int
                  Depth within in the resulting tree
              """
              return len(self.__stack)

          def __next__(self):
              """
              Updates the internal state, and update the one in list (current).

              Raises
              -------
              `StopIteration`
                  Stops the iteration process
              """
              if self.__current is None:
                  self.__current = self.__root  # Will be the root node
                  self.__current_index_in_parent = 0
                  return self.__current

              current_node: InkNode = self.__current

              if isinstance(current_node, StrokeGroupNode):
                  current_group: StrokeGroupNode = current_node

                  if (current_group is not None) and (len(current_group.children) > 0):
                      self.__stack.append(StackItem(current_group, self.__current_index_in_parent))
                      self.__current = current_group.children[0]
                      self.__current_index_in_parent = 0
                      return self.__current

              while len(self.__stack) > 0:

                  # Get the parent group of the current node (from the top of the stack)
                  cur_parent: InkNode = self.__stack[-1].node

                  # Calculate the index of the next sibling
                  sibling_index_in_parent: int = (self.__current_index_in_parent + 1)

                  # Return the next sibling of the current node
                  if isinstance(cur_parent, StrokeGroupNode) and sibling_index_in_parent < len(cur_parent.children):
                      self.__current = cur_parent.children[sibling_index_in_parent]
                      self.__current_index_in_parent = sibling_index_in_parent
                      return self.__current

                  # No next sibling - pop from the stack
                  parent: StackItem = self.__stack.pop()
                  self.__current = parent.node
                  self.__current_index_in_parent = parent.index
              raise StopIteration

  ### Methods

  `def get_depth_level(self) ‑> int`

    Returns the depth level within the tree.

    ## Returns

    `depth` :`int`
      Depth within in the resulting tree
    Expand source code

        def get_depth_level(self) -> int:
            """
            Returns the depth level within the tree.

            Returns
            -------
            depth: int
                Depth within in the resulting tree
            """
            return len(self.__stack)

`class StackItem (node: InkNode, index: int)`

  Represents an item in the internal stack of the enumerator.

  ## Parameters

  node - `InkNode` Reference to node index - `int` Index of the group node within its parent.

  Expand source code

      class StackItem(object):
          """
          Represents an item in the internal stack of the enumerator.

          Parameters
          ----------
          node - `InkNode`
              Reference to node
          index - `int`
              Index of the group node within its parent.
          """

          def __init__(self, node: InkNode, index: int):
              self.__node: InkNode = node
              self.__index: int = index

          @property
          def node(self) -> InkNode:
              """The element at the current position of the enumerator. (`InkNode`, read-only)"""
              return self.__node

          @property
          def index(self) -> int:
              """Index of the current node within its parent.  (`int`, read-only)"""
              return self.__index

          def __repr__(self):
              return f'<StackItem : [index:={self.index}, node-id:={self.node.id}]>'

  ### Instance variables

  `var index : int`

    Index of the current node within its parent. (`int`, read-only)

    Expand source code

        @property
        def index(self) -> int:
            """Index of the current node within its parent.  (`int`, read-only)"""
            return self.__index

  `var node : InkNode`

    The element at the current position of the enumerator. (`InkNode`, read-only)

    Expand source code

        @property
        def node(self) -> InkNode:
            """The element at the current position of the enumerator. (`InkNode`, read-only)"""
            return self.__node