B
    't\2                 @   s   d Z ddlmZ ddlmZmZ ddlmZmZm	Z	m
Z
 ddlmZ ddlZdd	d
gZG dd deZG dd	 d	eZddd
ZdS )z
Wrapper for the layout.
    )unicode_literals   )	UIControlBufferControl)	ContainerWindowto_containerConditionalContainer)BufferNLayoutInvalidLayoutErrorwalkc               @   s
  e Zd ZdZd5ddZdd Zdd Zd	d
 Zdd Zdd Z	e
dd Zejdd Ze
dd Zejdd Ze
dd Ze
dd Zdd Zdd Ze
dd Zdd  Ze
d!d" Ze
d#d$ Zd%d& Zd'd( Zd)d* Zd+d, Zd-d. Zd/d0 Zd1d2 Zd3d4 ZdS )6r   aL  
    The layout for a prompt_toolkit
    :class:`~prompt_toolkit.application.Application`.
    This also keeps track of which user control is focused.

    :param container: The "root" container for the layout.
    :param focused_element: element to be focused initially. (Can be anything
        the `focus` function accepts.)
    Nc             C   sp   t || _g | _i | _i | _|d kr\y| jt|   W qf tk
rX   t	dY qfX n
| 
| g | _d S )Nz>Invalid layout. The layout does not contain any Window object.)r   	container_stacksearch_links_child_to_parentappendnextfind_all_windowsStopIterationr   focusvisible_windows)selfr   Zfocused_element r   ;lib/python3.7/site-packages/prompt_toolkit/layout/layout.py__init__   s    

zLayout.__init__c             C   s   d| j | jf S )NzLayout(%r, current_window=%r))r   current_window)r   r   r   r   __repr__6   s    zLayout.__repr__c             c   s&   x |   D ]}t|tr
|V  q
W dS )zJ
        Find all the :class:`.UIControl` objects in this layout.
        N)r   
isinstancer   )r   itemr   r   r   r   :   s    
zLayout.find_all_windowsc             c   s   x|   D ]}|jV  q
W d S )N)r   content)r   r   r   r   r   find_all_controlsB   s    zLayout.find_all_controlsc             C   s  t |tjrTx4|  D ](}t |tr|jj|kr| | dS qW td|f nFt |t	rx2|  D ]&}t |trh|j|krh| | dS qhW td|f nt |t
r||  krtd| std|| _nt|}t |tr||  krtd|f || _ng }x8t|ddD ](}t |tr"|j r"|| q"W x(t| jD ]}||krZ|| _dS qZW |r|d | _dS td	|f dS )
a  
        Focus the given UI element.

        `value` can be either:

        - a :class:`.UIControl`
        - a :class:`.Buffer` instance or the name of a :class:`.Buffer`
        - a :class:`.Window`
        - Any container object. In this case we will focus the :class:`.Window`
          from this container that was focused most recent, or the very first
          focusable :class:`.Window` of the container.
        Nz/Couldn't find Buffer in the current layout: %r.z7Invalid value. Container does not appear in the layout.z*Invalid value. UIControl is not focusable.z7Invalid value. Window does not appear in the layout: %rT)skip_hiddenr   z.Invalid value. Container cannot be focused: %r)r   six	text_typer!   r   buffernamer   
ValueErrorr
   r   is_focusablecurrent_controlr   r   r   r   r   r    r   reversedr   )r   valuecontrolwindowscwr   r   r   r   F   sH    







zLayout.focusc             C   s   t |tjr&| jdkrdS | jj|kS t |tr:| j|kS t |trN| j|kS t|}t |t	rj| j
|kS xt|D ]}|| j
krtdS qtW dS dS )z
        Check whether the given control has the focus.
        :param value: :class:`.UIControl` or :class:`.Window` instance.
        NFT)r   r#   r$   current_bufferr&   r
   r   r)   r   r   r   r   )r   r+   elementr   r   r   	has_focus   s    







zLayout.has_focusc             C   s   | j d jS )zI
        Get the :class:`.UIControl` to currently has the focus.
        )r   r    )r   r   r   r   r)      s    zLayout.current_controlc             C   s@   t |tstx$|  D ]}|j|kr|| _dS qW tddS )zC
        Set the :class:`.UIControl` to receive the focus.
        Nz(Control not found in the user interface.)r   r   AssertionErrorr   r    r   r'   )r   r,   Zwindowr   r   r   r)      s    
c             C   s
   | j d S )z? Return the :class:`.Window` object that is currently focused. r3   )r   )r   r   r   r   r      s    zLayout.current_windowc             C   s   t |tst| j| dS )z: Set the :class:`.Window` object to be currently focused. N)r   r   r4   r   r   )r   r+   r   r   r   r      s    c             C   s   | j | jkS )z% True if we are searching right now. )r)   r   )r   r   r   r   is_searching   s    zLayout.is_searchingc             C   s   | j | jS )zI Return the :class:`.BufferControl` in which we are searching or `None`. )r   getr)   )r   r   r   r   search_target_buffer_control   s    z#Layout.search_target_buffer_controlc             c   s0   x*|   D ]}t|tr
|j r
|V  q
W dS )zl
        Return all the :class:`.Window` objects which are focusable (in the
        'modal' area).
        N)walk_through_modal_arear   r   r    r(   )r   r/   r   r   r   get_focusable_windows   s    zLayout.get_focusable_windowsc                s   | j   fdd|  D S )zO
        Return a list of :class:`.Window` objects that are focusable.
        c                s   g | ]}| kr|qS r   r   ).0r/   )r   r   r   
<listcomp>   s    z8Layout.get_visible_focusable_windows.<locals>.<listcomp>)r   r9   )r   r   )r   r   get_visible_focusable_windows   s    z$Layout.get_visible_focusable_windowsc             C   s   | j }t|tr|jS dS )zD
        The currently focused :class:`~.Buffer` or `None`.
        N)r)   r   r   r%   )r   
ui_controlr   r   r   r0      s    
zLayout.current_bufferc             C   sB   x<|   D ]0}t|tr
t|jtr
|jjj|kr
|jjS q
W dS )zt
        Look in the layout for a buffer with the given name.
        Return `None` when nothing was found.
        N)r   r   r   r    r   r%   r&   )r   Zbuffer_namer/   r   r   r   get_buffer_by_name   s    zLayout.get_buffer_by_namec             C   s   | j }t|tS )z
        Return `True` if the currently focused control is a
        :class:`.BufferControl`. (For instance, used to determine whether the
        default key bindings should be active or not.)
        )r)   r   r   )r   r=   r   r   r   buffer_has_focus   s    zLayout.buffer_has_focusc             C   s.   y| j d jS  tk
r(   | j d jS X dS )zJ
        Get the :class:`.UIControl` to previously had the focus.
        r3   N)r   r    
IndexError)r   r   r   r   previous_control  s    zLayout.previous_controlc             C   s"   t | jdkr| jdd | _dS )z=
        Give the focus to the last focused control.
        r   Nr3   )lenr   )r   r   r   r   
focus_last  s    zLayout.focus_lastc             C   s`   |   }t|dkr\y|| j}W n tk
r<   d}Y nX |d t| }| ||  dS )z:
        Focus the next visible/focusable Window.
        r   r   N)r<   rC   indexr   r'   r   )r   r-   rE   r   r   r   
focus_next  s    
zLayout.focus_nextc             C   s`   |   }t|dkr\y|| j}W n tk
r<   d}Y nX |d t| }| ||  dS )z>
        Focus the previous visible/focusable Window.
        r   r   N)r<   rC   rE   r   r'   r   )r   r-   rE   r   r   r   focus_previous"  s    
zLayout.focus_previousc             c   s   xt | jD ]
}|V  qW dS )zX
        Walk through all the layout nodes (and their children) and yield them.
        N)r   r   )r   ir   r   r   r   2  s    zLayout.walkc             c   sD   | j }x | s&|| jkr&| j| }qW xt|D ]
}|V  q2W dS )zn
        Walk through all the containers which are in the current 'modal' part
        of the layout.
        N)r   Zis_modalr   r   )r   rootr   r   r   r   r8   9  s
    zLayout.walk_through_modal_areac                s&   i   fdd| j   | _dS )z=
        Update child->parent relationships mapping.
        c                s&   x |   D ]}|  |< | q
W d S )N)get_children)er.   )parentsr   r   r   r   M  s    z-Layout.update_parents_relations.<locals>.walkN)r   r   )r   r   )rL   r   r   update_parents_relationsG  s    
zLayout.update_parents_relationsc             C   s   | j   | j S )N)r   clearr   reset)r   r   r   r   rO   V  s    
zLayout.resetc             C   s$   y
| j | S  tk
r   dS X dS )zo
        Return the parent container for the given container, or ``None``, if it
        wasn't found.
        N)r   KeyError)r   r   r   r   r   
get_parent_  s    
zLayout.get_parent)N)__name__
__module____qualname____doc__r   r   r   r!   r   r2   propertyr)   setterr   r5   r7   r9   r<   r0   r>   r?   rB   rD   rF   rG   r   r8   rM   rO   rQ   r   r   r   r   r      s6   	
I			


	c               @   s   e Zd ZdS )r   N)rR   rS   rT   r   r   r   r   r   j  s   Fc             c   s`   t | tst|r(t | tr(|  s(dS | V  x,|  D ] }xt||dD ]
}|V  qJW q8W dS )z:
    Walk through layout, starting at this container.
    N)r"   )r   r   r4   r	   filterrJ   r   )r   r"   r.   rH   r   r   r   r   n  s    )F)rU   Z
__future__r   Zcontrolsr   r   Z
containersr   r   r   r	   Zprompt_toolkit.bufferr
   r#   __all__objectr   	Exceptionr   r   r   r   r   r   <module>   s     [