U
    P’“eÈL  ã                   @   sâ   U d Z dZddlZddlZddlmZ ddlmZ ddlm	Z	 ddl
mZ ddlmZ dd	lmZ dd
lmZ dZG dd„ deƒZG dd„ dƒZedeƒZeed< G dd„ deƒZeƒ Zddd„Zddd„Zddd„Zdd„ ZdS )a+  
Kivy Base
=========

This module contains the Kivy core functionality and is not intended for end
users. Feel free to look through it, but bare in mind that calling any of
these methods directly may result in an unpredictable behavior as the calls
access directly the event loop of an application.
)Ú	EventLoopÚEventLoopBaseÚExceptionHandlerÚExceptionManagerBaseÚExceptionManagerÚrunTouchAppÚasync_runTouchAppÚstopTouchAppé    N)ÚConfig)ÚLogger)Úplatform)ÚClock)ÚEventDispatcher)ÚBuilder)Úregister_contextc                   @   s   e Zd ZdZdd„ ZdS )r   a®  Base handler that catches exceptions in :func:`runTouchApp`.
    You can subclass and extend it as follows::

        class E(ExceptionHandler):
            def handle_exception(self, inst):
                Logger.exception('Exception caught by ExceptionHandler')
                return ExceptionManager.PASS

        ExceptionManager.add_handler(E())

    Then, all exceptions will be set to PASS, and logged to the console!
    c                 C   s   t jS )aæ  Called by :class:`ExceptionManagerBase` to handle a exception.

        Defaults to returning :attr:`ExceptionManager.RAISE` that re-raises the
        exception. Return :attr:`ExceptionManager.PASS` to indicate that the
        exception was handled and should be ignored.

        This may be called multiple times with the same exception, if
        :attr:`ExceptionManager.RAISE` is returned as the exception bubbles
        through multiple kivy exception handling levels.
        )r   ÚRAISE)ÚselfÚ	exception© r   ú-/tmp/pip-unpacked-wheel-xzebddm3/kivy/base.pyÚhandle_exception3   s    z!ExceptionHandler.handle_exceptionN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r   %   s   r   c                   @   s8   e Zd ZdZdZdZdd„ Zdd„ Zdd	„ Zd
d„ Z	dS )r   z-ExceptionManager manages exceptions handlers.r	   é   c                 C   s   g | _ tj| _d S ©N)Úhandlersr   r   Úpolicy©r   r   r   r   Ú__init__K   s    zExceptionManagerBase.__init__c                 C   s   || j kr| j  |¡ dS )z)Add a new exception handler to the stack.N)r   Úappend©r   Úclsr   r   r   Úadd_handlerO   s    
z ExceptionManagerBase.add_handlerc                 C   s   || j kr| j  |¡ dS )z,Remove the exception handler from the stack.N)r   Úremover"   r   r   r   Úremove_handlerT   s    
z#ExceptionManagerBase.remove_handlerc                 C   s.   | j }| jD ]}| |¡}|tjkr|}q|S )zOCalled when an exception occurred in the :func:`runTouchApp`
        main loop.)r   r   r   r   ÚPASS)r   ÚinstÚretÚhandlerÚrr   r   r   r   Y   s    


z%ExceptionManagerBase.handle_exceptionN)
r   r   r   r   r   r'   r    r$   r&   r   r   r   r   r   r   A   s   r   r   c                       sò   e Zd ZdZdZ‡ fdd„Zedd„ ƒZdd„ Zd	d
„ Z	d8dd„Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Zd,d-„ Zd.d/„ Zd0d1„ Zd2d3„ Zd4d5„ Zd6d7„ Z‡  Z S )9r   zYMain event loop. This loop handles the updating of input and
    dispatching events.
    )Úon_startÚon_pauseÚon_stopc                    sN   t t| ƒ ¡  d| _g | _g | _d| _d| _g | _g | _	g | _
d | _g | _d S )NFÚidle)Úsuperr   r    ÚquitÚinput_eventsÚpostproc_modulesÚstatusÚstoppingÚinput_providersÚinput_providers_autoremoveÚevent_listenersÚwindowÚme_listr   ©Ú	__class__r   r   r    r   s    zEventLoopBase.__init__c                 C   s   | j S )zIReturn the list of all touches currently in down or move states.
        )r:   r   r   r   r   Útouches   s    zEventLoopBase.touchesc                 C   s&   ddl }| js"t d¡ t d¡ dS )z&Ensure that we have a window.
        r	   Nz#App: Unable to get a Window, abort.r   )Zkivy.core.windowr9   r   ÚcriticalÚsysÚexit)r   Zkivyr   r   r   Úensure_window…   s    
zEventLoopBase.ensure_windowc                 C   s
   || _ dS )z0Set the window used for the event loop.
        N)r9   ©r   r9   r   r   r   Ú
set_window   s    zEventLoopBase.set_windowFc                 C   s*   || j kr&| j  |¡ |r&| j |¡ dS )z=Add a new input provider to listen for touch events.
        N)r6   r!   r7   )r   ÚproviderZauto_remover   r   r   Úadd_input_provider’   s    
z EventLoopBase.add_input_providerc                 C   s0   || j kr,| j  |¡ || jkr,| j |¡ dS )zRemove an input provider.

        .. versionchanged:: 2.1.0
            Provider will be also removed if it exist in auto-remove list.
        N)r6   r%   r7   ©r   rD   r   r   r   Úremove_input_providerš   s    

z#EventLoopBase.remove_input_providerc                 C   s   || j kr| j  |¡ dS )z;Add a new event listener for getting touch events.
        N)r8   r!   ©r   Úlistenerr   r   r   Úadd_event_listener¥   s    
z EventLoopBase.add_event_listenerc                 C   s   || j kr| j  |¡ dS )z0Remove an event listener from the list.
        N)r8   r%   rH   r   r   r   Úremove_event_listener«   s    
z#EventLoopBase.remove_event_listenerc                 C   sD   | j dkrdS d| _ d| _t ¡  | jD ]}| ¡  q(|  d¡ dS )zôMust be called before :meth:`EventLoopBase.run()`. This starts all
        configured input providers.

        .. versionchanged:: 2.1.0
            Method can be called multiple times, but event loop will start only
            once.
        ÚstartedNFr,   )r4   r1   r   Zstart_clockr6   ÚstartÚdispatchrF   r   r   r   rM   ±   s    


zEventLoopBase.startc                 C   s   d| _ |  ¡  d| _dS )zHExit from the main loop and stop all configured
        input providers.TÚclosedN)r1   Ústopr4   r   r   r   r   ÚcloseÂ   s    zEventLoopBase.closec                 C   s`   | j dkrdS t| jdd… ƒD ]}| ¡  |  |¡ q g | _t ¡  d| _d| _ |  	d¡ dS )zòStop all input providers and call callbacks registered using
        `EventLoop.add_stop_callback()`.

        .. versionchanged:: 2.1.0
            Method can be called multiple times, but event loop will stop only
            once.
        rL   NFÚstoppedr.   )
r4   Úreversedr6   rP   rG   r2   r   Z
stop_clockr5   rN   rF   r   r   r   rP   É   s    
zEventLoopBase.stopc                 C   s   || j kr| j  |¡ dS )z^Add a postproc input module (DoubleTap, TripleTap, DeJitter
        RetainTouch are defaults).N)r3   r!   ©r   Úmodr   r   r   Úadd_postproc_moduleã   s    
z!EventLoopBase.add_postproc_modulec                 C   s   || j kr| j  |¡ dS )zRemove a postproc module.N)r3   r%   rT   r   r   r   Úremove_postproc_moduleé   s    
z$EventLoopBase.remove_postproc_modulec                 G   s<   zddl m} |ƒ  W n  tk
r6   t d¡ Y dS X dS )z+Remove android presplash in SDL2 bootstrap.r	   )Úremove_presplashzLBase: Failed to import "android" module. Could not remove android presplash.N)ÚandroidrX   ÚImportErrorr   Úwarning)r   ÚargsrX   r   r   r   Úremove_android_splashî   s    
ÿz#EventLoopBase.remove_android_splashc              
   C   sÄ  |dkr| j  |¡ n|dkr4|| j kr4| j  |¡ |jsT| jD ]}| d||¡ q@|js^dS d|_|jdd… D ]<}|ƒ }|dkr”|j |¡ qr| 	¡ }||kræ|dk	ræ| 
¡  z| ||¡ W n  tk
rä   | ¡  Y qrY nX ||_|j 
¡  |dkrn†|dkrF|jjr8|jj | d|¡ W 5 Q R X n| d|¡ nB|dkrˆ|jjr||jj | d|¡ W 5 Q R X n| d|¡ |j ¡  d|_||krr|dk	rr| ¡  qrd	|_| ¡  dS )
zàThis function is called by :meth:`EventLoopBase.dispatch_input()`
        when we want to dispatch an input event. The event is dispatched to
        all listeners and if grabbed, it's dispatched to grabbed widgets.
        ÚbeginÚendZ	on_motionNTÚupdateZon_touch_moveZon_touch_upF)r:   r!   r%   Zgrab_exclusive_classr8   rN   Zis_touchZ
grab_stateZ	grab_listZget_root_windowÚpushZtransform_motion_event_2dÚAttributeErrorÚpopZgrab_currentÚ_contextZsandboxZdispatch_done)r   ÚetypeÚmerI   Zweak_widgetZwidZroot_windowr   r   r   Úpost_dispatch_inputù   sX    












z!EventLoopBase.post_dispatch_inputc                 G   s&   || j kr| j  |¡ | j  |¡ d S r   )r2   r%   r!   )r   Zevr   r   r   Ú_dispatch_input6  s    
zEventLoopBase._dispatch_inputc                 C   s^   | j D ]}|j| jd q| jD ]}|j| jd| _q | j}|j}| j}|rZ||dƒŽ  qHdS )zCalled by :meth:`EventLoopBase.idle()` to read events from input
        providers, pass events to postproc, and dispatch final events.
        )Zdispatch_fn)Úeventsr	   N)r6   r`   rh   r3   Úprocessr2   rc   rg   )r   rD   rU   r2   rc   rg   r   r   r   Údispatch_input<  s    

zEventLoopBase.dispatch_inputc              
   C   st   | j sp| jdkrpz|  ¡  | jr*| j ¡  W q  tk
rl } z"t |¡}|tjkr\t	ƒ  ‚ n W 5 d }~X Y q X q d S )NrL   )
r1   r4   r/   r9   ÚmainloopÚBaseExceptionr   r   r   r   ©r   r(   r+   r   r   r   rl   P  s    

zEventLoopBase.mainloopc              
   Ã   sŒ   | j sv| jdkrvz"|  ¡ I d H  | jr0| j ¡  W q  tk
rr } z"t |¡}|tjkrbt	ƒ  ‚ n W 5 d }~X Y q X q t
 d¡ |  ¡  d S )NrL   z%Window: exiting mainloop and closing.)r1   r4   Ú
async_idler9   rl   rm   r   r   r   r   r   ÚinforQ   rn   r   r   r   Úasync_mainloop_  s    


zEventLoopBase.async_mainloopc                 C   s    t  ¡  | js|  ¡  | js$t ¡  | js2t  ¡  | js@t ¡  | jsl| j}|rl|jj	rl| 
d¡ | 
d¡ t| jƒdkršt d¡ t d¡ |  ¡  dS | jS )a  This function is called after every frame. By default:

           * it "ticks" the clock to the next frame.
           * it reads all input and dispatches events.
           * it dispatches `on_update`, `on_draw` and `on_flip` events to the
             window.
        Úon_drawÚon_flipr	   ú*Base: No event listeners have been createdúBase: Application will leaveF)r   Ztickr1   rk   r   ÚsyncÚ	tick_drawr9   ÚcanvasÚneeds_redrawrN   Úlenr8   r   Úerrorr@   rB   r   r   r   r/   q  s(    




zEventLoopBase.idlec                 Ã   s¦   t  ¡ I dH  | js|  ¡  | js*t ¡  | js8t  ¡  | jsFt ¡  | jsr| j}|rr|jj	rr| 
d¡ | 
d¡ t| jƒdkr t d¡ t d¡ |  ¡  dS | jS )zeIdentical to :meth:`idle`, but instead used when running
        within an async event loop.
        Nrr   rs   r	   rt   ru   F)r   Z
async_tickr1   rk   r   rv   rw   r9   rx   ry   rN   rz   r8   r   r{   r@   rB   r   r   r   ro   œ  s(    



zEventLoopBase.async_idlec                 C   s   | j s|  ¡  q |  ¡  dS )z	Main loopN)r1   r/   r@   r   r   r   r   ÚrunÃ  s    
zEventLoopBase.runc                 C   s   |   ¡  | jr| j  ¡  dS )z)Close the main loop and close the window.N)rQ   r9   r   r   r   r   r@   É  s    zEventLoopBase.exitc                 C   s   dS )zqEvent handler for `on_stop` events which will be fired right
        after all input providers have been stopped.Nr   r   r   r   r   r.   Ï  s    zEventLoopBase.on_stopc                 C   s   dS )zWEvent handler for `on_pause` which will be fired when
        the event loop is paused.Nr   r   r   r   r   r-   Ô  s    zEventLoopBase.on_pausec                 C   s   dS )zkEvent handler for `on_start` which will be fired right
        after all input providers have been started.Nr   r   r   r   r   r,   Ù  s    zEventLoopBase.on_start)F)!r   r   r   r   Z
__events__r    Úpropertyr=   rA   rC   rE   rG   rJ   rK   rM   rQ   rP   rV   rW   r]   rg   rh   rk   rl   rq   r/   ro   r|   r@   r.   r-   r,   Ú__classcell__r   r   r;   r   r   k   s:   

=+'r   c           
      C   s  ddl m}m} | rt ¡  t d¡D ]ˆ\}}t dt	|ƒ ¡ t	|ƒ 
dd¡}t|ƒdkrf| d¡ |\}}| |¡}|d kr”t dt	|ƒ ¡ q&|||ƒ}|r&t |d	¡ q&t| ¡ ƒD ]}	t |	¡ q¼| rîtjrî| tjjkrîtj | ¡ t d
¡ t ¡  tdkrt tj¡ d S )Nr	   )ÚMotionEventFactoryÚkivy_postproc_modulesÚinputzBase: Create provider from %sú,r   Ú zBase: Unknown <%s> providerTz!Base: Start application main looprY   )Z
kivy.inputr   r€   r   rA   r
   Úitemsr   ÚdebugÚstrÚsplitrz   r!   Úgetr[   rE   ÚlistÚvaluesrV   r9   ÚchildrenZ
add_widgetrp   rM   r   r   Úschedule_oncer]   )
Úwidgetr   r€   ÚkeyÚvaluer\   Zprovider_idrD   ÚprU   r   r   r   Ú_runTouchApp_prepareã  s2    





r‘   Fc                 C   s,   t | d |rdS zt ¡  W 5 tƒ  X dS )až  Static main function that starts the application loop.
    You can access some magic via the following arguments:

    See :mod:`kivy.app` for example usage.

    :Parameters:
        `<empty>`
            To make dispatching work, you need at least one
            input listener. If not, application will leave.
            (MTWindow act as an input listener)

        `widget`
            If you pass only a widget, a MTWindow will be created
            and your widget will be added to the window as the root
            widget.

        `embedded`
            No event dispatching is done. This will be your job.

        `widget + embedded`
            No event dispatching is done. This will be your job but
            we try to get the window (must be created by you beforehand)
            and add the widget to it. Very useful for embedding Kivy
            in another toolkit. (like Qt, check kivy-designed)

    ©r   N)r‘   r   r   rl   )r   Úembeddedr   r   r   r     s    
r   c                 Ã   sD   |dk	rt  |¡ t| d |r$dS zt ¡ I dH  W 5 tƒ  X dS )züIdentical to :func:`runTouchApp` but instead it is a coroutine
    that can be run in an existing async event loop.

    ``async_lib`` is the async library to use. See :mod:`kivy.app` for details
    and example usage.

    .. versionadded:: 2.0.0
    Nr’   )r   Zinit_async_libr‘   r   r   rq   )r   r“   Z	async_libr   r   r   r   C  s    	

r   c                   C   sZ   t dkrdS t jdkrdS t jdkrDt js@dt _t dd„ d¡ dS t d¡ t  ¡  dS )	zgStop the current application by leaving the main loop.

    See :mod:`kivy.app` for example usage.
    N)rR   rO   rL   Tc                 S   s   t ƒ S r   )r   )Údtr   r   r   Ú<lambda>f  ó    zstopTouchApp.<locals>.<lambda>r	   z(Base: Leaving application in progress...)r   r4   r5   r   rŒ   r   rp   rQ   r   r   r   r   r   Z  s    


r   )N)NF)NFN)r   Ú__all__r?   ÚosZkivy.configr
   Zkivy.loggerr   Z
kivy.utilsr   Z
kivy.clockr   Z
kivy.eventr   Z	kivy.langr   Zkivy.contextr   r   Úobjectr   r   r   Ú__annotations__r   r‘   r   r   r   r   r   r   r   Ú<module>   s2   
$ ÿ  w
9
'
