o
    � o_×U  ã                   @   s0  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 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                   @   s8   e Zd ZdZdZddd„Zddd„Zdd	„ Zd
d„ ZdS )ÚSelectableIconFTr   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ÚtextÚcursor_position© r   ú,/usr/lib/python3/dist-packages/urwid/wimp.pyr   '   s   
zSelectableIcon.__init__c                 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
        (0, 0)
        >>> si = SelectableIcon("((*))", 2)
        >>> si.render((8,), focus=True).cursor
        (2, 0)
        >>> si.render((2,), focus=True).cursor
        (0, 1)
        )r   Úrenderr	   Úget_cursor_coordsÚcursor)r   ÚsizeÚfocusÚcr   r   r   r   5   s
   zSelectableIcon.renderc                 C   sL   | j t| jƒkr
dS |\}|  |¡}t| j|| j ƒ\}}||kr"d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   Úget_line_translationr   )r   r   ÚmaxcolÚtransÚxÚyr   r   r   r   L   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__Úignore_focusÚ_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   r1   c   s    r1   c                   @   s¨   e Zd Zdd„ Zeddƒeddƒed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   ó
   t tgƒS ©N©Ú	frozensetr   ©r   r   r   r   Úsizingg   ó   
zCheckBox.sizingz[X]é   z[ ]z[#]©TFÚmixedé   ÚchangeÚ
postchangeFNc                 C   sd   | j  d¡ tdƒ| _|| _d| _|rtd| dƒ| jd< |r&t| 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Ú z[%s]r:   Tr>   )Ú_CheckBox__superr   r   Ú_labelÚ	has_mixedÚ_stater   Ústatesr
   Ú	set_labelÚ	set_state)r   ÚlabelÚstaterC   Úon_state_changeÚ	user_dataÚchecked_symbolr   r   r   r   u   s   

zCheckBox.__init__c                 C   ó   | j  ¡ t| jƒg S r4   )rA   Ú_repr_wordsr   rH   r7   r   r   r   rN   ¡   s   ÿzCheckBox._repr_wordsc                 C   s   t | j ¡ | jd�S )N)rI   )ÚdictrA   Ú_repr_attrsrI   r7   r   r   r   rP   ¥   s   
ÿzCheckBox._repr_attrsc                 C   ó   | 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©rB   Úset_text©r   rH   r   r   r   rF   ©   s   zCheckBox.set_labelc                 C   ó   | 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
        ©rB   r   r7   r   r   r   Ú	get_label»   s   zCheckBox.get_labelTc                 C   sž   | j |krdS || jvrtdt| ƒt|ƒf ƒ‚| j }|r'|dur'|  d|¡ || _ td| j| j| f| jgƒ| _d| j_	|rK|durM|  d|¡ dS dS 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: %sr>   Úfixedr   r?   )
rD   rE   r1   ÚreprÚ_emitr   Úreserve_columnsrB   Ú_wÚ	focus_col)r   rI   Údo_callbackÚ	old_stater   r   r   rG   Ë   s$   

ÿþÿzCheckBox.set_statec                 C   s   | j S )z!Return the state of the checkbox.)rD   r7   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   s`   | j dkr|  d¡ dS | j dkr"| jr|  d¡ dS |  d¡ dS | j dkr.|  d¡ dS 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
        FTr<   N)rI   rG   rC   r7   r   r   r   rb     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   rb   ©r   r   ÚeventÚbuttonr&   r'   r    r   r   r   Úmouse_event3  s   zCheckBox.mouse_event)FFNNN©T)r,   r-   r.   r8   r   rE   r[   Úsignalsr   rN   rP   rF   rW   ÚpropertyrH   rG   r`   rI   r*   rb   rf   r   r   r   r   r2   f   s,    ý
ÿ,
2
r2   c                   @   sN   e Zd ZeddƒeddƒeddƒdœZdZ		dd	d
„Zddd„Zdd„ ZdS )ÚRadioButtonz(X)r:   z( )z(#)r;   r=   ú
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   ']
        rk   FN)ÚgroupÚ_RadioButton__superr   Úappend)r   rl   rH   rI   rJ   rK   r   r   r   r   M  s   $ÿzRadioButton.__init__Tc                 C   sR   | j |krdS | j ||¡ |durdS | jD ]}|| u 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)rD   rm   rG   rl   )r   rI   r^   Úcbr   r   r   rG   {  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)rG   r7   r   r   r   rb   ©  s   zRadioButton.toggle_state)rk   NNrg   )	r,   r-   r.   r   rE   r[   r   rG   rb   r   r   r   r   rj   F  s    ý
ÿ
..rj   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   r3   r4   r5   r7   r   r   r   r8   ½  r9   zButton.sizingú<ú>ÚclickNc                 C   s\   t ddƒ| _tdd| jf| jdd| jfgdd�}| j |¡ |r't| 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      >']
        r@   r   rX   r:   )Údividecharsrs   N)	r   rB   r   Úbutton_leftÚbutton_rightÚ_Button__superr   r
   rF   )r   rH   Úon_pressrK   Úcolsr   r   r   r   Å  s   

ýüzButton.__init__c                 C   rM   r4   )rw   rN   r   rH   r7   r   r   r   rN   ì  s   ÿzButton._repr_wordsc                 C   rQ   )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'>
        NrR   rT   r   r   r   rF   ñ  s   zButton.set_labelc                 C   rU   )z•
        Return label text.

        >>> b = Button(u"Ok")
        >>> print(b.get_label())
        Ok
        >>> print(b.label)
        Ok
        rV   r7   r   r   r   rW   þ  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']
        rs   N)ra   r   rZ   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:   Frs   T)r   rZ   rc   r   r   r   rf   !  s   
zButton.mouse_event)NN)r,   r-   r.   r8   r   ru   rv   rh   r   rN   rF   rW   ri   rH   r*   rf   r   r   r   r   rp   ¼  s    
'rp   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 r4   )Ú_PopUpLauncher__superr   Ú_pop_up_widget©r   Úoriginal_widgetr   r   r   r   ;  s   
zPopUpLauncher.__init__c                 C   ó   t dƒ‚)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 method©ÚNotImplementedErrorr7   r   r   r   Úcreate_pop_up?  s   zPopUpLauncher.create_pop_upc                 C   r   )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.
        r€   r�   r7   r   r   r   Úget_pop_up_parametersG  s   z#PopUpLauncher.get_pop_up_parametersc                 C   s   |   ¡ | _|  ¡  d S r4   )rƒ   r|   Ú_invalidater7   r   r   r   Úopen_pop_upQ  s   
zPopUpLauncher.open_pop_upc                 C   s   d | _ |  ¡  d S r4   )r|   r…   r7   r   r   r   Úclose_pop_upU  s   zPopUpLauncher.close_pop_upFc                 C   s8   | j  ||¡}| jrt|ƒ}|j| jfi |  ¡ ¤Ž |S r4   )r{   r   r|   r	   Ú
set_pop_upr„   )r   r   r    Úcanvr   r   r   r   Y  s
   zPopUpLauncher.renderNr+   )	r,   r-   r.   r   rƒ   r„   r†   r‡   r   r   r   r   r   rz   9  s    
rz   Ú_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 r4   )Ú_PopUpTarget__superr   Ú_pop_uprŠ   Ú_current_widgetr}   r   r   r   r   g  s   zPopUpTarget.__init__c           
      C   s”   | j j||d�}|| _| ¡ }|rA|\}}\}}}	| j|kr2|| _t|| j d|f|d|f|	ƒ| _d S | j d|f|d|f|	¡ d S d | _| j | _d S )N©r    z
fixed leftz	fixed top)rŠ   r   Ú_cache_original_canvasÚ
get_pop_upr�   r   rŽ   Úset_overlay_parameters)
r   r   r    r‰   Úpop_upÚleftÚtopÚwÚoverlay_widthÚoverlay_heightr   r   r   Ú_update_overlayl  s&   ÿ

þþzPopUpTarget._update_overlayFc                 C   s   |   ||¡ | jj||d�S )Nr�   )r™   rŽ   r   ©r   r   r    r   r   r   r   €  ó   zPopUpTarget.renderc                 C   ó   |   |d¡ | j |¡S ©NT)r™   rŽ   r   ©r   r   r   r   r   r   ƒ  ó   zPopUpTarget.get_cursor_coordsc                 C   rœ   r�   )r™   rŽ   Úget_pref_colrž   r   r   r   r    †  rŸ   zPopUpTarget.get_pref_colc                 C   s   |   |d¡ | j ||¡S r�   )r™   rŽ   r*   r(   r   r   r   r*   ‰  s   zPopUpTarget.keypressc                 C   s   |   |d¡ | j |||¡S r�   )r™   rŽ   Úmove_cursor_to_coords)r   r   r&   r'   r   r   r   r¡   Œ  r›   z!PopUpTarget.move_cursor_to_coordsc                 C   s"   |   ||¡ | j ||||||¡S r4   )r™   rŽ   rf   rc   r   r   r   rf   �  s   zPopUpTarget.mouse_eventNc                 C   s   |   ||¡ | j |¡S r4   )r™   rŽ   Úpackrš   r   r   r   r¢   ’  rŸ   zPopUpTarget.packr+   )NF)r,   r-   r.   Úsetr   Ú_sizingr0   r   r™   r   r   r    r*   r¡   rf   r¢   r   r   r   r   r‹   a  s    

r‹   c                  C   s   dd l } |  ¡  d S )Nr   )ÚdoctestÚtestmod)r¥   r   r   r   Ú_test›  s   r§   Ú__main__N)%Ú
__future__r   r   Úurwid.widgetr   r   r   r   r   Úurwid.canvasr	   Úurwid.signalsr
   Úurwid.containerr   r   Ú
urwid.utilr   Úurwid.text_layoutr   r   Úurwid.split_reprr   Úurwid.decorationr   Úurwid.command_mapr   r   Ú	Exceptionr1   r2   rj   rp   rz   r‹   r§   r,   r   r   r   r   Ú<module>   s2   ? av}ÿ(:
ÿ