U
    ºñdZú<  ã                   @   sŽ   d dl mZmZ d dlZd dlmZ G dd„ deƒZG dd„ dejƒZ	G dd	„ d	e
ƒZG d
d„ deƒZG dd„ dejƒZG dd„ dejƒZdS )é    )ÚdivisionÚprint_functionN)ÚSelectableIconc                   @   s   e Zd ZdS )ÚTreeWidgetErrorN)Ú__name__Ú
__module__Ú__qualname__© r	   r	   ú1/usr/lib/python3/dist-packages/urwid/treetools.pyr   &   s   r   c                   @   s    e Zd ZdZ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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$S )%Ú
TreeWidgetz9A widget representing something in a nested tree display.é   ú+r   ú-c                 C   s8   || _ d | _t|dƒ | _d| _|  ¡ }| j |¡ d S )NÚget_first_childT)Ú_nodeÚ_innerwidgetÚhasattrÚis_leafÚexpandedÚget_indented_widgetÚ_TreeWidget__superÚ__init__)ÚselfÚnodeÚwidgetr	   r	   r
   r   0   s    zTreeWidget.__init__c                 C   s   | j  S )zS
        Allow selection of non-leaf nodes so children may be (un)expanded
        )r   ©r   r	   r	   r
   Ú
selectable8   s    zTreeWidget.selectablec                 C   sL   |   ¡ }| js4tjdd| j| jg| j f|gdd�}|  ¡ }tj|d|d�S )NZfixedé   )Zdividechars)Úrelativeéd   )ÚwidthÚleft)	Úget_inner_widgetr   ÚurwidZColumnsÚunexpanded_iconÚexpanded_iconr   Úget_indent_colsZPadding)r   r   Úindent_colsr	   r	   r
   r   >   s    ÿþþ ÿzTreeWidget.get_indented_widgetc                 C   s    | j | jg| j | jjjd< dS )z-Update display widget text for parent widgetsr   N)r$   r%   r   Ú_wZbase_widgetZwidget_listr   r	   r	   r
   Úupdate_expanded_iconH   s
     ÿÿzTreeWidget.update_expanded_iconc                 C   s   | j |  ¡  ¡  S ©N)r'   Úget_nodeÚ	get_depthr   r	   r	   r
   r&   N   s    zTreeWidget.get_indent_colsc                 C   s   | j d kr|  ¡ | _ | j S r*   )r   Úload_inner_widgetr   r	   r	   r
   r"   Q   s    

zTreeWidget.get_inner_widgetc                 C   s   t  |  ¡ ¡S r*   )r#   ZTextÚget_display_textr   r	   r	   r
   r-   V   s    zTreeWidget.load_inner_widgetc                 C   s   | j S r*   )r   r   r	   r	   r
   r+   Y   s    zTreeWidget.get_nodec                 C   s    |   ¡  ¡ d t|   ¡  ¡ ƒ S )Nz: )r+   Úget_keyÚstrÚ	get_valuer   r	   r	   r
   r.   \   s    ÿzTreeWidget.get_display_textc                 C   s~   |   ¡ }|dk	r|S |  ¡ }| ¡ }| ¡ }|dkrf|dkrf| ¡ }| ¡ }|d8 }|| ¡ ks,t‚q,|dkrrdS | ¡ S dS )z5Return the next TreeWidget depth first from this one.Nr   r   )Úfirst_childr+   Únext_siblingr,   Ú
get_parentÚAssertionErrorÚ
get_widget)r   Z
firstchildÚthisnodeZnextnodeÚdepthr	   r	   r
   Únext_inorder`   s    zTreeWidget.next_inorderc                 C   sp   | j }| ¡ }|dk	r8| ¡ }| ¡ }|dkr2|S |S n4| ¡ }|dkrT|dkrTdS |dkrd| ¡ }| ¡ S dS )z9Return the previous TreeWidget depth first from this one.Nr   )r   Úprev_siblingr6   Ú
last_childr,   r4   )r   r7   ZprevnodeZ
prevwidgetÚ	lastchildr8   r	   r	   r
   Úprev_inorderw   s    zTreeWidget.prev_inorderc                 C   sZ   | j r
|S |dkr"d| _|  ¡  n4|dkr:d| _|  ¡  n| j ¡ rR| j ||¡S |S dS )z2Handle expand & collapse requests (non-leaf nodes))r   ÚrightTr   FN)r   r   r)   r(   r   r   Úkeypress©r   ÚsizeÚkeyr	   r	   r
   r?   �   s    


zTreeWidget.keypressc                 C   sH   | j s|dks|dkrdS |dkrD||  ¡ krD| j | _|  ¡  dS dS )Nzmouse pressr   Fr   T)r   r&   r   r)   )r   rA   ZeventZbuttonÚcolÚrowÚfocusr	   r	   r
   Úmouse_event�   s    
zTreeWidget.mouse_eventc                 C   s4   | j s| jsdS | j ¡ r,| j ¡ }| ¡ S dS dS )zReturn first child if expanded.N)r   r   r   Úhas_childrenr   r6   )r   Z	firstnoder	   r	   r
   r2   ¨   s    

zTreeWidget.first_childc                 C   sJ   | j s| jsdS | j ¡ r*| j ¡  ¡ }ndS | ¡ }|dkrB|S |S dS )zReturn last child if expanded.N)r   r   r   rG   Úget_last_childr6   r;   )r   r<   Zlastdescendantr	   r	   r
   r;   ³   s    
zTreeWidget.last_childN)r   r   r   Ú__doc__r'   r   r$   r%   r   r   r   r)   r&   r"   r-   r+   r.   r9   r=   r?   rF   r2   r;   r	   r	   r	   r
   r   *   s&   


r   c                   @   sŒ   e Zd ZdZd"dd„Zd#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S )$ÚTreeNodea:  
    Store tree contents and cache TreeWidget objects.
    A TreeNode consists of the following elements:
    *  key: accessor token for parent nodes
    *  value: subclass-specific data
    *  parent: a TreeNode which contains a pointer back to this object
    *  widget: The widget used to render the object
    Nc                 C   s"   || _ || _|| _|| _d | _d S r*   )Ú_keyÚ_parentÚ_valueÚ_depthÚ_widget©r   ÚvalueÚparentrB   r8   r	   r	   r
   r   Í   s
    zTreeNode.__init__Fc                 C   s"   | j dks|dkr|  ¡ | _ | j S )z! Return the widget for this node.NT)rO   Úload_widget©r   Úreloadr	   r	   r
   r6   Ô   s    
zTreeNode.get_widgetc                 C   s   t | ƒS r*   )r   r   r	   r	   r
   rS   Ú   s    zTreeNode.load_widgetc                 C   s<   | j d kr| jd krd| _ n| j d kr6| j ¡ d | _ | j S )Nr   r   )rN   rL   r,   r   r	   r	   r
   r,   Ý   s
    
zTreeNode.get_depthc                 C   s.   |   ¡ dkrd S |  ¡ }|  ¡ }| |¡S d S ©Nr   )r,   r/   r4   Úget_child_index)r   rB   rR   r	   r	   r
   Ú	get_indexä   s
    zTreeNode.get_indexc                 C   s   | j S r*   ©rK   r   r	   r	   r
   r/   ì   s    zTreeNode.get_keyc                 C   s
   || _ d S r*   rY   ©r   rB   r	   r	   r
   Úset_keyï   s    zTreeNode.set_keyc                 C   s   |   ¡  | j|¡ d S r*   )r4   Úchange_child_keyrK   rZ   r	   r	   r
   Ú
change_keyò   s    zTreeNode.change_keyc                 C   s&   | j d kr |  ¡ dkr |  ¡ | _ | j S rV   )rL   r,   Úload_parentr   r	   r	   r
   r4   õ   s    
zTreeNode.get_parentc                 C   s   t dƒ‚dS )z¦Provide TreeNode with a parent for the current node.  This function
        is only required if the tree was instantiated from a child node
        (virtual function)ú(virtual function.  Implement in subclassN©r   r   r	   r	   r
   r^   ú   s    zTreeNode.load_parentc                 C   s   | j S r*   )rM   r   r	   r	   r
   r1      s    zTreeNode.get_valuec                 C   s   |   ¡ dkS rV   )r,   r   r	   r	   r
   Úis_root  s    zTreeNode.is_rootc                 C   s&   |   ¡ dkr|  ¡  |  ¡ ¡S d S d S rV   )r,   r4   Ú
next_childr/   r   r	   r	   r
   r3     s    zTreeNode.next_siblingc                 C   s&   |   ¡ dkr|  ¡  |  ¡ ¡S d S d S rV   )r,   r4   Ú
prev_childr/   r   r	   r	   r
   r:     s    zTreeNode.prev_siblingc                 C   s   | }|  ¡ d k	r|  ¡ }q|S r*   )r4   )r   Úrootr	   r	   r
   Úget_root  s    
zTreeNode.get_root)NNN)F)r   r   r   rI   r   r6   rS   r,   rX   r/   r[   r]   r4   r^   r1   ra   r3   r:   re   r	   r	   r	   r
   rJ   Ä   s    

rJ   c                   @   s†   e Zd ZdZd dd„Zd!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dd„ Zdd„ Zdd„ Zdd„ ZdS )#Ú
ParentNodez"Maintain sort order for TreeNodes.Nc                 C   s$   t j| ||||d� d | _i | _d S )N)rR   rB   r8   )rJ   r   Ú_child_keysÚ	_childrenrP   r	   r	   r
   r     s    zParentNode.__init__Fc                 C   s"   | j dks|dkr|  ¡ | _ | j S )z,Return a possibly ordered list of child keysNT)rg   Úload_child_keysrT   r	   r	   r
   Úget_child_keys!  s    
zParentNode.get_child_keysc                 C   s   t dƒ‚dS )zPProvide ParentNode with an ordered list of child keys (virtual
        function)r_   Nr`   r   r	   r	   r
   ri   '  s    zParentNode.load_child_keysc                 C   s   |   |¡}| ¡ S )z8Return the widget for a given key.  Create if necessary.)Úget_child_noder6   )r   rB   Zchildr	   r	   r
   Úget_child_widget,  s    
zParentNode.get_child_widgetc                 C   s,   || j ks|dkr"|  |¡| j |< | j | S )z<Return the child node for a given key.  Create if necessary.T)rh   Úload_child_node)r   rB   rU   r	   r	   r
   rk   2  s    zParentNode.get_child_nodec                 C   s   t dƒ‚dS )z6Load the child node for a given key (virtual function)r_   Nr`   rZ   r	   r	   r
   rm   8  s    zParentNode.load_child_nodec                 C   s   || j |< dS )z]Set the child node for a given key.  Useful for bottom-up, lazy
        population of a tree.N)rh   )r   rB   r   r	   r	   r
   Úset_child_node<  s    zParentNode.set_child_nodec                 C   s<   || j krtd| ƒ‚| j  |¡| j |< | j |  |¡ d S )Nz%s is already in use)rh   r   Úpopr[   )r   ZoldkeyZnewkeyr	   r	   r
   r\   A  s    
zParentNode.change_child_keyc              
   C   sL   z|   ¡  |¡W S  tk
rF   d}t|||  ¡ t|   ¡ ƒf ƒ‚Y nX d S )Nz7Can't find key %s in ParentNode %s
ParentNode items: %s)rj   ÚindexÚ
ValueErrorr   r/   r0   )r   rB   Zerrorstringr	   r	   r
   rW   G  s    
ÿzParentNode.get_child_indexc                 C   sH   |   |¡}|dkrdS |d7 }|  ¡ }|t|ƒk r@|  || ¡S dS dS )z=Return the next child node in index order from the given key.Nr   )rW   rj   Úlenrk   ©r   rB   rp   Ú
child_keysr	   r	   r
   rb   P  s    
zParentNode.next_childc                 C   sD   |   |¡}|dkrdS |  ¡ }|d8 }|dkr<|  || ¡S dS dS )zAReturn the previous child node in index order from the given key.Nr   r   )rW   rj   rk   rs   r	   r	   r
   rc   `  s    
zParentNode.prev_childc                 C   s   |   ¡ }|  |d ¡S )z+Return the first TreeNode in the directory.r   ©rj   rk   ©r   rt   r	   r	   r
   r   o  s    zParentNode.get_first_childc                 C   s   |   ¡ }|  |d ¡S )z*Return the last TreeNode in the directory.éÿÿÿÿru   rv   r	   r	   r
   rH   t  s    zParentNode.get_last_childc                 C   s   t |  ¡ ƒdkS )z!Does this node have any children?r   )rr   rj   r   r	   r	   r
   rG   y  s    zParentNode.has_children)NNN)F)F)r   r   r   rI   r   rj   ri   rl   rk   rm   rn   r\   rW   rb   rc   r   rH   rG   r	   r	   r	   r
   rf     s   


	rf   c                   @   s8   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ ZdS )Ú
TreeWalkerzTListWalker-compatible class for displaying TreeWidgets

    positions are TreeNodes.c                 C   s
   || _ dS )z,start_from: TreeNode with the initial focus.N)rE   )r   Ú
start_fromr	   r	   r
   r   ƒ  s    zTreeWalker.__init__c                 C   s   | j  ¡ }|| j fS r*   )rE   r6   )r   r   r	   r	   r
   Ú	get_focus‡  s    
zTreeWalker.get_focusc                 C   s   || _ |  ¡  d S r*   )rE   Z	_modified)r   rE   r	   r	   r
   Ú	set_focus‹  s    zTreeWalker.set_focusc                 C   s,   |  ¡ }| ¡ }|d krdS || ¡ fS d S ©N)NN)r6   r9   r+   ©r   ry   r   Útargetr	   r	   r
   Úget_next�  s
    zTreeWalker.get_nextc                 C   s,   |  ¡ }| ¡ }|d krdS || ¡ fS d S r|   )r6   r=   r+   r}   r	   r	   r
   Úget_prev—  s
    zTreeWalker.get_prevN)	r   r   r   rI   r   rz   r{   r   r€   r	   r	   r	   r
   rx   ~  s   rx   c                   @   s@   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dS )ÚTreeListBoxzPA ListBox with special handling for navigation and
    collapsing of TreeWidgetsc                 C   s   | j  ||¡}|  ||¡S r*   )Z_TreeListBox__superr?   Úunhandled_inputr@   r	   r	   r
   r?   ¤  s    zTreeListBox.keypressc                 C   sX   |dkr|   |¡ n@|dkr(|  |¡ n,|dkr<|  |¡ n|dkrP|  |¡ n|S dS )zHandle macro-navigation keysr!   r   ÚhomeÚendN)Úmove_focus_to_parentÚcollapse_focus_parentÚ
focus_homeÚ	focus_end)r   rA   Úinputr	   r	   r
   r‚   ¨  s    zTreeListBox.unhandled_inputc                 C   s>   | j  ¡ \}}|  |¡ | j  ¡ \}}||kr:|  |d¡ dS )zCollapse parent directory.r   N)Úbodyrz   r…   r?   )r   rA   r   ÚposZpwidgetZpposr	   r	   r
   r†   µ  s
    
z!TreeListBox.collapse_focus_parentc                 C   s�   | j  ¡ \}}| ¡ }|dkr"dS |  |¡\}}}|\}}	}
}}|\}}|D ].\}}}||8 }||krL|  |||¡  dS qL|  || ¡ ¡ dS )z(Move focus to parent of widget in focus.N)rŠ   rz   r4   Zcalculate_visibleÚchange_focus)r   rA   r   r‹   Ú	parentposZmiddleÚtopZbottomÚ
row_offsetZfocus_widgetZ	focus_posZ
focus_rowsZcursorZtrim_topZ
fill_aboveZrowsr	   r	   r
   r…   ¿  s    z TreeListBox.move_focus_to_parentc                 C   s&   | j  ¡ \}}| ¡ }|  ||¡ dS )zMove focus to very top.N)rŠ   rz   re   rŒ   )r   rA   r   r‹   Úrootnoder	   r	   r
   r‡   Ö  s    zTreeListBox.focus_homec           
      C   sL   |\}}| j  ¡ \}}| ¡ }| ¡ }| ¡ }| ¡ }	|  ||	|d ¡ dS )zMove focus to far bottom.r   N)rŠ   rz   re   r6   r;   r+   rŒ   )
r   rA   ZmaxrowZmaxcolr   r‹   r�   Z
rootwidgetZ
lastwidgetZlastnoder	   r	   r
   rˆ   Ý  s    zTreeListBox.focus_endN)
r   r   r   rI   r?   r‚   r†   r…   r‡   rˆ   r	   r	   r	   r
   r�      s   
r�   )Z
__future__r   r   r#   Z
urwid.wimpr   ÚRuntimeErrorr   Z
WidgetWrapr   ÚobjectrJ   rf   Z
ListWalkerrx   ZListBoxr�   r	   r	   r	   r
   Ú<module>   s    Ue"