
    BPc]                     z    d Z ddlmZ ddlmZmZmZmZ ddlm	Z	 ddl
mZ ddlmZ dd	lmZ  G d
 de          ZdS )z^
When elements are selected, these structures provide an advanced API.

.. versionadded:: 1.1
    )OrderedDict)AnyoverloadUnionOptional   )IBaseElement   natural_sort_key)inkex_gettext)AbortExtensionc                       e Zd ZdZd fd	Zd Z fdZ fdZ fdZe	ddd	e
d
e
fd            Ze	deeeef         d	e
d
efd            Zdd
efdZ fdZd Zd fd	Zd Zd Zd Zdddee         fdZd Zd Zd Zd Z xZS )ElementListaf  
    A list of elements, selected by id, iterator or xpath

    This may look like a dictionary, but it is really a list of elements.
    The default iterator is the element objects themselves (not keys) and it is
    possible to key elements by their numerical index.

    It is also possible to look up items by their id and the element object itself.
    Nc                     || _         t                      | _        t                                                       | | j        t          |            d S d S N)svgr   idssuper__init__setlist)selfr   _iter	__class__s      :/usr/share/inkscape/extensions/inkex/elements/_selected.pyr   zElementList.__init__-   sT    ==DHd5kk""""     c                 N    |                                                                  S r   )values__iter__r   s    r   r    zElementList.__iter__4   s    {{}}%%'''r   c                 l    t                                          |                     |                    S r   )r   __getitem___to_keyr   keyr   s     r   r#   zElementList.__getitem__7   s'    ww""4<<#4#4555r   c                 l    t                                          |                     |                    S r   )r   __contains__r$   r%   s     r   r(   zElementList.__contains__:   s'    ww##DLL$5$5666r   c                    ||k    r+||                     d          k    rt          d|           t          |t                    r"|}| j                            |d          }|d S t          |t                    rL|j        }|                     d          }|
|| j        |<   t                      
                    ||           d S t          |          j        }t          d|           )Nidz'Refusing to set bad key in ElementList T)literalzUnknown element type: )get
ValueError
isinstancestrr   getElementByIdr	   xml_pathr   r   __setitem__type__name__)r   orig_keyelemr&   
element_idkindr   s         r   r2   zElementList.__setitem__=   s    tDHHTNN : :QxQQRRRdC   	C8**4*>>D|dL)) 		>-C$J%'*$GGT*****::&D<d<<===r   r&   defaultreturnc                     d S r    r   r&   r9   s      r   r$   zElementList._to_keyQ       r   c                     d S r   r<   r=   s      r   r$   zElementList._to_keyU   r>   r   c                 :   | r||}t          |t                    r't          |                                           |         S t          |t                    r|j        S t          |t                    r'|d         dk    r| j                            ||          S |S )z:Takes a key (id, element, etc) and returns an xml_path keyNr   /)	r.   intr   keysr	   r1   r/   r   r,   r=   s      r   r$   zElementList._to_keyY   s      	CKCc3 	*		$$S))c<(( 	 <c3 	*CFcMM8<<S)))
r   c                 z    | j                                          t                                                       dS )zAlso clear idsN)r   clearr   )r   r   s    r   rE   zElementList.clearf   s*    r   c                 B    |                                    | j        |  dS )a  
        Sets the currently selected elements to these ids, any existing
        selection is cleared.

        Arguments a list of element ids, element objects or
        a single xpath expression starting with ``//``.

        All element objects must have an id to be correctly set.

        >>> selection.set("rect123", "path456", "text789")
        >>> selection.set(elem1, elem2, elem3)
        >>> selection.set("//rect")
        N)rE   add)r   r   s     r   r   zElementList.setk   s"     	

#r   c                     t                                          |                     |d                    }| j                            |                    d                     |S )z4Remove the key item or remove the last item selected)r9   r*   )r   popr$   r   r,   )r   r&   itemr   s      r   rJ   zElementList.pop|   sK    ww{{4<<R<8899TXXd^^$$$r   c                     t          |          dk    rVt          |d         t                    r;|d                             d          r | j                            |d                   }|D ]}|| |<   dS )z#Like set() but does not clear firstr
   r   z//N)lenr.   r/   
startswithr   xpath)r   r   r6   s      r   rG   zElementList.add   sv     s88q==ZA44=Q9J9J49P9P=(..Q((C 	 	DDJJ	 	r   c                     t          | j                  } |j        d t          |                                 d           D               |S )zGet the selected elements by z-order (stacking order), ordered from bottom to
        top

        .. versionadded:: 1.2
            :func:`paint_order` has been renamed to :func:`rendering_order`c                     g | ]\  }}|S r<   r<   ).0_r6   s      r   
<listcomp>z/ElementList.rendering_order.<locals>.<listcomp>   s,       At   r   c                 ,    t          | d                   S )Nr   r   )xs    r   <lambda>z-ElementList.rendering_order.<locals>.<lambda>   s    0@10F0F r   )r&   )r   r   r   sorteditems)r   new_lists     r   rendering_orderzElementList.rendering_order   si     tx(( 	 %JJLL&F&F       	
 	
 r   c                 F    t          | j        fd| D                       S )zYFilter selected elements of the given type, returns a new SelectedElements
        objectc                 8    g | ]}rt          |          |S r<   r.   )rR   etypess     r   rT   z&ElementList.filter.<locals>.<listcomp>   s-    LLLQeLz!U7K7KLqLLLr   r   r   )r   r`   s    `r   filterzElementList.filter   s3     HLLLL$LLL
 
 	
r   )	error_msgrc   c                     | j         | }|sP|?t          d                              d                    d |D                                 }t	          |          |S )a  Filter selected elements of the given type, returns a new SelectedElements
        object. If the selection is empty, abort the extension.

        .. versionadded:: 1.2

        :param error_msg: e
        :type error_msg: str, optional

        Args:
            *types (Type) : type(s) to filter the selection by
            error_msg (str, optional): error message that is displayed if the selection
                is empty, defaults to
                ``_("Please select at least one element of type(s) {}")``.
                Defaults to None.

        Raises:
            AbortExtension: if the selection is empty

        Returns:
            ElementList: filtered selection
        Nz?Please select at least one element of the following type(s): {}z, c                     g | ]	}|j         
S r<   )r4   )rR   r3   s     r   rT   z.ElementList.filter_nonzero.<locals>.<listcomp>   s    #D#D#DdDM#D#D#Dr   )rb   r   formatjoinr   )r   rc   r`   filtereds       r   filter_nonzerozElementList.filter_nonzero   sr    , 4;& 	, )U &#D#De#D#D#DEEFF  !+++r   c                 T    fdt          | j        fd| D                       S )z[Like filter, but will enter each element searching for any child of the given
        typesc              3   d   K   rt          |           r| V  | D ]} |          E d {V  d S r   r^   )r6   child_recurser`   s     r   rm   z!ElementList.get.<locals>._recurse   se       JtU33 


 + +#8E??********+ +r   c                 h    g | ].} |          D ] }t          |t          t          f          |!/S r<   )r.   r	   r/   )rR   r_   rrm   s      r   rT   z#ElementList.get.<locals>.<listcomp>   s]       !!  a,!455	   r   ra   )r   r`   rm   s    `@r   r,   zElementList.get   sa    	+ 	+ 	+ 	+ 	+ 	+ H     
 
 	
r   c                 N      fd j                                         D             S )zCFor compatibility, return regular dictionary of id -> element pairsc                 (    i | ]\  }}||         S r<   r<   )rR   eidxidr   s      r   
<dictcomp>z'ElementList.id_dict.<locals>.<dictcomp>   s#    @@@83T#Y@@@r   )r   rY   r!   s   `r   id_dictzElementList.id_dict   s)    @@@@tx~~/?/?@@@@r   c                 6    t          d | D             d          S )a  
        Gets a :class:`inkex.transforms.BoundingBox` object for the selected items.

        Text objects have a bounding box without width or height that only
        reflects the coordinate of their anchor. If a text object is a part of
        the selection's boundary, the bounding box may be inaccurate.

        When no object is selected or when the object's location cannot be
        determined (e.g. empty group or layer), all coordinates will be None.
        c                 6    g | ]}|                                 S r<   )bounding_box)rR   r6   s     r   rT   z,ElementList.bounding_box.<locals>.<listcomp>   s$    999DD%%''999r   N)sumr!   s    r   rx   zElementList.bounding_box   s#     99D9994@@@r   c                     | D ]}|c S dS )z+Returns the first item in the selected listNr<   )r   r6   s     r   firstzElementList.first   s     	 	DKKKtr   r   )r4   
__module____qualname____doc__r   r    r#   r(   r2   r   r   r$   r   rB   r	   r/   rE   r   rJ   rG   r[   rb   r   ri   r,   ru   rx   r{   __classcell__)r   s   @r   r   r   "   s        # # # # # #( ( (6 6 6 6 67 7 7 7 7> > > > >( 4 # #    X 5lC!78 3 3    X C        
  "         &
 
 
 AE       >
 
 
(A A AA A A      r   r   N)r~   collectionsr   typingr   r   r   r   interfaces.IElementr	   _utilsr   localizationr   utilsr   r   r<   r   r   <module>r      s   &  $ # # # # # 1 1 1 1 1 1 1 1 1 1 1 1 . . . . . . $ $ $ $ $ $ ( ( ( ( ( ( " " " " " "K K K K K+ K K K K Kr   