U
    ºñdZ0U  ã                   @   s.  d dl mZmZ d dlmZmZmZmZmZ d dl	m
Z
 d dlmZ d dlmZ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 G dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZ G dd„ dedƒeƒZ!G dd„ deƒZ"dd„ Z#e$dk�r*e#ƒ  dS )é    )ÚdivisionÚprint_function)ÚTextÚ
WidgetWrapÚdelegate_to_widget_mixinÚBOXÚFLOW)ÚCompositeCanvas)Úconnect_signal)ÚColumnsÚOverlay)Úis_mouse_press)Úcalc_coords)Údisconnect_signal)Úpython3_repr)ÚWidgetDecoration)ÚACTIVATEc                   @   s4   e Zd ZdZddd„Zddd„Zdd	„ Zd
d„ ZdS )ÚSelectableIconTé   c                 C   s   | j  |¡ || _dS )aË  
        :param text: markup for this widget; see :class:`Text` for
                     description of text markup
        :param cursor_position: position the cursor will appear in the
                                text when this widget is in focus

        This is a text widget that is selectable.  A cursor
        displayed at a fixed location in the text when in focus.
        This widget has no special handling of keyboard or mouse input.
        N)Ú_SelectableIcon__superÚ__init__Ú_cursor_position)ÚselfÚtextZcursor_position© r   ú,/usr/lib/python3/dist-packages/urwid/wimp.pyr   &   s    zSelectableIcon.__init__Fc                 C   s*   | j  ||¡}|r&t|ƒ}|  |¡|_|S )a±  
        Render the text content of this widget with a cursor when
        in focus.

        >>> si = SelectableIcon(u"[!]")
        >>> si
        <SelectableIcon selectable flow widget '[!]'>
        >>> si.render((4,), focus=True).cursor
        (1, 0)
        >>> si = SelectableIcon("((*))", 2)
        >>> si.render((8,), focus=True).cursor
        (2, 0)
        >>> si.render((2,), focus=True).cursor
        (0, 1)
        )r   Úrenderr	   Úget_cursor_coordsZcursor)r   ÚsizeÚfocusÚcr   r   r   r   4   s
    zSelectableIcon.renderc                 C   sL   | j t| jƒkrdS |\}|  |¡}t| j|| j ƒ\}}||krDdS ||fS )zƒ
        Return the position of the cursor if visible.  This method
        is required for widgets that display a cursor.
        N)r   Úlenr   Zget_line_translationr   )r   r   ZmaxcolZtransÚxÚyr   r   r   r   K   s    
z SelectableIcon.get_cursor_coordsc                 C   s   |S )zn
        No keys are handled by this widget.  This method is
        required for selectable widgets.
        r   ©r   r   Úkeyr   r   r   Úkeypress[   s    zSelectableIcon.keypressN)r   )F)Ú__name__Ú
__module__Ú__qualname__Ú_selectabler   r   r   r&   r   r   r   r   r   $   s
   

r   c                   @   s   e Zd ZdS )ÚCheckBoxErrorN)r'   r(   r)   r   r   r   r   r+   b   s   r+   c                   @   sž   e Zd Zdd„ ZedƒedƒedƒdœZdZdd	gZd!dd„Zdd„ Z	dd„ Z
dd„ Zdd„ ZeeƒZd"dd„Zdd„ ZeeeƒZdd„ Zdd„ Zdd „ ZdS )#ÚCheckBoxc                 C   s
   t tgƒS ©N©Ú	frozensetr   ©r   r   r   r   Úsizingf   s    zCheckBox.sizingz[X]z[ ]z[#]©TFÚmixedé   ÚchangeÚ
postchangeFNc                 C   sL   | j  d¡ tdƒ| _|| _d| _|r4t| d||ƒ |  |¡ |  |¡ dS )a“  
        :param label: markup for check box label
        :param state: False, True or "mixed"
        :param has_mixed: True if "mixed" is a state to cycle through
        :param on_state_change: shorthand for connect_signal()
                                function call for a single callback
        :param user_data: user_data for on_state_change

        Signals supported: ``'change'``, ``"postchange"``

        Register signal handler with::

          urwid.connect_signal(check_box, 'change', callback, user_data)

        where callback is callback(check_box, new_state [,user_data])
        Unregister signal handlers with::

          urwid.disconnect_signal(check_box, 'change', callback, user_data)

        >>> CheckBox(u"Confirm")
        <CheckBox selectable flow widget 'Confirm' state=False>
        >>> CheckBox(u"Yogourt", "mixed", True)
        <CheckBox selectable flow widget 'Yogourt' state='mixed'>
        >>> cb = CheckBox(u"Extra onions", True)
        >>> cb
        <CheckBox selectable flow widget 'Extra onions' state=True>
        >>> cb.render((20,), focus=True).text # ... = b in Python 3
        [...'[X] Extra onions    ']
        NÚ r5   )	Ú_CheckBox__superr   r   Ú_labelÚ	has_mixedÚ_stater
   Ú	set_labelÚ	set_state)r   ÚlabelÚstater:   Úon_state_changeÚ	user_datar   r   r   r   t   s    

zCheckBox.__init__c                 C   s   | j  ¡ t| jƒg S r-   )r8   Ú_repr_wordsr   r>   r0   r   r   r   rB   ž   s    ÿzCheckBox._repr_wordsc                 C   s   t | j ¡ | jd�S )N)r?   )Údictr8   Ú_repr_attrsr?   r0   r   r   r   rD   ¢   s    
ÿzCheckBox._repr_attrsc                 C   s   | j  |¡ dS )au  
        Change the check box label.

        label -- markup for label.  See Text widget for description
        of text markup.

        >>> cb = CheckBox(u"foo")
        >>> cb
        <CheckBox selectable flow widget 'foo' state=False>
        >>> cb.set_label(('bright_attr', u"bar"))
        >>> cb
        <CheckBox selectable flow widget 'bar' state=False>
        N©r9   Zset_text©r   r>   r   r   r   r<   ¦   s    zCheckBox.set_labelc                 C   s   | j jS )a>  
        Return label text.

        >>> cb = CheckBox(u"Seriously")
        >>> print(cb.get_label())
        Seriously
        >>> print(cb.label)
        Seriously
        >>> cb.set_label([('bright_attr', u"flashy"), u" normal"])
        >>> print(cb.label)  #  only text is returned
        flashy normal
        ©r9   r   r0   r   r   r   Ú	get_label¸   s    zCheckBox.get_labelTc                 C   s–   | j |krdS || jkr0tdt| ƒt|ƒf ƒ‚| j }|rN|dk	rN|  d|¡ || _ td| j| j| f| jgƒ| _d| j_	|r’|dk	r’|  d|¡ dS )a×  
        Set the CheckBox state.

        state -- True, False or "mixed"
        do_callback -- False to suppress signal from this change

        >>> changes = []
        >>> def callback_a(cb, state, user_data):
        ...     changes.append("A %r %r" % (state, user_data))
        >>> def callback_b(cb, state):
        ...     changes.append("B %r" % state)
        >>> cb = CheckBox('test', False, False)
        >>> key1 = connect_signal(cb, 'change', callback_a, "user_a")
        >>> key2 = connect_signal(cb, 'change', callback_b)
        >>> cb.set_state(True) # both callbacks will be triggered
        >>> cb.state
        True
        >>> disconnect_signal(cb, 'change', callback_a, "user_a")
        >>> cb.state = False
        >>> cb.state
        False
        >>> cb.set_state(True)
        >>> cb.state
        True
        >>> cb.set_state(False, False) # don't send signal
        >>> changes
        ["A True 'user_a'", 'B True', 'B False', 'B True']
        Nz%s Invalid state: %sr5   Úfixedr   r6   )
r;   Ústatesr+   ÚreprÚ_emitr   Úreserve_columnsr9   Z_wZ	focus_col)r   r?   Údo_callbackZ	old_stater   r   r   r=   È   s$    

 ÿþzCheckBox.set_statec                 C   s   | j S )z!Return the state of the checkbox.)r;   r0   r   r   r   Ú	get_stateú   s    zCheckBox.get_statec                 C   s   | j | tkr|S |  ¡  dS )aŸ  
        Toggle state on 'activate' command.

        >>> assert CheckBox._command_map[' '] == 'activate'
        >>> assert CheckBox._command_map['enter'] == 'activate'
        >>> size = (10,)
        >>> cb = CheckBox('press me')
        >>> cb.state
        False
        >>> cb.keypress(size, ' ')
        >>> cb.state
        True
        >>> cb.keypress(size, ' ')
        >>> cb.state
        False
        N)Ú_command_mapr   Útoggle_stater$   r   r   r   r&   ÿ   s    zCheckBox.keypressc                 C   sV   | j dkr|  d¡ n<| j dkr>| jr2|  d¡ qR|  d¡ n| j dkrR|  d¡ dS )aM  
        Cycle to the next valid state.

        >>> cb = CheckBox("3-state", has_mixed=True)
        >>> cb.state
        False
        >>> cb.toggle_state()
        >>> cb.state
        True
        >>> cb.toggle_state()
        >>> cb.state
        'mixed'
        >>> cb.toggle_state()
        >>> cb.state
        False
        FTr3   N)r?   r=   r:   r0   r   r   r   rQ     s    


zCheckBox.toggle_statec                 C   s    |dkst |ƒsdS |  ¡  dS )a  
        Toggle state on button 1 press.

        >>> size = (20,)
        >>> cb = CheckBox("clickme")
        >>> cb.state
        False
        >>> cb.mouse_event(size, 'mouse press', 1, 2, 0, True)
        True
        >>> cb.state
        True
        r   FT)r   rQ   ©r   r   ZeventZbuttonr"   r#   r   r   r   r   Úmouse_event0  s    zCheckBox.mouse_event)FFNN)T)r'   r(   r)   r1   r   rJ   rM   Úsignalsr   rB   rD   r<   rH   Úpropertyr>   r=   rO   r?   r&   rQ   rS   r   r   r   r   r,   e   s,   ý    ÿ
*
2
r,   c                   @   sD   e Zd ZedƒedƒedƒdœZdZddd	„Zddd„Zdd„ ZdS )ÚRadioButtonz(X)z( )z(#)r2   r4   ú
first TrueNc                 C   s6   |dkr| }|| _ | j ||d||¡ | | ¡ dS )a  
        :param group: list for radio buttons in same group
        :param label: markup for radio button label
        :param state: False, True, "mixed" or "first True"
        :param on_state_change: shorthand for connect_signal()
                                function call for a single 'change' callback
        :param user_data: user_data for on_state_change

        This function will append the new radio button to group.
        "first True" will set to True if group is empty.

        Signals supported: ``'change'``, ``"postchange"``

        Register signal handler with::

          urwid.connect_signal(radio_button, 'change', callback, user_data)

        where callback is callback(radio_button, new_state [,user_data])
        Unregister signal handlers with::

          urwid.disconnect_signal(radio_button, 'change', callback, user_data)

        >>> bgroup = [] # button group
        >>> b1 = RadioButton(bgroup, u"Agree")
        >>> b2 = RadioButton(bgroup, u"Disagree")
        >>> len(bgroup)
        2
        >>> b1
        <RadioButton selectable flow widget 'Agree' state=True>
        >>> b2
        <RadioButton selectable flow widget 'Disagree' state=False>
        >>> b2.render((15,), focus=True).text # ... = b in Python 3
        [...'( ) Disagree   ']
        rW   FN)ÚgroupÚ_RadioButton__superr   Úappend)r   rX   r>   r?   r@   rA   r   r   r   r   J  s    $ÿzRadioButton.__init__Tc                 C   sR   | j |krdS | j ||¡ |dk	r(dS | jD ]}|| kr<q.|j r.| d¡ q.dS )aý  
        Set the RadioButton state.

        state -- True, False or "mixed"

        do_callback -- False to suppress signal from this change

        If state is True all other radio buttons in the same button
        group will be set to False.

        >>> bgroup = [] # button group
        >>> b1 = RadioButton(bgroup, u"Agree")
        >>> b2 = RadioButton(bgroup, u"Disagree")
        >>> b3 = RadioButton(bgroup, u"Unsure")
        >>> b1.state, b2.state, b3.state
        (True, False, False)
        >>> b2.set_state(True)
        >>> b1.state, b2.state, b3.state
        (False, True, False)
        >>> def relabel_button(radio_button, new_state):
        ...     radio_button.set_label(u"Think Harder!")
        >>> key = connect_signal(b3, 'change', relabel_button)
        >>> b3
        <RadioButton selectable flow widget 'Unsure' state=False>
        >>> b3.set_state(True) # this will trigger the callback
        >>> b3
        <RadioButton selectable flow widget 'Think Harder!' state=True>
        NTF)r;   rY   r=   rX   )r   r?   rN   Úcbr   r   r   r=   x  s    

 zRadioButton.set_statec                 C   s   |   d¡ dS )a†  
        Set state to True.

        >>> bgroup = [] # button group
        >>> b1 = RadioButton(bgroup, "Agree")
        >>> b2 = RadioButton(bgroup, "Disagree")
        >>> b1.state, b2.state
        (True, False)
        >>> b2.toggle_state()
        >>> b1.state, b2.state
        (False, True)
        >>> b2.toggle_state()
        >>> b1.state, b2.state
        (False, True)
        TN)r=   r0   r   r   r   rQ   ¦  s    zRadioButton.toggle_state)rW   NN)T)	r'   r(   r)   r   rJ   rM   r   r=   rQ   r   r   r   r   rV   C  s   ý    ÿ
.
.rV   c                   @   sd   e Zd Zdd„ ZedƒZedƒZdgZddd„Zd	d
„ Z	dd„ Z
dd„ ZeeƒZdd„ Zdd„ ZdS )ÚButtonc                 C   s
   t tgƒS r-   r.   r0   r   r   r   r1   º  s    zButton.sizingú<ú>ÚclickNc                 C   s\   t ddƒ| _tdd| jf| jdd| jfgdd�}| j |¡ |rNt| d||ƒ |  |¡ dS )aê  
        :param label: markup for button label
        :param on_press: shorthand for connect_signal()
                         function call for a single callback
        :param user_data: user_data for on_press

        Signals supported: ``'click'``

        Register signal handler with::

          urwid.connect_signal(button, 'click', callback, user_data)

        where callback is callback(button [,user_data])
        Unregister signal handlers with::

          urwid.disconnect_signal(button, 'click', callback, user_data)

        >>> Button(u"Ok")
        <Button selectable flow widget 'Ok'>
        >>> b = Button("Cancel")
        >>> b.render((15,), focus=True).text # ... = b in Python 3
        [...'< Cancel      >']
        r7   r   rI   r   )Zdividecharsr_   N)	r   r9   r   Úbutton_leftÚbutton_rightÚ_Button__superr   r
   r<   )r   r>   Zon_pressrA   Zcolsr   r   r   r   Â  s    

ýüzButton.__init__c                 C   s   | j  ¡ t| jƒg S r-   )rb   rB   r   r>   r0   r   r   r   rB   é  s    ÿzButton._repr_wordsc                 C   s   | j  |¡ dS )zÖ
        Change the button label.

        label -- markup for button label

        >>> b = Button("Ok")
        >>> b.set_label(u"Yup yup")
        >>> b
        <Button selectable flow widget 'Yup yup'>
        NrE   rF   r   r   r   r<   î  s    zButton.set_labelc                 C   s   | j jS )z•
        Return label text.

        >>> b = Button(u"Ok")
        >>> print(b.get_label())
        Ok
        >>> print(b.label)
        Ok
        rG   r0   r   r   r   rH   û  s    
zButton.get_labelc                 C   s    | j | tkr|S |  d¡ dS )aD  
        Send 'click' signal on 'activate' command.

        >>> assert Button._command_map[' '] == 'activate'
        >>> assert Button._command_map['enter'] == 'activate'
        >>> size = (15,)
        >>> b = Button(u"Cancel")
        >>> clicked_buttons = []
        >>> def handle_click(button):
        ...     clicked_buttons.append(button.label)
        >>> key = connect_signal(b, 'click', handle_click)
        >>> b.keypress(size, 'enter')
        >>> b.keypress(size, ' ')
        >>> clicked_buttons # ... = u in Python 2
        [...'Cancel', ...'Cancel']
        r_   N)rP   r   rL   r$   r   r   r   r&     s    zButton.keypressc                 C   s"   |dkst |ƒsdS |  d¡ dS )a  
        Send 'click' signal on button 1 press.

        >>> size = (15,)
        >>> b = Button(u"Ok")
        >>> clicked_buttons = []
        >>> def handle_click(button):
        ...     clicked_buttons.append(button.label)
        >>> key = connect_signal(b, 'click', handle_click)
        >>> b.mouse_event(size, 'mouse press', 1, 4, 0, True)
        True
        >>> b.mouse_event(size, 'mouse press', 2, 4, 0, True) # ignored
        False
        >>> clicked_buttons # ... = u in Python 2
        [...'Ok']
        r   Fr_   T)r   rL   rR   r   r   r   rS     s    
zButton.mouse_event)NN)r'   r(   r)   r1   r   r`   ra   rT   r   rB   r<   rH   rU   r>   r&   rS   r   r   r   r   r\   ¹  s   
'r\   c                   @   s>   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ Zddd„ZdS )ÚPopUpLauncherc                 C   s   | j  |¡ d | _d S r-   )Ú_PopUpLauncher__superr   Ú_pop_up_widget©r   Zoriginal_widgetr   r   r   r   8  s    zPopUpLauncher.__init__c                 C   s   t dƒ‚dS )z¯
        Subclass must override this method and return a widget
        to be used for the pop-up.  This method is called once each time
        the pop-up is opened.
        ú"Subclass must override this methodN©ÚNotImplementedErrorr0   r   r   r   Úcreate_pop_up<  s    zPopUpLauncher.create_pop_upc                 C   s   t dƒ‚dS )zÚ
        Subclass must override this method and have it return a dict, eg:

        {'left':0, 'top':1, 'overlay_width':30, 'overlay_height':4}

        This method is called each time this widget is rendered.
        rg   Nrh   r0   r   r   r   Úget_pop_up_parametersD  s    z#PopUpLauncher.get_pop_up_parametersc                 C   s   |   ¡ | _|  ¡  d S r-   )rj   re   Ú_invalidater0   r   r   r   Úopen_pop_upN  s    
zPopUpLauncher.open_pop_upc                 C   s   d | _ |  ¡  d S r-   )re   rl   r0   r   r   r   Úclose_pop_upR  s    zPopUpLauncher.close_pop_upFc                 C   s4   | j  ||¡}| jr0t|ƒ}|j| jf|  ¡ Ž |S r-   )rd   r   re   r	   Z
set_pop_uprk   )r   r   r   Úcanvr   r   r   r   V  s
    zPopUpLauncher.renderN)F)	r'   r(   r)   r   rj   rk   rm   rn   r   r   r   r   r   rc   6  s   
rc   Ú_original_widgetc                   @   sf   e Zd ZeegƒZ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d„ZdS )ÚPopUpTargetTc                 C   s   | j  |¡ d | _| j| _d S r-   )Z_PopUpTarget__superr   Ú_pop_uprp   Ú_current_widgetrf   r   r   r   r   d  s    zPopUpTarget.__init__c           
      C   s�   | j j||d�}|| _| ¡ }|r~|\}}\}}}	| j|krb|| _t|| j d|f|d|f|	ƒ| _qŒ| j d|f|d|f|	¡ nd | _| j | _d S )N©r   z
fixed leftz	fixed top)rp   r   Z_cache_original_canvasZ
get_pop_uprr   r   rs   Zset_overlay_parameters)
r   r   r   ro   Zpop_upÚleftÚtopÚwZoverlay_widthZoverlay_heightr   r   r   Ú_update_overlayi  s2    ÿ  
  þ  þzPopUpTarget._update_overlayFc                 C   s   |   ||¡ | jj||d�S )Nrt   )rx   rs   r   ©r   r   r   r   r   r   r   }  s    zPopUpTarget.renderc                 C   s   |   |d¡ | j |¡S ©NT)rx   rs   r   ©r   r   r   r   r   r   €  s    zPopUpTarget.get_cursor_coordsc                 C   s   |   |d¡ | j |¡S rz   )rx   rs   Úget_pref_colr{   r   r   r   r|   ƒ  s    zPopUpTarget.get_pref_colc                 C   s   |   |d¡ | j ||¡S rz   )rx   rs   r&   r$   r   r   r   r&   †  s    zPopUpTarget.keypressc                 C   s   |   |d¡ | j |||¡S rz   )rx   rs   Úmove_cursor_to_coords)r   r   r"   r#   r   r   r   r}   ‰  s    z!PopUpTarget.move_cursor_to_coordsc                 C   s"   |   ||¡ | j ||||||¡S r-   )rx   rs   rS   rR   r   r   r   rS   Œ  s    zPopUpTarget.mouse_eventNc                 C   s   |   ||¡ | j |¡S r-   )rx   rs   Úpackry   r   r   r   r~   �  s    zPopUpTarget.pack)F)NF)r'   r(   r)   Úsetr   Z_sizingr*   r   rx   r   r   r|   r&   r}   rS   r~   r   r   r   r   rq   ^  s   

rq   c                  C   s   dd l } |  ¡  d S )Nr   )ÚdoctestZtestmod)r€   r   r   r   Ú_test˜  s    r�   Ú__main__N)%Z
__future__r   r   Zurwid.widgetr   r   r   r   r   Zurwid.canvasr	   Zurwid.signalsr
   Zurwid.containerr   r   Z
urwid.utilr   Zurwid.text_layoutr   r   Zurwid.split_reprr   Zurwid.decorationr   Zurwid.command_mapr   r   Ú	Exceptionr+   r,   rV   r\   rc   rq   r�   r'   r   r   r   r   Ú<module>   s.   > _v}ÿ(:
