o
     o_7=  ã                   @   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   ó   zTreeWidget.selectablec                 C   sL   |   ¡ }| jstjdd| j| jg| j f|gdd}|  ¡ }tj|d|dS )NÚfixedé   )Údividechars)Úrelativeéd   )ÚwidthÚleft)	Úget_inner_widgetr   ÚurwidÚColumnsÚunexpanded_iconÚexpanded_iconr   Úget_indent_colsÚ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   Ú_wÚbase_widgetÚ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 u r
|  ¡ | _ | j S r1   )r   Úload_inner_widgetr   r	   r	   r
   r%   Q   s   

zTreeWidget.get_inner_widgetc                 C   s   t  |  ¡ ¡S r1   )r&   ÚTextÚget_display_textr   r	   r	   r
   r4   V   s   zTreeWidget.load_inner_widgetc                 C   ó   | j S r1   )r   r   r	   r	   r
   r2   Y   ó   zTreeWidget.get_nodec                 C   s    |   ¡  ¡ d t|   ¡  ¡ ƒ S )Nz: )r2   Úget_keyÚstrÚ	get_valuer   r	   r	   r
   r6   \   s   ÿzTreeWidget.get_display_textc                 C   sˆ   |   ¡ }|dur
|S |  ¡ }| ¡ }| ¡ }|du r:|dkr:| ¡ }| ¡ }|d8 }|| ¡ ks2J ‚|du r:|dks|du r@dS | ¡ S )z5Return the next TreeWidget depth first from this one.Nr   r   )Úfirst_childr2   Únext_siblingr3   Ú
get_parentÚ
get_widget)r   Ú
firstchildÚthisnodeÚnextnodeÚdepthr	   r	   r
   Únext_inorder`   s   ûzTreeWidget.next_inorderc                 C   sj   | j }| ¡ }|dur| ¡ }| ¡ }|du r|S |S | ¡ }|du r)|dkr)dS |du r1| ¡ }| ¡ S )z9Return the previous TreeWidget depth first from this one.Nr   )r   Úprev_siblingr?   Ú
last_childr3   r>   )r   rA   ÚprevnodeÚ
prevwidgetÚ	lastchildrC   r	   r	   r
   Úprev_inorderw   s   zTreeWidget.prev_inorderc                 C   sZ   | j r|S |dv rd| _|  ¡  dS |dkrd| _|  ¡  dS | j ¡ r+| j ||¡S |S )z2Handle expand & collapse requests (non-leaf nodes))r   ÚrightTr   FN)r   r   r0   r-   r   r   Úkeypress©r   ÚsizeÚkeyr	   r	   r
   rL      s   
zTreeWidget.keypressc                 C   sH   | j s|dks|dkrdS |dkr"||  ¡ kr"| j | _|  ¡  dS dS )Nzmouse pressr   Fr   T)r   r*   r   r0   )r   rN   ÚeventÚbuttonÚcolÚrowÚfocusr	   r	   r
   Úmouse_event   s   
zTreeWidget.mouse_eventc                 C   s0   | j s| jsdS | j ¡ r| j ¡ }| ¡ S dS )zReturn first child if expanded.N)r   r   r   Úhas_childrenr   r?   )r   Ú	firstnoder	   r	   r
   r<   ¨   s   

zTreeWidget.first_childc                 C   sF   | j s| jsdS | j ¡ r| j ¡  ¡ }ndS | ¡ }|du r!|S |S )zReturn last child if expanded.N)r   r   r   rV   Úget_last_childr?   rF   )r   rI   Úlastdescendantr	   r	   r
   rF   ³   s   
zTreeWidget.last_childN)r   r   r   Ú__doc__r,   r   r(   r)   r   r   r   r0   r*   r%   r4   r2   r6   rD   rJ   rL   rU   r<   rF   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 r1   )Ú_keyÚ_parentÚ_valueÚ_depthÚ_widget©r   ÚvalueÚparentrO   rC   r	   r	   r
   r   Í   s
   
zTreeNode.__init__Fc                 C   ó"   | j du s	|dkr|  ¡ | _ | j S )z! Return the widget for this node.NT)r`   Úload_widget©r   Úreloadr	   r	   r
   r?   Ô   ó   
zTreeNode.get_widgetc                 C   s   t | ƒS r1   )r   r   r	   r	   r
   re   Ú   s   zTreeNode.load_widgetc                 C   s@   | j d u r| jd u rd| _ | j S | j d u r| j ¡ d | _ | j S )Nr   r   )r_   r]   r3   r   r	   r	   r
   r3   Ý   s   
þzTreeNode.get_depthc                 C   s*   |   ¡ dkrd S |  ¡ }|  ¡ }| |¡S ©Nr   )r3   r9   r>   Úget_child_index)r   rO   rc   r	   r	   r
   Ú	get_indexä   s
   
zTreeNode.get_indexc                 C   r7   r1   ©r\   r   r	   r	   r
   r9   ì   r8   zTreeNode.get_keyc                 C   s
   || _ d S r1   rl   ©r   rO   r	   r	   r
   Úset_keyï   ó   
zTreeNode.set_keyc                 C   s   |   ¡  | j|¡ d S r1   )r>   Úchange_child_keyr\   rm   r	   r	   r
   Ú
change_keyò   s   zTreeNode.change_keyc                 C   s&   | j d kr|  ¡ dkr|  ¡ | _ | j S ri   )r]   r3   Úload_parentr   r	   r	   r
   r>   õ   s   
zTreeNode.get_parentc                 C   ó   t dƒ‚)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 subclass©r   r   r	   r	   r
   rr   ú   r   zTreeNode.load_parentc                 C   r7   r1   )r^   r   r	   r	   r
   r;      r8   zTreeNode.get_valuec                 C   s   |   ¡ dkS ri   )r3   r   r	   r	   r
   Úis_root  s   zTreeNode.is_rootc                 C   ó"   |   ¡ dkr|  ¡  |  ¡ ¡S d S ri   )r3   r>   Ú
next_childr9   r   r	   r	   r
   r=     ó   zTreeNode.next_siblingc                 C   rw   ri   )r3   r>   Ú
prev_childr9   r   r	   r	   r
   rE     ry   zTreeNode.prev_siblingc                 C   s(   | }|  ¡ d ur|  ¡ }|  ¡ d us|S r1   )r>   )r   Úrootr	   r	   r
   Úget_root  s
   ÿzTreeNode.get_root©NNN©F)r   r   r   rZ   r   r?   re   r3   rk   r9   rn   rq   r>   rr   r;   rv   r=   rE   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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)rc   rO   rC   )r[   r   Ú_child_keysÚ	_childrenra   r	   r	   r
   r     s   
zParentNode.__init__Fc                 C   rd   )z,Return a possibly ordered list of child keysNT)r€   Úload_child_keysrf   r	   r	   r
   Úget_child_keys!  rh   zParentNode.get_child_keysc                 C   rs   )zPProvide ParentNode with an ordered list of child keys (virtual
        function)rt   ru   r   r	   r	   r
   r‚   '  s   zParentNode.load_child_keysc                 C   s   |   |¡}| ¡ S )z8Return the widget for a given key.  Create if necessary.)Úget_child_noder?   )r   rO   Úchildr	   r	   r
   Úget_child_widget,  s   
zParentNode.get_child_widgetc                 C   s,   || j vs	|dkr|  |¡| j |< | j | S )z<Return the child node for a given key.  Create if necessary.T)r   Úload_child_node)r   rO   rg   r	   r	   r
   r„   2  s   
zParentNode.get_child_nodec                 C   rs   )z6Load the child node for a given key (virtual function)rt   ru   rm   r	   r	   r
   r‡   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)r   )r   rO   r   r	   r	   r
   Úset_child_node<  s   zParentNode.set_child_nodec                 C   s<   || j v rtd| ƒ‚| j  |¡| j |< | j |  |¡ d S )Nz%s is already in use)r   r   Úpoprn   )r   ÚoldkeyÚnewkeyr	   r	   r
   rp   A  s   
zParentNode.change_child_keyc              
   C   sB   z|   ¡  |¡W S  ty    d}t|||  ¡ t|   ¡ ƒf ƒ‚w )Nz7Can't find key %s in ParentNode %s
ParentNode items: %s)rƒ   ÚindexÚ
ValueErrorr   r9   r:   )r   rO   Úerrorstringr	   r	   r
   rj   G  s   
ÿýzParentNode.get_child_indexc                 C   sD   |   |¡}|du rdS |d7 }|  ¡ }|t|ƒk r |  || ¡S dS )z=Return the next child node in index order from the given key.Nr   )rj   rƒ   Úlenr„   ©r   rO   rŒ   Ú
child_keysr	   r	   r
   rx   P  s   
zParentNode.next_childc                 C   s@   |   |¡}|du rdS |  ¡ }|d8 }|dkr|  || ¡S dS )zAReturn the previous child node in index order from the given key.Nr   r   )rj   rƒ   r„   r   r	   r	   r
   rz   `  s   
zParentNode.prev_childc                 C   ó   |   ¡ }|  |d ¡S )z+Return the first TreeNode in the directory.r   ©rƒ   r„   ©r   r‘   r	   r	   r
   r   o  ó   zParentNode.get_first_childc                 C   r’   )z*Return the last TreeNode in the directory.éÿÿÿÿr“   r”   r	   r	   r
   rX   t  r•   zParentNode.get_last_childc                 C   s   t |  ¡ ƒdkS )z!Does this node have any children?r   )r   rƒ   r   r	   r	   r
   rV   y  s   zParentNode.has_childrenr}   r~   )r   r   r   rZ   r   rƒ   r‚   r†   r„   r‡   rˆ   rp   rj   rx   rz   r   rX   rV   r	   r	   r	   r
   r     s     


	r   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)rT   )r   Ú
start_fromr	   r	   r
   r   ƒ  s   
zTreeWalker.__init__c                 C   s   | j  ¡ }|| j fS r1   )rT   r?   )r   r   r	   r	   r
   Ú	get_focus‡  s   

zTreeWalker.get_focusc                 C   s   || _ |  ¡  d S r1   )rT   Ú	_modified)r   rT   r	   r	   r
   Ú	set_focus‹  s   zTreeWalker.set_focusc                 C   ó(   |  ¡ }| ¡ }|d u rdS || ¡ fS ©N)NN)r?   rD   r2   ©r   r˜   r   Útargetr	   r	   r
   Úget_next  ó
   zTreeWalker.get_nextc                 C   rœ   r   )r?   rJ   r2   rž   r	   r	   r
   Úget_prev—  r¡   zTreeWalker.get_prevN)	r   r   r   rZ   r   r™   r›   r    r¢   r	   r	   r	   r
   r—   ~  s    r—   c                   @   sP   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d„ Z
dd„ ZdS )ÚTreeListBoxzPA ListBox with special handling for navigation and
    collapsing of TreeWidgetsc                 C   s   | j  ||¡}|  ||¡S r1   )Ú_TreeListBox__superrL   Úunhandled_inputrM   r	   r	   r
   rL   ¤  s   zTreeListBox.keypressc                 C   s0   |dkr|   |¡ dS |dkr|  |¡ dS |S )zHandle macro-navigation keysr$   r   N)Úmove_focus_to_parentÚcollapse_focus_parent)r   rN   Úinputr	   r	   r
   r¥   ¨  s
   zTreeListBox.unhandled_inputc                 C   sB   | j  ¡ \}}|  |¡ | j  ¡ \}}||kr|  |d¡ dS dS )zCollapse parent directory.r   N)Úbodyr™   r¦   rL   )r   rN   r   ÚposÚpwidgetÚpposr	   r	   r
   r§   ±  s   
ÿz!TreeListBox.collapse_focus_parentc                 C   s   | j  ¡ \}}| ¡ }|du rdS |  |¡\}}}|\}}	}
}}|\}}|D ]\}}}||8 }||kr=|  |||¡  dS q&|  || ¡ ¡ dS )z(Move focus to parent of widget in focus.N)r©   r™   r>   Úcalculate_visibleÚchange_focus)r   rN   r   rª   Ú	parentposÚmiddleÚtopÚbottomÚ
row_offsetÚfocus_widgetÚ	focus_posÚ
focus_rowsÚcursorÚtrim_topÚ
fill_aboveÚrowsr	   r	   r
   r¦   »  s   þz TreeListBox.move_focus_to_parentc                 C   ó
   |   |¡S r1   )Ú
focus_home©r   rN   r	   r	   r
   Ú_keypress_max_leftÒ  ro   zTreeListBox._keypress_max_leftc                 C   r»   r1   )Ú	focus_endr½   r	   r	   r
   Ú_keypress_max_rightÕ  ro   zTreeListBox._keypress_max_rightc                 C   s&   | j  ¡ \}}| ¡ }|  ||¡ dS )zMove focus to very top.N)r©   r™   r|   r®   )r   rN   r   rª   Úrootnoder	   r	   r
   r¼   Ø  s   zTreeListBox.focus_homec           
      C   sT   |\}}| j  ¡ \}}| ¡ }| ¡ }| ¡ }|r(| ¡ }	|  ||	|d ¡ dS dS )zMove focus to far bottom.r   N)r©   r™   r|   r?   rF   r2   r®   )
r   rN   ÚmaxrowÚmaxcolr   rª   rÁ   Ú
rootwidgetÚ
lastwidgetÚlastnoder	   r	   r
   r¿   ß  s   ýzTreeListBox.focus_endN)r   r   r   rZ   rL   r¥   r§   r¦   r¾   rÀ   r¼   r¿   r	   r	   r	   r
   r£      s    	
r£   )Ú
__future__r   r   r&   Ú
urwid.wimpr   ÚRuntimeErrorr   Ú
WidgetWrapr   Úobjectr[   r   Ú
ListWalkerr—   ÚListBoxr£   r	   r	   r	   r
   Ú<module>   s   	 Ue"