o
    rZh                     @   sd   d Z ddlZddlmZmZmZmZmZ G dd deZG dd dZ	dd	 Z
ed
kr0e
  dS dS )zC
Tkinter widgets for displaying multi-column listboxes and tables.
    N)FrameLabelListbox	ScrollbarTkc                	   @   s  e Zd ZdZeddddZeddddd	d
ZeddddddddZdi fddZdd Z	dd Z
dd Zedd Zedd Zedd Zdd Zd d! Zd"d# Zdbd$d%Zi fd&d'Zd(d) Zi fd*d+Zi fd,d-Zdcd.d/Zd0d1 Zdcd2d3Zd4d5 Zd6d7 Zd8d9 Zddd:d;Zddd<d=Zddd>d?Z d@dA Z!dBdC Z"dDdE Z#dFdG Z$dHdI Z%dJdK Z&dLdM Z'dNdO Z(dPdQ Z)dRdS Z*dTdU Z+dVdW Z,dXdY Z-dZd[ Z.d\d] Z/d^d_ Z0d`da Z1eZ2eZ3eZ4e,Z5e-Z6e"Z7e.Z8dS )eMultiListboxa  
    A multi-column listbox, where the current selection applies to an
    entire row.  Based on the MultiListbox Tkinter widget
    recipe from the Python Cookbook (https://code.activestate.com/recipes/52266/)

    For the most part, ``MultiListbox`` methods delegate to its
    contained listboxes.  For any methods that do not have docstrings,
    see ``Tkinter.Listbox`` for a description of what that method does.
    z#888T   )
background	takefocushighlightthicknessraisedzhelvetica -16 boldz#444white)borderwidthZreliefZfontr	   
foregroundr   Fnone)r   Zselectborderwidthr   ZexportselectionselectbackgroundZactivestyler
   Nc                    sT  t |trtt|}d}nd}t|dkrtdt| _g  _g  _	|du r1dgt| }nt|t|kr=td| _
tj |fi  j  jddd t jD ]\}} j||| d |rt fd	|i j}	 j	|	 |	j|dd
ddd ||	_t fi  j}
 j|
 |
j|dd
ddd ||
_|
d j |
d j |
d fdd |
d fdd |
d fdd |
d fdd |
d fdd |
ddd  |
d j qW d j  d fdd  d fdd  d fd d  d! fd"d  j|fi | dS )#a  
        Construct a new multi-column listbox widget.

        :param master: The widget that should contain the new
            multi-column listbox.

        :param columns: Specifies what columns should be included in
            the new multi-column listbox.  If ``columns`` is an integer,
            then it is the number of columns to include.  If it is
            a list, then its length indicates the number of columns
            to include; and each element of the list will be used as
            a label for the corresponding column.

        :param cnf, kw: Configuration parameters for this widget.
            Use ``label_*`` to configure all labels; and ``listbox_*``
            to configure all listboxes.  E.g.:
                >>> root = Tk()  # doctest: +SKIP
                >>> MultiListbox(root, ["Subject", "Sender", "Date"], label_foreground='red').pack()  # doctest: +SKIP
        FTr   zExpected at least one columnNr   z*Expected one column_weight for each columnweighttextnewscolumnrowZstickyZpadxZpady
<Button-1>z<B1-Motion>z
<Button-4>c                    
     dS )N_scrolleself >/var/www/auris/lib/python3.10/site-packages/nltk/draw/table.py<lambda>      
 z'MultiListbox.__init__.<locals>.<lambda>z
<Button-5>c                    r   )Nr   r   r   r    r"   r#   r$      r%   z<MouseWheel>c                    s     | jS N)r   deltar   r    r"   r#   r$          z
<Button-2>c                         | j| jS r&   )	scan_markxyr   r    r"   r#   r$          z<B2-Motion>c                    r)   r&   )scan_dragtor+   r,   r   r    r"   r#   r$      r-   z
<B1-Leave>c                 S   s   dS )Nbreakr"   r   r"   r"   r#   r$      s    z<Up>c                        j ddS )Nr   r'   selectr   r    r"   r#   r$      r(   z<Down>c                    r0   )Nr   r1   r2   r   r    r"   r#   r$      r(   z<Prior>c                    s    j    dS Nr1   r3   	_pagesizer   r    r"   r#   r$      s    z<Next>c                    s    j   dS r4   r5   r   r    r"   r#   r$      r-   )
isinstanceintlistrangelen
ValueErrortuple_column_names
_listboxes_labels_column_weightsr   __init__FRAME_CONFIGZgrid_rowconfigure	enumerategrid_columnconfigurer   LABEL_CONFIGappendgridcolumn_indexr   LISTBOX_CONFIGbind_select_resize_column	configure)r!   mastercolumnscolumn_weightscnfkwZinclude_labelsilabelllbr"   r    r#   rB   >   sT   

zMultiListbox.__init__c                 C   s   |j drdS d| _|j | u r-t| jD ]\}}t|j| |   dk r+|| _qn"|j|j  d kr=|j j	| _n|jdk rO|j j	dkrO|j j	d | _| jduri|j d| j
 |j d	|j | j d
S dS )z
        Callback used to resize a column of the table.  Return ``True``
        if the column is actually getting resized (if the user clicked
        on the far left or far right 5 pixels of a label); and
        ``False`` otherwies.
        z<ButtonRelease>FN
      r   r   <Motion><ButtonRelease-%d>T)widgetrK   _resize_column_indexrD   r?   absr+   winfo_xwinfo_widthrI   _resize_column_motion_cbnum_resize_column_buttonrelease_cb)r!   eventrT   rW   r"   r"   r#   rM      s(   	

zMultiListbox._resize_columnc                 C   sb   | j | j }| |d  }|j|j  }| |  }tdt|d || |  |d< d S )Nwidth   )r?   r]   r`   r+   r\   r_   maxr8   )r!   rd   rW   Z	charwidthx1Zx2r"   r"   r#   ra      s
   &z%MultiListbox._resize_column_motion_cbc                 C   s"   |j d|j  |j d d S )Nr[   rZ   )r\   Zunbindrb   )r!   rd   r"   r"   r#   rc      s   z,MultiListbox._resize_column_buttonrelease_cbc                 C   s   | j S )zh
        A tuple containing the names of the columns used by this
        multi-column listbox.
        )r>   r    r"   r"   r#   column_names   s   zMultiListbox.column_namesc                 C   
   t | jS )a  
        A tuple containing the ``Tkinter.Label`` widgets used to
        display the label of each column.  If this multi-column
        listbox was created without labels, then this will be an empty
        tuple.  These widgets will all be augmented with a
        ``column_index`` attribute, which can be used to determine
        which column they correspond to.  This can be convenient,
        e.g., when defining callbacks for bound events.
        )r=   r@   r    r"   r"   r#   column_labels   s   
zMultiListbox.column_labelsc                 C   rj   )aY  
        A tuple containing the ``Tkinter.Listbox`` widgets used to
        display individual columns.  These widgets will all be
        augmented with a ``column_index`` attribute, which can be used
        to determine which column they correspond to.  This can be
        convenient, e.g., when defining callbacks for bound events.
        )r=   r?   r    r"   r"   r#   	listboxes   s   
	zMultiListbox.listboxesc                 C   s:   |j |j}| dd | | | | |   d S )Nr   end)r\   nearestr,   selection_clearselection_setactivatefocus)r!   r   rT   r"   r"   r#   rL      s
   

zMultiListbox._selectc                 C   s   | j D ]}||d qdS )Nunitr/   r?   yview_scroll)r!   r'   rW   r"   r"   r#   r      s   
zMultiListbox._scrollc                 C   s   t | dt | d S )z2:return: The number of rows that makes up one pagez
@0,1000000z@0,0)r8   indexr    r"   r"   r#   r6      s   zMultiListbox._pagesizec                 C   s   |dur|durt d|dur't|  dkrd| }n
t|  d | }| dd |durKtt|d|  d }| | |rM| 	| dS dS dS )a  
        Set the selected row.  If ``index`` is specified, then select
        row ``index``.  Otherwise, if ``delta`` is specified, then move
        the current selection by ``delta`` (negative numbers for up,
        positive numbers for down).  This will not move the selection
        past the top or the bottom of the list.

        :param see: If true, then call ``self.see()`` with the newly
            selected index, to ensure that it is visible.
        Nz$specify index or delta, but not bothr   r   rm   r   )
r<   r;   curselectionr8   ro   minrg   sizerp   seer!   rv   r'   rz   r"   r"   r#   r3     s   

zMultiListbox.selectc                 K   s   t t| t|  }t| D ]D\}}|ds"|dr4| jD ]}||dd |i q%q|ds>|drP| jD ]}||dd |i qAqt| ||i qdS )a  
        Configure this widget.  Use ``label_*`` to configure all
        labels; and ``listbox_*`` to configure all listboxes.  E.g.:

                >>> master = Tk()  # doctest: +SKIP
                >>> mlb = MultiListbox(master, 5)  # doctest: +SKIP
                >>> mlb.configure(label_foreground='red')  # doctest: +SKIP
                >>> mlb.configure(listbox_foreground='red')  # doctest: +SKIP
        Zlabel_zlabel-   NZlistbox_zlistbox-   )dictr9   items
startswithr@   rN   r?   r   )r!   rR   rS   keyvalrU   listboxr"   r"   r#   rN   *  s   


zMultiListbox.configurec                 C   s   |  ||i dS )z|
        Configure this widget.  This is equivalent to
        ``self.configure({key,val``)}.  See ``configure()``.
        N)rN   )r!   r   r   r"   r"   r#   __setitem__?  s   zMultiListbox.__setitem__c                 K   s$   | j D ]}|j||fi | qdS )z
        Configure all table cells in the given row.  Valid keyword
        arguments are: ``background``, ``bg``, ``foreground``, ``fg``,
        ``selectbackground``, ``selectforeground``.
        Nr?   itemconfigure)r!   	row_indexrR   rS   rW   r"   r"   r#   rowconfigureF  s   
zMultiListbox.rowconfigurec                 K   sz   | j | }tt| t|  }t| D ]!\}}|dv r3t| D ]
}||||i q'q|||i qdS )z
        Configure all table cells in the given column.  Valid keyword
        arguments are: ``background``, ``bg``, ``foreground``, ``fg``,
        ``selectbackground``, ``selectforeground``.
        )r	   bgr   Zfgr   selectforegroundN)r?   r~   r9   r   r:   ry   r   rN   )r!   	col_indexrR   rS   rW   r   r   rT   r"   r"   r#   columnconfigureO  s   
zMultiListbox.columnconfigurec                 K   s   | j | }|j||fi |S )z
        Configure the table cell at the given row and column.  Valid
        keyword arguments are: ``background``, ``bg``, ``foreground``,
        ``fg``, ``selectbackground``, ``selectforeground``.
        r   )r!   r   r   rR   rS   rW   r"   r"   r#   r   f  s   
zMultiListbox.itemconfigurec                 G   sX   |D ]}t |t | jkrtdqt| jtt| D ]\}}|j|g|R   qdS )a0  
        Insert the given row or rows into the table, at the given
        index.  Each row value should be a tuple of cell values, one
        for each column in the row.  Index may be an integer or any of
        the special strings (such as ``'end'``) accepted by
        ``Tkinter.Listbox``.
        zDrows should be tuples whose length is equal to the number of columnsN)r;   r>   r<   zipr?   r9   insert)r!   rv   rowseltrW   eltsr"   r"   r#   r   s  s   zMultiListbox.insertc                    s4    fdd| j D }rdd t| D S t|S )a  
        Return the value(s) of the specified row(s).  If ``last`` is
        not specified, then return a single row value; otherwise,
        return a list of row values.  Each row value is a tuple of
        cell values, one for each column in the row.
        c                    s   g | ]}|  qS r"   )get).0rW   firstlastr"   r#   
<listcomp>      z$MultiListbox.get.<locals>.<listcomp>c                 S   s   g | ]}t |qS r"   )r=   r   r   r"   r"   r#   r     s    )r?   r   r=   )r!   r   r   valuesr"   r   r#   r     s   zMultiListbox.getc           
      C   sZ   | j d|d\}}}}| j| |\}}}}	t|t| t|t| t|t|	fS )z
        Return the bounding box for the given table cell, relative to
        this widget's top-left corner.  The bounding box is a tuple
        of integers ``(left, top, width, height)``.
        r   )r   r   )Z	grid_bboxr?   bboxr8   )
r!   r   colZdxZdy_r+   r,   whr"   r"   r#   r     s   ,zMultiListbox.bboxc                 C   s4   | j r
| j |   | j|   | j|dd dS )a1  
        Hide the given column.  The column's state is still
        maintained: its values will still be returned by ``get()``, and
        you must supply its values when calling ``insert()``.  It is
        safe to call this on a column that is already hidden.

        :see: ``show_column()``
        r   r   N)r@   Zgrid_forgetrl   rE   )r!   r   r"   r"   r#   hide_column  s   	zMultiListbox.hide_columnc                 C   sV   | j | }| jr| j| j|ddddd | j| j|ddddd | j||d dS )z
        Display a column that has been hidden using ``hide_column()``.
        It is safe to call this on a column that is not hidden.
        r   r   r   r   r   N)rA   r@   rH   r?   rE   )r!   r   r   r"   r"   r#   show_column  s   




zMultiListbox.show_columnc                    s    fdd| j D S )aK  
        Add a binding to each ``Tkinter.Label`` widget in this
        mult-column listbox that will call ``func`` in response to the
        event sequence.

        :return: A list of the identifiers of replaced binding
            functions (if any), allowing for their deletion (to
            prevent a memory leak).
        c                    s   g | ]	}|  qS r"   )rK   )r   rU   addfuncsequencer"   r#   r         z/MultiListbox.bind_to_labels.<locals>.<listcomp>)rk   r!   r   r   r   r"   r   r#   bind_to_labels  s   
zMultiListbox.bind_to_labelsc                 C   s   | j D ]	}|||| qdS )aM  
        Add a binding to each ``Tkinter.Listbox`` widget in this
        mult-column listbox that will call ``func`` in response to the
        event sequence.

        :return: A list of the identifiers of replaced binding
            functions (if any), allowing for their deletion (to
            prevent a memory leak).
        N)rl   rK   )r!   r   r   r   r   r"   r"   r#   bind_to_listboxes  s   

zMultiListbox.bind_to_listboxesc                 C   s   |  |||| ||| S )ac  
        Add a binding to each ``Tkinter.Label`` and ``Tkinter.Listbox``
        widget in this mult-column listbox that will call ``func`` in
        response to the event sequence.

        :return: A list of the identifiers of replaced binding
            functions (if any), allowing for their deletion (to
            prevent a memory leak).
        )r   r   r   r"   r"   r#   bind_to_columns  s   
zMultiListbox.bind_to_columnsc                 O      | j d j|i |S Nr   )r?   rw   r!   argskwargsr"   r"   r#   rw        zMultiListbox.curselectionc                 O   r   r   )r?   selection_includesr   r"   r"   r#   r     r   zMultiListbox.selection_includesc                 O   r   r   )r?   itemcgetr   r"   r"   r#   r     r   zMultiListbox.itemcgetc                 O   r   r   )r?   ry   r   r"   r"   r#   ry     r   zMultiListbox.sizec                 O   r   r   )r?   rv   r   r"   r"   r#   rv     r   zMultiListbox.indexc                 O   r   r   )r?   rn   r   r"   r"   r#   rn     r   zMultiListbox.nearestc                 O       | j D ]
}|j|i | qd S r&   )r?   rq   r!   r   r   rW   r"   r"   r#   rq        
zMultiListbox.activatec                 O   r   r&   )r?   deleter   r"   r"   r#   r     r   zMultiListbox.deletec                 O   r   r&   )r?   r*   r   r"   r"   r#   r*     r   zMultiListbox.scan_markc                 O   r   r&   )r?   r.   r   r"   r"   r#   r.     r   zMultiListbox.scan_dragtoc                 O   r   r&   )r?   rz   r   r"   r"   r#   rz     r   zMultiListbox.seec                 O   r   r&   )r?   selection_anchorr   r"   r"   r#   r     r   zMultiListbox.selection_anchorc                 O   r   r&   )r?   ro   r   r"   r"   r#   ro     r   zMultiListbox.selection_clearc                 O   r   r&   )r?   rp   r   r"   r"   r#   rp     r   zMultiListbox.selection_setc                 O   s    | j D ]
}|j|i |}q|S r&   )r?   yview)r!   r   r   rW   vr"   r"   r#   r     s   
zMultiListbox.yviewc                 O   r   r&   )r?   yview_movetor   r"   r"   r#   r   $  r   zMultiListbox.yview_movetoc                 O   r   r&   rt   r   r"   r"   r#   ru   (  r   zMultiListbox.yview_scrollNNTr&   NNN)9__name__
__module____qualname____doc__r~   rC   rF   rJ   rB   rM   ra   rc   propertyri   rk   rl   rL   r   r6   r3   rN   r   r   r   r   r   r   r   r   r   r   r   r   rw   r   r   ry   rv   rn   rq   r   r*   r.   rz   r   ro   rp   r   r   ru   
itemconfig	rowconfigcolumnconfigZselect_anchorZselect_clearZselect_includesZ
select_setr"   r"   r"   r#   r      s    	^!	



$	




r   c                   @   sX  e Zd ZdZdddddi fddZdd Zdd	 Zd
d ZdHddZi fddZ	i fddZ
dIddZdHddZdHddZdHddZe	Ze
Ze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ed,d- Zd.d/ Zd0d1 Zd2d3 Zd4d5 Z dJd6d7Z!dKd9d:Z"d;d< Z#dLd=d>Z$d?d@ Z%dMdBdCZ&dNdDdEZ'dAZ(	 dFdG Z)dS )OTablea  
    A display widget for a table of values, based on a ``MultiListbox``
    widget.  For many purposes, ``Table`` can be treated as a
    list-of-lists.  E.g., table[i] is a list of the values for row i;
    and table.append(row) adds a new row with the given list of
    values.  Individual cells can be accessed using table[i,j], which
    refers to the j-th column of the i-th row.  This can be used to
    both read and write values from the table.  E.g.:

        >>> table[i,j] = 'hello'  # doctest: +SKIP

    The column (j) can be given either as an index number, or as a
    column name.  E.g., the following prints the value in the 3rd row
    for the 'First Name' column:

        >>> print(table[3, 'First Name'])  # doctest: +SKIP
        John

    You can configure the colors for individual rows, columns, or
    cells using ``rowconfig()``, ``columnconfig()``, and ``itemconfig()``.
    The color configuration for each row will be preserved if the
    table is modified; however, when new rows are added, any color
    configurations that have been made for *columns* will not be
    applied to the new row.

    Note: Although ``Table`` acts like a widget in some ways (e.g., it
    defines ``grid()``, ``pack()``, and ``bind()``), it is not itself a
    widget; it just contains one.  This is because widgets need to
    define ``__getitem__()``, ``__setitem__()``, and ``__nonzero__()`` in
    a way that's incompatible with the fact that ``Table`` behaves as a
    list-of-lists.

    :ivar _mlb: The multi-column listbox used to display this table's data.
    :ivar _rows: A list-of-lists used to hold the cell values of this
        table.  Each element of _rows is a row value, i.e., a list of
        cell values, one for each column in the row.
    NTc	                 K   s  t || _|| _t|| _dd t|D | _|du rg | _ndd |D | _| jD ]}
| |
 q*t	| j|||fi |	| _
| j
jdddd	 |rgt| jd
| j
jd}|j| j
jd d< |jddd || _d| _|r~t| j
jD ]\}}|d| j qr|   dS )a  
        Construct a new Table widget.

        :type master: Tkinter.Widget
        :param master: The widget that should contain the new table.
        :type column_names: list(str)
        :param column_names: A list of names for the columns; these
            names will be used to create labels for each column;
            and can be used as an index when reading or writing
            cell values from the table.
        :type rows: list(list)
        :param rows: A list of row values used to initialize the table.
            Each row value should be a tuple of cell values, one for
            each column in the row.
        :type scrollbar: bool
        :param scrollbar: If true, then create a scrollbar for the
            new table widget.
        :type click_to_sort: bool
        :param click_to_sort: If true, then create bindings that will
            sort the table's rows by a given column's values if the
            user clicks on that colum's label.
        :type reprfunc: function
        :param reprfunc: If specified, then use this function to
            convert each table cell value to a string suitable for
            display.  ``reprfunc`` has the following signature:
            reprfunc(row_index, col_index, cell_value) -> str
            (Note that the column is specified by index, not by name.)
        :param cnf, kw: Configuration parameters for this widget's
            contained ``MultiListbox``.  See ``MultiListbox.__init__()``
            for details.
        c                 S   s   i | ]\}}||qS r"   r"   )r   rT   cr"   r"   r#   
<dictcomp>  s    z"Table.__init__.<locals>.<dictcomp>Nc                 S   s   g | ]	}d d |D qS )c                 S   s   g | ]}|qS r"   r"   )r   r   r"   r"   r#   r     r-   z-Table.__init__.<locals>.<listcomp>.<listcomp>r"   r   r"   r"   r#   r     r   z"Table.__init__.<locals>.<listcomp>leftTboth)sideexpandfillvertical)Zorientcommandr   Zyscrollcommandrightr,   )r   r   r   )r;   _num_columns	_reprfuncr   _framerD   _column_name_to_index_rows	_checkrowr   _mlbpackr   r   setrl   Z
_scrollbar_sortkeyrk   rK   _sort_fill_table)r!   rO   ri   r   rQ   Z	scrollbarZclick_to_sortreprfuncrR   rS   r   sbrT   rV   r"   r"   r#   rB   l  s*   
+

zTable.__init__c                 O      | j j|i | dS )zrPosition this table's main frame widget in its parent
        widget.  See ``Tkinter.Frame.pack()`` for more info.N)r   r   r   r"   r"   r#   r        z
Table.packc                 O   r   )zrPosition this table's main frame widget in its parent
        widget.  See ``Tkinter.Frame.grid()`` for more info.N)r   rH   r   r"   r"   r#   rH     r   z
Table.gridc                 C   s   | j   dS )z-Direct (keyboard) input foxus to this widget.N)r   rr   r    r"   r"   r#   rr     s   zTable.focusc                 C      | j ||| dS )zkAdd a binding to this table's main frame that will call
        ``func`` in response to the event sequence.N)r   rK   r   r"   r"   r#   rK     s   z
Table.bindc                 K   s   | j j||fi | dS )z%:see: ``MultiListbox.rowconfigure()``N)r   r   )r!   r   rR   rS   r"   r"   r#   r     s   zTable.rowconfigurec                 K   s$   |  |}| jj||fi | dS )z(:see: ``MultiListbox.columnconfigure()``N)rI   r   r   )r!   r   rR   rS   r"   r"   r#   r     s   
zTable.columnconfigurec                 K   s"   |  |}| jj|||fi |S )z&:see: ``MultiListbox.itemconfigure()``)rI   r   r   )r!   r   r   rR   rS   r"   r"   r#   r     s   
zTable.itemconfigurec                 C      | j |||S )z':see: ``MultiListbox.bind_to_labels()``)r   r   r   r"   r"   r#   r        zTable.bind_to_labelsc                 C   r   )z*:see: ``MultiListbox.bind_to_listboxes()``)r   r   r   r"   r"   r#   r     r   zTable.bind_to_listboxesc                 C   r   )z(:see: ``MultiListbox.bind_to_columns()``)r   r   r   r"   r"   r#   r     r   zTable.bind_to_columnsc                    s^    | j | jdur fddt|D }j | jr-  dS dS )aT  
        Insert a new row into the table, so that its row index will be
        ``row_index``.  If the table contains any rows whose row index
        is greater than or equal to ``row_index``, then they will be
        shifted down.

        :param rowvalue: A tuple of cell values, one for each column
            in the new row.
        Nc                       g | ]\}}  ||qS r"   r   r   jr   r   r!   r"   r#   r     s    z Table.insert.<locals>.<listcomp>)r   r   r   r   rD   r   _DEBUG_check_table_vs_mlb)r!   r   rowvaluer"   r   r#   r     s   


zTable.insertc                 C   s*   |D ]}|  | q| jr|   dS dS )z
        Add new rows at the end of the table.

        :param rowvalues: A list of row values used to initialize the
            table.  Each row value should be a tuple of cell values,
            one for each column in the row.
        N)rG   r   r   )r!   Z	rowvaluesr   r"   r"   r#   extend	  s
   zTable.extendc                 C   s(   |  t| j| | jr|   dS dS )z
        Add a new row to the end of the table.

        :param rowvalue: A tuple of cell values, one for each column
            in the new row.
        N)r   r;   r   r   r   r!   r   r"   r"   r#   rG     s   zTable.appendc                 C   s*   g | _ | jdd | jr|   dS dS )z0
        Delete all rows in this table.
        r   rm   N)r   r   r   r   r   r    r"   r"   r#   clear!  s
   zTable.clearc                 C   sR   t |tr	tdt |tr"t|dkr"| j|d  | |d  S t| j| S )a  
        Return the value of a row or a cell in this table.  If
        ``index`` is an integer, then the row value for the ``index``th
        row.  This row value consists of a tuple of cell values, one
        for each column in the row.  If ``index`` is a tuple of two
        integers, ``(i,j)``, then return the value of the cell in the
        ``i``th row and the ``j``th column.
        Slicing not supported   r   r   )r7   slicer<   r=   r;   r   rI   )r!   rv   r"   r"   r#   __getitem__*  s
   
	zTable.__getitem__c                    s  t  tr	tdt  trUt dkrU d  d }}|g}|j| |< jdur9|||}j	j
| || j	j
| |d  | dS  g}| t|j < jdurx fddt|D }j	 | j	 d  | dS )a  
        Replace the value of a row or a cell in this table with
        ``val``.

        If ``index`` is an integer, then ``val`` should be a row value
        (i.e., a tuple of cell values, one for each column).  In this
        case, the values of the ``index``th row of the table will be
        replaced with the values in ``val``.

        If ``index`` is a tuple of integers, ``(i,j)``, then replace the
        value of the cell in the ``i``th row and ``j``th column with
        ``val``.
        r   r   r   r   Nc                    r   r"   r   r   rv   r!   r"   r#   r   \      z%Table.__setitem__.<locals>.<listcomp>)r7   r   r<   r=   r;   rI   _save_config_infor   r   r   rl   r   r   _restore_config_infor   r9   rD   )r!   rv   r   rT   r   config_cookier"   r   r#   r   :  s&   



zTable.__setitem__c                 C   sZ   t |tr	tdt |trt|dkrtd| j|= | j| | jr+| 	  dS dS )zA
        Delete the ``row_index``th row from this table.
        r   r   zCannot delete a single cell!N)
r7   r   r<   r=   r;   r   r   r   r   r   )r!   r   r"   r"   r#   __delitem__a  s   
zTable.__delitem__c                 C   rj   )z<
        :return: the number of rows in this table.
        )r;   r   r    r"   r"   r#   __len__n  s   
zTable.__len__c                 C   s*   t || jkrtd|t || jf dS )z
        Helper function: check that a given row value has the correct
        number of elements; and if not, raise an exception.
        z"Row %r has %d columns; expected %dN)r;   r   r<   r   r"   r"   r#   r   t  s   zTable._checkrowc                 C   s   | j jS )z1A list of the names of the columns in this table.)r   ri   r    r"   r"   r#   ri     s   zTable.column_namesc                 C   s.   t |trd|  kr| jk r|S  | j| S )z
        If ``i`` is a valid column index integer, then return it as is.
        Otherwise, check if ``i`` is used as the name for any column;
        if so, return that column's index.  Otherwise, raise a
        ``KeyError`` exception.
        r   )r7   r8   r   r   )r!   rT   r"   r"   r#   rI     s   
zTable.column_indexc                 C      | j | | dS )z$:see: ``MultiListbox.hide_column()``N)r   r   rI   r!   rI   r"   r"   r#   r        zTable.hide_columnc                 C   r   )z$:see: ``MultiListbox.show_column()``N)r   r   rI   r   r"   r"   r#   r     r   zTable.show_columnc                 C   s   | j  }|rt|d S dS )z
        Return the index of the currently selected row, or None if
        no row is selected.  To get the row value itself, use
        ``table[table.selected_row()]``.
        r   N)r   rw   r8   )r!   selr"   r"   r#   selected_row  s   
zTable.selected_rowc                 C   r   )z:see: ``MultiListbox.select()``N)r   r3   r{   r"   r"   r#   r3     s   zTable.selecttogglec                 C   s   |dvrt d| |}| jdd}|dkr"|| jkr"| j  n| jjt||dkd || _| 	  | j
|ddd | jrG|   d	S d	S )
a  
        Sort the rows in this table, using the specified column's
        values as a sort key.

        :param column_index: Specifies which column to sort, using
            either a column index (int) or a column's label name
            (str).

        :param order: Specifies whether to sort the values in
            ascending or descending order:

              - ``'ascending'``: Sort from least to greatest.
              - ``'descending'``: Sort from greatest to least.
              - ``'toggle'``: If the most recent call to ``sort_by()``
                sorted the table by the same column (``column_index``),
                then reverse the rows; otherwise sort in ascending
                order.
        )Z	ascending
descendingr   zBsort_by(): order should be "ascending", "descending", or "toggle".T)index_by_idr   r   )r   reverse)r   rz   N)r<   rI   r   r   r   r  sortoperator
itemgetterr   r   r   r   )r!   rI   orderr   r"   r"   r#   sort_by  s"   
zTable.sort_byc                 C   s&   |j j}| j|rdS | | dS )zLEvent handler for clicking on a column label -- sort by
        that column.continue)r\   rI   r   rM   r  )r!   rd   rI   r"   r"   r#   r     s
   
zTable._sortc                    sV   j dd tjD ]\ }jdur! fddt|D }j d| qdS )a  
        Re-draw the table from scratch, by clearing out the table's
        multi-column listbox; and then filling it in with values from
        ``self._rows``.  Note that any cell-, row-, or column-specific
        color configuration that has been done will be lost.  The
        selection will also be lost -- i.e., no row will be selected
        after this call completes.
        r   rm   Nc                    r   r"   r   r   rT   r!   r"   r#   r     r   z%Table._fill_table.<locals>.<listcomp>)r   r   rD   r   r   r   )r!   Zsave_configr   r"   r  r#   r     s   	
zTable._fill_tablec                    s    fdddD S )Nc                    s"   i | ]}|j  |d  qS )r   )r   r   )r   kr   rr!   r"   r#   r     s    z)Table._get_itemconfig.<locals>.<dictcomp>)r   r   r	   r   r"   )r!   r  r   r"   r
  r#   _get_itemconfig   s   zTable._get_itemconfigFc                    st   |du rt tt j}  }|r|durt j| }|r- fdd|D }||fS  fdd|D }||fS )a*  
        Return a 'cookie' containing information about which row is
        selected, and what color configurations have been applied.
        this information can the be re-applied to the table (after
        making modifications) using ``_restore_config_info()``.  Color
        configuration information will be saved for any rows in
        ``row_indices``, or in the entire table, if
        ``row_indices=None``.  If ``index_by_id=True``, the the cookie
        will associate rows with their configuration information based
        on the rows' python id.  This is useful when performing
        operations that re-arrange the rows (e.g. ``sort``).  If
        ``index_by_id=False``, then it is assumed that all rows will be
        in the same order when ``_restore_config_info()`` is called.
        Nc                    s2   i | ] t j   fd dtjD qS )c                       g | ]}  |qS r"   r  r   r   r  r!   r"   r#   r   &  s    6Table._save_config_info.<locals>.<dictcomp>.<listcomp>)idr   r:   r   r   r    r  r#   r   %  s    z+Table._save_config_info.<locals>.<dictcomp>c                    s(   i | ]   fd dt jD qS )c                    r  r"   r  r  r  r"   r#   r   -  r   r  )r:   r   r  r    r  r#   r   ,  s    )r9   r:   r;   r   r   r  )r!   Zrow_indicesr   	selectionconfigr"   r    r#   r     s   

zTable._save_config_infoc           	   	   C   s   |\}}|du r| j dd |rGt| jD ].\}}t||v r6t| jD ]}| j |||t| |  q%t||krD| j j||d qdS |durS| j j||d |D ]}t| jD ]}| j |||| |  q\qUdS )zy
        Restore selection & color configuration information that was
        saved using ``_save_config_info``.
        Nr   rm   )rz   )	r   ro   rD   r   r  r:   r   r   r3   )	r!   cookier   rz   r  r  r  r   r   r"   r"   r#   r   3  s&   zTable._restore_config_infoc                 C   s   | j jD ]}t| | ksJ q| D ]}t|| jksJ q| jt| j jks*J t| D ]%\}}t|D ]\}}| jdurF| |||}| j || |ksRJ q6q.dS )a  
        Verify that the contents of the table's ``_rows`` variable match
        the contents of its multi-listbox (``_mlb``).  This is just
        included for debugging purposes, to make sure that the
        list-modifying operations are working correctly.
        N)	r   rl   r;   ry   r   ri   rD   r   r   )r!   r   r   rT   r   cellr"   r"   r#   r   U  s   
zTable._check_table_vs_mlbr   r&   r   )r   )T)NF)FF)*r   r   r   r   rB   r   rH   rr   rK   r   r   r   r   r   r   r   r   r   r   r   rG   r   r   r   r   r   r   r   ri   rI   r   r   r   r3   r  r   r   r  r   r   r   r   r"   r"   r"   r#   r   E  s^    *
T




	'


)


(r   c            
         sx  t    d fdd t d g ddd d} | jdd	d
 ddlm}m} tt	|
 d d D ]D\}}|d dkrAq6| }||D ]/}z
| d  }W n   d}Y z
| d  }W n   d}Y | || ||g qJq6| jddd | jddd | jddd | jddd tt| D ]}dD ]}	| ||	f dkr| j||	ddd qq   d S )Nz<Control-q>c                    s      S r&   )destroyr   rootr"   r#   r$   q      zdemo.<locals>.<lambda>zWord Synset Hypernym Hyponym)r   r   r   r   c                 S   s   d| S )Nz  %sr"   )rT   r   sr"   r"   r#   r$   w  r  )rQ   r   Tr   )r   r   r   )brownwordneti  Nz*none*Wordz#afa)r	   ZSynsetz#efeHypernymz#feeHyponymz#ffe)r"  r#  z#666)r   r   )r   rK   r   splitr   Znltk.corpusr  r  sortedr   Ztagged_wordslowerZsynsetsZ	hypernymsZ
definitionrG   r   r:   r;   r   Zmainloop)
tabler  r  wordposZsynsetZ	hyper_defZhypo_defr   r   r"   r  r#   demoo  sL    r*  __main__)r   r  tkinterr   r   r   r   r   r   r   r*  r   r"   r"   r"   r#   <module>   s"       5    .*
