U
    PeK                     @   sx   d Z ddlZddlZddlZddlZddlmZ ddlmZ dZ	G dd deZ
eZG dd	 d	eZG d
d deZdS )z
.. warning::

    The classes in this file are internal and may well be removed to an
    external kivy-pytest package or similar in the future. Use at your own
    risk.
    N)deque)UnitTestTouch)UnitKivyAppc                       s4   e Zd Z fddZdd Zdd Zdd Z  ZS )	AsyncUnitTestTouchc                    s"   d | _ d| _tt| j|| d S NT)Zgrab_exclusive_classZis_touchsuperr   __init__)selflargskwargs	__class__ ;/tmp/pip-unpacked-wheel-xzebddm3/kivy/tests/async_common.pyr      s    zAsyncUnitTestTouch.__init__c                 G   s   | j d|  d S )Nbegin	eventloop_dispatch_inputr	   argsr   r   r   
touch_down   s    zAsyncUnitTestTouch.touch_downc                 C   s>   | j j}| ||jd  ||jd  d | j d|  d S )Ng      ?)xyupdate)r   Zwindowmovewidthheightr   )r	   r   r   winr   r   r   
touch_move   s    zAsyncUnitTestTouch.touch_movec                 G   s   | j d|  d S )Nendr   r   r   r   r   touch_up%   s    zAsyncUnitTestTouch.touch_up)__name__
__module____qualname__r   r   r   r    __classcell__r   r   r   r   r      s   r   c                       sr   e Zd ZdZdZdZi Zg Z fddZdd Z	dd Z
dd
dZdd Zdd Zdd Zdd Zdd Z  ZS )WidgetResolverz:It assumes that the widget tree strictly forms a DAG.
    Nc                    s(   || _ i | _g | _tt| jf | d S N)base_widget_kwargs_filter_funcs_filterr   r%   r   )r	   r'   r   r   r   r   r   8   s    zWidgetResolver.__init__c                 C   s&   | j d k	r| j S | js"| js"| jS d S r&   )matched_widgetr(   r)   r'   r	   r   r   r   __call__>   s
    
zWidgetResolver.__call__c                 K   s   | j | d S r&   )r(   r   )r	   kwargs_filterr   r   r   matchF   s    zWidgetResolver.matchr   c                 C   s   | j | d S r&   )r)   extend)r	   Zfuncs_filterr   r   r   match_funcsI   s    zWidgetResolver.match_funcsc                    sJ   t  fdd| jD sdS | j D ]\}}t |t|kr& dS q&dS )Nc                 3   s   | ]}| V  qd S r&   r   ).0funcwidgetr   r   	<genexpr>M   s     z.WidgetResolver.check_widget.<locals>.<genexpr>FT)allr)   r(   itemsgetattr_unique_value)r	   r4   attrvalr   r3   r   check_widgetL   s    zWidgetResolver.check_widgetc                 C   s   t d| j| j| j|d S )NzXCannot find widget matching <{}, {}> starting from base widget "{}" doing "{}" traversal)
ValueErrorformatr(   r)   r'   )r	   opr   r   r   	not_foundV   s       zWidgetResolver.not_foundc                 K   sX   | j f | | j}t| jg}|rJ| }||r<t|dS ||j q| d d S )Nr'   down)	r.   r<   r   r'   popleftr%   r/   childrenr@   )r	   r-   checkfifor4   r   r   r   rB   \   s    
zWidgetResolver.downc                 K   sV   | j f | | j}| j}|d k	rH||r2t|dS |j}||krBqH|}q| d d S )NrA   up)r.   r<   r'   r%   parentr@   )r	   r-   rE   rH   Z
new_parentr   r   r   rG   j   s    
zWidgetResolver.upc                 K   s   | j f | | j}| j}d }|d k	r~t|g}|rd| }||krDq.||rVt|dS ||j q.|}|j}||krxq~|}q| 	d d S )NrA   	family_up)
r.   r<   r'   r   rC   r%   r/   rD   rH   r@   )r	   r-   rE   r'   Zalready_checked_baserF   r4   Znew_base_widgetr   r   r   rI   {   s&    

zWidgetResolver.family_up)r   )r!   r"   r#   __doc__r'   r*   r(   r)   r   r,   r.   r0   r<   r@   rB   rG   rI   r$   r   r   r   r   r%   ,   s   

r%   c                       s   e Zd ZdZdZdZdZ fddZdd Zd% fdd		Z	d&d
dZ
d'ddZdd Zd(ddZd)ddZd*ddZd+ddZd,d#d$Z  ZS )-r   zBase class to use with async test apps.

    .. warning::

        The classes in this file are internal and may well be removed to an
        external kivy-pytest package or similar in the future. Use at your own
        risk.
    FNc                    sB   t  jf |  fdd} d|  fdd} d| d S )Nc                     s
   d _ d S r   )app_has_startedr
   r+   r   r   started_app   s    z)UnitKivyApp.__init__.<locals>.started_appZon_startc                     s
   d _ d S r   )app_has_stoppedrL   r+   r   r   stopped_app   s    z)UnitKivyApp.__init__.<locals>.stopped_appZon_stop)r   r   Zfbind)r	   r   rM   rO   r   r+   r   r      s
    zUnitKivyApp.__init__c                 C   s,   ddl m} |d k	r|| |jj| _d S Nr   )Clock)
kivy.clockrQ   Zinit_async_libZ
_async_libsleepasync_sleep)r	   	async_librQ   r   r   r   set_async_lib   s    
zUnitKivyApp.set_async_libc                    s"   |  | tt| j|dI d H S )N)rU   )rV   r   r   	async_run)r	   rU   r   r   r   rW      s    
zUnitKivyApp.async_runc                 C   s"   |d krddl m} |}t|dS )Nr   WindowrA   )kivy.core.windowrY   r%   )r	   r'   rY   r   r   r   resolve_widget   s    zUnitKivyApp.resolve_widget?c                    s6   ddl m} |j}|j|| k r2| |I d H  qd S rP   )rR   rQ   framesrT   )r	   nZ
sleep_timerQ   Zframes_startr   r   r   wait_clock_frames   s    zUnitKivyApp.wait_clock_framesc              	   C   s2  ddl m}m}m} d}|jd k	rJ|jj|j}|dkrJ|jj|j t|j	t|j
 }}|||fdd}	|	 |dddd |  W 5 Q R X |	|j |	  |	j}
|	|j |jd k	r|dkr|jj||j g }|D ]F\}}t|}t|}|| d |d  }|t|
||d   q|S )Nr   )Fbo
ClearColorClearBuffersT)sizeZwith_stencilbuffer   )Zkivy.graphicsr`   ra   rb   rH   ZcanvasZindexofremoveintr   r   addZdrawpixelsinsertappendtuple)r	   r4   Z	positionsr`   ra   rb   Zcanvas_parent_indexwhZfborj   valuesr   r   ir   r   r   get_widget_pos_pixel   s0    
z UnitKivyApp.get_widget_pos_pixel皙??c                 C  s  |d kr|\}}	n.|d kr,|j |j \}}	n|j |ddi\}}	t||	}
t }|
  | dI d H  d|
jfV  |s|s| |I d H  |
	  | dI d H  d|
jfV  d S d}|r|\}}n|j
d }|jd }t | |k rTd}| |I d H  |
|t d d |  |	t d d |   | dI d H  d	|
jfV  q|r|r|
||	 | dI d H  d	|
jfV  |
	  | dI d H  d|
jfV  d S )
NinitialF   rB   rG   g       @T   r   )	to_windowcenterr   timeperf_counterr   r_   posrT   r    r   r   r   random)r	   r|   r4   durationZ
pos_jitterZwidget_jitterZ	jitter_dtZ
end_on_posr   r   touchtsmoveddxdyr   r   r   do_touch_down_up   sJ    




zUnitKivyApp.do_touch_down_upZcenter_xZcenter_yr   r   r      c                 C  sj  |dkr$|\}}|| ||  }}n|dkrrt ||d }t ||d }|||\}}||| || \}}n8|j|ddi\}}|j|d | |d | dd\}}|dk	r|dkr|\}}n|j|ddi \}}}nT|dk	r*|\}}t ||	d | }t ||	d | }||| \}}}n||f}t||}|  | dI dH  |
rj| |
I dH  d|jfV  || | }|| | }t }t	|D ]p}| t
d|t |  ||  I dH  |||d |  ||d |   | dI dH  d	|jfV  q|j|krB|j|  | dI dH  d	|jfV  |  | dI dH  d
|jfV  dS )a[  Initiates a touch down, followed by some dragging to a target
        location, ending with a touch up.

        `origin`: These parameters specify where the drag starts.
        - If ``widget`` is None, it starts at ``pos`` (in window coordinates).
          If ``dx``/``dy`` is used, it is in the window coordinate system also.
        - If ``pos`` is None, it starts on the ``widget`` as specified by
          ``widget_loc``. If ``dx``/``dy`` is used, it is in the ``widget``
          coordinate system.
        - If neither is None, it starts at ``pos``, but in the ``widget``'s
          coordinate system (:meth:`~kivy.uix.widget.Widget.to_window` is used
          on it). If ``dx``/``dy`` is used, it is in the ``widget``
          coordinate system.

        `target`: These parameters specify where the drag ends.
        - If ``target_pos`` and ``target_widget`` is None, then ``dx`` and
          ``dy`` is used relative to the position where the drag started.
        - If ``target_widget`` is None, it ends at ``target_pos``
          (in window coordinates).
        - If ``target_pos`` is None, it ends on the ``target_widget`` as
          specified by ``target_widget_loc``. ``target_widget_offset``, is an
          additional ``(x, y)`` offset relative to ``target_widget_loc``.
        - If neither is None, it starts at ``target_pos``, but in the
          ``target_widget``'s coordinate system
          (:meth:`~kivy.uix.widget.Widget.to_window` is used on it).

        When ``widget`` and/or ``target_widget`` are specified, ``widget_loc``
        and ``target_widget_loc``, respectively, indicate where on the widget
        the drag starts/ends. It is a a tuple with property names of the widget
        to loop up to get the value. The default is
        ``('center_x', 'center_y')`` so the drag would start/end in the
        widget's center.
        Nr   rv   ru   F)ru   rB           r   rG   )r8   rx   r   r   r_   rT   r|   rz   r{   rangemaxr   r    )r	   r|   r4   
widget_locr   r   
target_postarget_widgettarget_widget_offsettarget_widget_loc
long_pressr~   drag_nr   r   txtyw_xw_yx_offy_offr   ts0rq   r   r   r   do_touch_drag  sf    '
 
 




$
zUnitKivyApp.do_touch_drag   c                   s  |dkr|\}}nJ|dkrHt ||d }t ||d }|||\}}n|j|ddi\}}dkrltd fdd}t||}|  | dI dH  |r| |I dH  d	|jfV  t	 }| \}}d}t
|j|rt
|j|s||krtd
|j||ftd|
| }td|	t	 |  | }|d7 }| |I dH  |j\}}|||| |  ||| |   | dI dH  d|jfV  | \}}q|  | dI dH  d|jfV  dS )a  Very similar to :meth:`do_touch_drag`, except it follows the target
        widget, even if the target widget moves as a result of the drag, the
        drag will follow it until it's on the target widget.

        `origin`: These parameters specify where the drag starts.
        - If ``widget`` is None, it starts at ``pos`` (in window coordinates).
        - If ``pos`` is None, it starts on the ``widget`` as specified by
          ``widget_loc``.
        - If neither is None, it starts at ``pos``, but in the ``widget``'s
          coordinate system (:meth:`~kivy.uix.widget.Widget.to_window` is used
          on it).

        `target`: These parameters specify where the drag ends.
        - If ``target_pos`` is None, it ends on the ``target_widget`` as
          specified by ``target_widget_loc``. ``target_widget_offset``, is an
          additional ``(x, y)`` offset relative to ``target_widget_loc``.
        - If ``target_pos`` is not None, it starts at ``target_pos``, but in
          the ``target_widget``'s coordinate system
          (:meth:`~kivy.uix.widget.Widget.to_window` is used on it).

        When ``widget`` and/or ``target_widget`` are specified, ``widget_loc``
        and ``target_widget_loc``, respectively, indicate where on the widget
        the drag starts/ends. It is a a tuple with property names of the widget
        to loop up to get the value. The default is
        ``('center_x', 'center_y')`` so the drag would start/end in the
        widget's center.
        Nr   rv   ru   Fztarget_widget must be specifiedc                     sT    d k	rj  ddiS \} }td |  }td | } ||S d S )Nru   Fr   rv   )rx   r8   )r   r   Zwt_xZwt_yr   r   r   r   r   r   
get_target  s    z4UnitKivyApp.do_touch_drag_follow.<locals>.get_targetrB   z7Exceeded the maximum number of iterations, but {} != {}r   r   rG   )r8   rx   r=   r   r   r_   rT   r|   rz   r{   mathiscloser   r   	Exceptionr>   r   r   r    )r	   r|   r4   r   r   r   r   r   r   r~   r   Zmax_nr   r   r   r   r   r   r   r   r   rq   Zrem_iZrem_tr   r   r   do_touch_drag_follow~  sN    !
	


 
$z UnitKivyApp.do_touch_drag_followc                   s   dk	r fdd|D }|d \}}|dd }t ||}|  | dI dH  |rh| |I dH  d|jfV  t }t|}	t|D ]^\}
\}}| t	d|t |  |	|
  I dH  |
|| | dI dH  d|jfV  q|  | dI dH  d	|jfV  dS )
a;  Drags the touch along the specified path.

        :parameters:

            `path`: list
                A list of position tuples the touch will follow. The first
                item is used for the touch down and the rest for the move.
            `axis_widget`: a Widget
                If None, the path coordinates is in window coordinates,
                otherwise, we will first transform the path coordinates
                to window coordinates using
                :meth:`~kivy.uix.widget.Widget.to_window` of the specified
                widget.
        Nc                    s   g | ]} j |d diqS )ru   F)rx   )r1   paxis_widgetr   r   
<listcomp>  s     z2UnitKivyApp.do_touch_drag_path.<locals>.<listcomp>r   rv   rB   r   r   rG   )r   r   r_   rT   r|   rz   r{   len	enumerater   r   r    )r	   pathr   r   r~   r   r   r   r   r^   rq   Zx2y2r   r   r   do_touch_drag_path  s,    

zUnitKivyApp.do_touch_drag_pathr   皙?rv   c                 C  st  ddl m} |dkrd}| }|j|}ddddh}t|| rZtd	t|| d
ddddddddddddddddd}	d }
zt|}
||kr|}
W n tk
r   Y nX || }t	|D ]x}| 
|I d H  |d|d|
| ||kr||	kr|t|@ s|d|
 | dI d H  d||d|
|ffV  q|d|d | dI d H  d||d|
|ffV  d S )Nr   rX    ZspacebarshiftZaltZctrlmetazUnknown modifiers "{}"escapetabZ	backspaceZenterdelrG   rB   rightlefthomer   ZpgupZpgdownZnumlockZcapslockZ
screenlock)   	            i  i  i  i  i  i  i  i  i  i,  i-     Zon_key_downZon_textinputrv   Z	on_key_up)rZ   rY   lowerZ_system_keyboardZstring_to_keycodesetr=   r>   chrr   rT   dispatchr_   )r	   key	modifiersr~   Z	num_pressrY   	key_lowerZkey_codeZknown_modifiersZspecial_keystextdtrq   r   r   r   do_keyboard_key   sd    


zUnitKivyApp.do_keyboard_key)N)N)r\   )NNrs   NFrt   F)NNr   r   r   NNr   r   r   rs   r   )NNr   NNr   r   r   rs   r   r   )Nr   rs   )r   r   rv   )r!   r"   r#   rJ   rK   rN   rT   r   rV   rW   r[   r_   rr   r   r   r   r   r   r$   r   r   r   r   r      sf   	

"            
5                   
a                 
X     
,     r   )rJ   r}   rz   r   oscollectionsr   Z
kivy.testsr   __all__r   objectr9   r%   r   r   r   r   r   <module>   s   l