U
    Pe4w                     @   s4  d Z d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 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 ddlmZmZmZmZmZm Z m!Z!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Z)G dd deZ*dS )a  
TabbedPanel
===========

.. image:: images/tabbed_panel.jpg
    :align: right

.. versionadded:: 1.3.0


The `TabbedPanel` widget manages different widgets in tabs, with a header area
for the actual tab buttons and a content area for showing the current tab
content.

The :class:`TabbedPanel` provides one default tab.

Simple example
--------------

.. include:: ../../examples/widgets/tabbedpanel.py
    :literal:

.. note::

    A new class :class:`TabbedPanelItem` has been introduced in 1.5.0 for
    convenience. So now one can simply add a :class:`TabbedPanelItem` to a
    :class:`TabbedPanel` and `content` to the :class:`TabbedPanelItem`
    as in the example provided above.

Customize the Tabbed Panel
--------------------------

You can choose the position in which the tabs are displayed::

    tab_pos = 'top_mid'

An individual tab is called a TabbedPanelHeader. It is a special button
containing a `content` property. You add the TabbedPanelHeader first, and set
its `content` property separately::

    tp = TabbedPanel()
    th = TabbedPanelHeader(text='Tab2')
    tp.add_widget(th)

An individual tab, represented by a TabbedPanelHeader, needs its content set.
This content can be any widget. It could be a layout with a deep
hierarchy of widgets, or it could be an individual widget, such as a label or a
button::

    th.content = your_content_instance

There is one "shared" main content area active at any given time, for all
the tabs. Your app is responsible for adding the content of individual tabs
and for managing them, but it's not responsible for content switching. The
tabbed panel handles switching of the main content object as per user action.

There is a default tab added when the tabbed panel is instantiated.
Tabs that you add individually as above, are added in addition to the default
tab. Thus, depending on your needs and design, you will want to customize the
default tab::

    tp.default_tab_text = 'Something Specific To Your Use'


The default tab machinery requires special consideration and management.
Accordingly, an `on_default_tab` event is provided for associating a callback::

    tp.bind(default_tab = my_default_tab_callback)

It's important to note that by default, :attr:`default_tab_cls` is of type
:class:`TabbedPanelHeader` and thus has the same properties as other tabs.

Since 1.5.0, it is now possible to disable the creation of the
:attr:`default_tab` by setting :attr:`do_default_tab` to False.

Tabs and content can be removed in several ways::

    tp.remove_widget(widget/tabbed_panel_header)
    or
    tp.clear_widgets() # to clear all the widgets in the content area
    or
    tp.clear_tabs() # to remove the TabbedPanelHeaders

To access the children of the tabbed panel, use content.children::

    tp.content.children

To access the list of tabs::

    tp.tab_list

To change the appearance of the main tabbed panel content::

    background_color = (1, 0, 0, .5) #50% translucent red
    border = [0, 0, 0, 0]
    background_image = 'path/to/background/image'

To change the background of a individual tab, use these two properties::

    tab_header_instance.background_normal = 'path/to/tab_head/img'
    tab_header_instance.background_down = 'path/to/tab_head/img_pressed'

A TabbedPanelStrip contains the individual tab headers. To change the
appearance of this tab strip, override the canvas of TabbedPanelStrip.
For example, in the kv language:

.. code-block:: kv

    <TabbedPanelStrip>
        canvas:
            Color:
                rgba: (0, 1, 0, 1) # green
            Rectangle:
                size: self.size
                pos: self.pos

By default the tabbed panel strip takes its background image and color from the
tabbed panel's background_image and background_color.

)StripLayoutTabbedPanelTabbedPanelContentTabbedPanelHeaderTabbedPanelItemTabbedPanelStripTabbedPanelException    )partial)Clock)string_types)Factory)ToggleButton)Widget)Scatter)
ScrollView)
GridLayout)FloatLayout)Logger)dp)ObjectPropertyStringPropertyOptionPropertyListPropertyNumericPropertyAliasPropertyBooleanPropertyColorPropertyc                   @   s   e Zd ZdZdS )r   z$The TabbedPanelException class.
    N__name__
__module____qualname____doc__ r"   r"   8/tmp/pip-unpacked-wheel-xzebddm3/kivy/uix/tabbedpanel.pyr      s   r   c                       s4   e Zd ZdZedddZ fddZdd Z  ZS )	r   zA Base for implementing a Tabbed Panel Head. A button intended to be
    used as a Heading/Tab for a TabbedPanel widget.

    You can use this TabbedPanelHeader widget to add a new tab to a
    TabbedPanel.
    NTZ	allownonec                    s:   | j dkr&| jD ]}|d| qd S tt| | d S )Ndownon_touch_down)statechildrendispatchsuperr   r&   )selftouchchild	__class__r"   r#   r&      s
    

zTabbedPanelHeader.on_touch_downc                 G   s*   | j r| j j|  n| j| jj d S N)parenttabbed_panel	switch_topanelcurrent_tab)r+   largsr"   r"   r#   
on_release   s    zTabbedPanelHeader.on_release)	r   r   r    r!   r   contentr&   r7   __classcell__r"   r"   r.   r#   r      s   	r   c                   @   s    e Zd ZdZdd Zdd ZdS )r   a  This is a convenience class that provides a header of type
    TabbedPanelHeader and links it with the content automatically. Thus
    facilitating you to simply do the following in kv language:

    .. code-block:: kv

        <TabbedPanel>:
            # ...other settings
            TabbedPanelItem:
                BoxLayout:
                    Label:
                        text: 'Second tab content area'
                    Button:
                        text: 'Button that does nothing'

    .. versionadded:: 1.5.0
    c                 O   s0   || _ | jsd S | jj}|j| kr,||  d S r0   )r8   r1   r2   r5   r3   )r+   widgetargskwargsr4   r"   r"   r#   
add_widget   s    
zTabbedPanelItem.add_widgetc                 O   s2   d | _ | jsd S | jj}|j| kr.|j|| d S r0   )r8   r1   r2   r5   remove_widget)r+   r;   r<   r4   r"   r"   r#   r>      s    
zTabbedPanelItem.remove_widgetN)r   r   r    r!   r=   r>   r"   r"   r"   r#   r      s   r   c                   @   s   e Zd ZdZedZdS )r   zA strip intended to be used as background for Heading/Tab.
    This does not cover the blank areas in case the tabs don't cover
    the entire width/height of the TabbedPanel(use :class:`StripLayout`
    for that).
    N)r   r   r    r!   r   r2   r"   r"   r"   r#   r      s   r   c                   @   s(   e Zd ZdZeddddgZedZdS )r   z The main layout that is used to house the entire tabbedpanel strip
    including the blank areas in case the tabs don't cover the entire
    width/height.

    .. versionadded:: 1.8.0

       ,atlas://data/images/defaulttheme/action_viewN)r   r   r    r!   r   borderr   background_imager"   r"   r"   r#   r      s   r   c                   @   s   e Zd ZdZdS )r   z"The TabbedPanelContent class.
    Nr   r"   r"   r"   r#   r     s   r   c                       s  e Zd ZdZeddddgZeddddgZedZ	edZ
edZeddddgZedZd	d
 ZeedddZedddZedZedddZedZedgdgdgddgddgfdZedZedZeeZdd ZeedZedZ edddZ!dd Z"dd Z#ee"e#ddZ$d d! Z%d"d# Z&ee%e&Z'd Z( Z)Z* fd$d%Z+dQd'd(Z,d)d* Z- fd+d,Z. fd-d.Z/d/d0 Z0d1d2 Z1d3d4 Z2d5d6 Z3d7d8 Z4d9d: Z5d;d< Z6d=d> Z7d?d@ Z8dAdB Z9dCdD Z:dEdF Z; fdGdHZ<dIdJ Z=dKdL Z>dMdN Z?dOdP Z@  ZAS )Rr   zJThe TabbedPanel class. See module documentation for more information.
          z$atlas://data/images/defaulttheme/tabz-atlas://data/images/defaulttheme/tab_disabledr@   r?   Nc                 C   s   | j S r0   _current_tabr+   r"   r"   r#   get_current_tabL  s    zTabbedPanel.get_current_tabrE   )bindtop_left)Zleft_topZleft_midZleft_bottomrJ   top_mid	top_rightZ	right_topZ	right_midZright_bottombottom_left
bottom_midbottom_right)optionsZ40dpZ100dpTr$   Z2dpr8   ZbarszDefault tabc                 C   s   | j r| j jS dS )Ng      ?)
_tab_stripr(   rG   r"   r"   r#   get_tab_list  s    zTabbedPanel.get_tab_list)
allow_nonec                 C   s   | j S r0   _default_tabrG   r"   r"   r#   get_def_tab  s    zTabbedPanel.get_def_tabc                 C   sR   t |jtstd| j|kr"d S | j}|| _| | d | _| | d|_d S )NP`default_tab_class` should be                subclassed from `TabbedPanelHeader`r%   )	
issubclassr/   r   r   rU   r>   _original_tabr3   r'   )r+   Znew_tabZoltabr"   r"   r#   set_def_tab  s    


zTabbedPanel.set_def_tabrT   c                 C   s   | j jS r0   default_tabr8   rG   r"   r"   r#   get_def_tab_content  s    zTabbedPanel.get_def_tab_contentc                 G   s   |d | j _d S Nr   r[   r+   lr"   r"   r#   set_def_tab_content  s    zTabbedPanel.set_def_tab_contentc                    s   g | _ tdd| _d| _t| dd| j| jd| _d | _t	 | _
t  | _ | _| _tt| jf | | d| j | jst| j d S |   | | j d S )NrC   )rowsNN)r2   rb   	size_hintheightwidthsize)
_childrensr   _tab_layoutrb   r   
tab_height	tab_widthrQ   _partial_update_scrollviewr   r8   r   rF   rY   rU   r*   r   __init__Zfbind_reposition_tabsdo_default_tabr
   schedule_once_switch_to_first_tab_setup_default_tabr3   r\   )r+   r<   r.   r"   r#   rm     s,      zTabbedPanel.__init__Fc                 C   sf   |j }d| j_d|_|| _|   |dkr.dS |j}|rB|| | | |rb| j}|j| dS )a  Switch to a specific panel header.

        .. versionchanged:: 1.10.0

        If used with `do_scroll=True`, it scrolls
        to the header's tab too.

        :meth:`switch_to` cannot be called from within the
        :class:`TabbedPanel` or its subclass' ``__init__`` method.
        If that is required, use the ``Clock`` to schedule it. See `discussion
        <https://github.com/kivy/kivy/issues/3493#issuecomment-121567969>`_
        for full example.
        normalr%   N)	r8   rF   r'   clear_widgetsr1   r>   r=   rQ   Z	scroll_to)r+   headerZ	do_scrollZheader_contentr1   tabsr"   r"   r#   r3     s    

zTabbedPanel.switch_toc                 G   s8   | j }|  | jr,| j}|| |j|_|   d S r0   )rQ   rt   ro   rU   r=   rf   rn   )r+   r`   	self_tabsZself_default_tabr"   r"   r#   
clear_tabs%  s    
zTabbedPanel.clear_tabsc                    s   | j }|d krd S |j}|r&|| ||| jfkrNtt| j|f|| nlt|tr| j	}|j|f|| d|j
 |_|   n4ddd|_| j| | jj|_|j|f|| d S )N	__tab%r__r   rC   )xtop)r8   r1   r>   ri   r*   r   r=   
isinstancer   rQ   uidgroupon_tab_widthZpos_hintrh   appendr5   disabled)r+   r:   r;   r<   r8   r1   rw   r.   r"   r#   r=   .  s"    



zTabbedPanel.add_widgetc                    s   | j }|d krd S ||| jfkr:tt| j|f|| nt|tr| jrT|| jks| j	}| j
|j
8  _
|| |jdkr| jr| j  |   qtd n2|| jkr| j| ||jkr|j|f|| d S )Nr%   zTTabbedPanel: default tab! can't be removed.
Change `default_tab` to a different tab.)r8   ri   r*   r   r>   r|   r   ro   rU   rQ   rf   r'   r7   rn   r   inforh   remover(   )r+   r:   r;   r<   r8   rw   r.   r"   r#   r>   B  s$    





zTabbedPanel.remove_widgetc                 O   s   | j r| j j|| d S r0   )r8   rt   )r+   r;   r<   r"   r"   r#   rt   Y  s    zTabbedPanel.clear_widgetsc                 C   s   | j s
d S || j _d S r0   )ri   rB   r+   instancevaluer"   r"   r#   on_strip_image]  s    zTabbedPanel.on_strip_imagec                 C   s   | j s
d S || j _d S r0   )ri   rA   r   r"   r"   r#   on_strip_borderb  s    zTabbedPanel.on_strip_borderc                 C   sD   |s0| j }|| jkr@| | |   | j| _nd| j_|   d S )Nrs   )r\   tab_listr>   rq   rF   rU   r'   rr   )r+   r   r   Zdftr"   r"   r#   on_do_default_tabg  s    


zTabbedPanel.on_do_default_tabc                 G   s   | j | j_d S r0   )default_tab_textrU   text)r+   r;   r"   r"   r#   on_default_tab_textr  s    zTabbedPanel.on_default_tab_textc                 G   s,   | j }|d kr"t| jd }| _ |  d S r^   )_update_tab_evr
   create_trigger_update_tab_widthr+   r`   evr"   r"   r#   r   u  s     
zTabbedPanel.on_tab_widthc                 G   s   | j  | j_| j_|   d S r0   )rj   ri   re   rQ   rn   r_   r"   r"   r#   on_tab_height|  s    zTabbedPanel.on_tab_heightc                 G   s   |    d S r0   )rn   r_   r"   r"   r#   
on_tab_pos  s    zTabbedPanel.on_tab_posc                 C   s  | j | jkrd S | j j}| j}| j}t|tr8t|}t	|t
sJtd|t
krf|  | _ | _| _ | j}| j| jkr| j|_| j|_d|j |_d|_| jr| jnd|_||_| j}||kr||t| |jr|   | | jj nt| j || _d S )NrW   ry   r%   d   )rU   r   r8   rQ   default_tab_clsr|   r   r   getrX   r   r   rF   rY   r\   r   r   rj   re   r}   r~   r'   rk   rf   r=   lenrt   r
   rp   _load_default_tab_content)r+   r8   Z_tabsclsr\   tlr"   r"   r#   rr     s6    


zTabbedPanel._setup_default_tabc                 G   s:   t | jd }|dkr6| j|  | _ }| _| | d S )NrC   )r   r   rF   rY   r3   )r+   r`   Zltldtr"   r"   r#   rq     s
    z TabbedPanel._switch_to_first_tabc                 C   s   | j r| | j  d S r0   )r\   r3   )r+   r   r"   r"   r#   r     s    z%TabbedPanel._load_default_tab_contentc                 G   s,   | j }|d kr"t| jd }| _ |  d S r^   )_update_tabs_evr
   r   _update_tabsr   r"   r"   r#   rn     s     
zTabbedPanel._reposition_tabsc              	      sJ  | j }|sd S | j}| j}|  tdd| j| jd}| j}|j}|rP|	| |
| d|_| j}| jd k	r~|j| jd t||| _|j| jd tt|   | j}	g }
g }|d }|dks|dkrd	| _d
| _d	|_d|_d|_|	|jd	  |jd  td
 |_|| |dkr~|dkrBt |t f}||f}
n:|dkr\|t t f}n|dkrtt t |f}||f}
nT|dkrt |t f}n2|dkr|t t f}n|dkrt t |f}||f}
n<|dks|dkrd
| _d	| _d|_d	|_d|_|	|_|	|_|| |d dkr.dnd}td|dddd|jd}|
| t|}||d d  dkr|jt| j|dd d |f}nd||d d  dkr|jt| j|d|jd t |t f}n$||d d  d krt t |f}|dkr
||f}
n||f}
|j
}|D ]}|| q| j
}|
D ]}|| q6d S )!N)NrC   F)rd   Zalways_overscroll	bar_widthscroll_typer   r   )rf   r   btrC         )rC   NrN   rM   rO   rK   rJ   rL   r`   rZ   irc   )Zdo_translationrotationZdo_rotationZdo_scalerd   Zauto_bring_to_frontrg   r?   Z_topr{   )posZ_midZmid   Z_bottom) r8   tab_posri   rt   r   r   r   rQ   r1   r>   r=   r   _update_scrollviewrl   Zunbindr	   rI   r*   r   rj   colsrb   rd   paddingr   re   r   rf   r   rg   r   _update_top)r+   r`   Zself_contentr   Z
tab_layoutscrl_vrv   r1   Zself_update_scrollviewrj   Zwidget_listr   Z
pos_letterr   sctrZ
lentab_posaddZwidgr.   r"   r#   r     s    


 












zTabbedPanel._update_tabsc                 G   sp   | j r,| jD ]
}d|_q| j t| jj }n0d}| jD ]$}|jrPd|_|d7 }q6||j7 }q6|| j_|   d S )NrC   r   r   )rk   r   Zsize_hint_xr   rQ   r(   rf   rn   )r+   r`   tabZtswr"   r"   r#   r   @  s    


zTabbedPanel._update_tab_widthc                 G   sF   |\}}}}}| j }|d k	r$|  tt| j|||d }| _ d S r^   )_update_top_evcancelr
   rp   r	   	_updt_top)r+   r;   r   r{   scrl_v_widthrz   yr   r"   r"   r#   r   T  s     zTabbedPanel._update_topc                 G   s0   |d dkr| j |_ n| j | j| d  |_ d S )Nr   r   r   )r{   re   )r+   r   r{   r   r;   r"   r"   r#   r   ]  s    
zTabbedPanel._updt_topc                 G   sl   | j }| j}|d dks$|d dkrRt| j|j|_| jd7  _| jd8  _nt| j|j|_d|_d S )Nr   r   r   rC   r   )r   rQ   minrf   r{   re   r   )r+   r   r`   Zself_tab_posrw   r"   r"   r#   r   c  s    zTabbedPanel._update_scrollview)F)Br   r   r    r!   r   Zbackground_colorr   rA   r   rB   Zbackground_disabled_imageZstrip_imageZstrip_borderr   rF   rH   r   r5   r   r   r   rj   rk   r   r   r   ro   r   r   r   rR   r   r8   rU   rV   rZ   r\   r]   ra   Zdefault_tab_contentr   r   r   rm   r3   rx   r=   r>   rt   r   r   r   r   r   r   r   rr   rq   r   rn   r   r   r   r   r   r9   r"   r"   r.   r#   r   
  s   
	
 	
	
	' 	r   N)+r!   __all__	functoolsr	   Z
kivy.clockr
   Zkivy.compatr   Zkivy.factoryr   Zkivy.uix.togglebuttonr   Zkivy.uix.widgetr   Zkivy.uix.scatterr   Zkivy.uix.scrollviewr   Zkivy.uix.gridlayoutr   Zkivy.uix.floatlayoutr   Zkivy.loggerr   Zkivy.metricsr   Zkivy.propertiesr   r   r   r   r   r   r   r   	Exceptionr   r   r   r   r   r   r   r"   r"   r"   r#   <module>   s*   y($$