
    e`                       d Z ddlmZ ddlZddl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 ddlmZ ddlZddlmZ ddlmZ ddl m!Z!m"Z" ddl#m$Z$m%Z%m&Z' ddl(m)Z)m*Z*m+Z+m,Z, ddl-m.Z.m/Z/m0Z0m1Z1 ddl2m3Z3m4Z4 ddlm5Z5 ddl6m7Z7 ddl8m9Z9 ddl:m;Z;m<Z< erddl=m>Z> ddl?m@Z@ ddlAmBZB eeCeeDe,f         ZEeeCeEf         ZFdZGdZHdZIdZJd ZKd!ZLd"ZMi d#eGd$eGd%eGd&eGd'eGd(eGd)eHd*eHd+eHd,eHd-eHd.eHd/eHd0eId1eJd2eJd3di d4d5d6d7d8d9d:d;d<d=d>d?d@eKdAeKdBeLdCeLdDeLdEdFdGdHdIdJdKdLdMdNdOdPeMeMdQdRdSZNe G dT dU                      ZO G dV dWe$          ZPdS )XzJ
The message module provides a low-level API for rendering chat messages.
    )annotationsN)	ExitStack)	dataclass)partial)BytesIO)NamedTemporaryFile)indent)TYPE_CHECKINGAnyClassVarDictIterableListUnion)ZoneInfo   )CDN_DIST)state)ColumnRow)PaneBaseReplacementPanepanel)PDFFileBaseImage	ImageBase)HTML	DataFrameHTMLBasePaneMarkdown)AudioVideo)ParamFunction)Viewable)Widget   )ChatCopyIconChatReactionIcons)Document)Model)Commu   🧑u   🤖u   ⚙️u   ❌zuhttps://upload.wikimedia.org/wikipedia/commons/thumb/0/04/ChatGPT_logo.svg/1024px-ChatGPT_logo.svg.png?20230318122128z=https://upload.wikimedia.org/wikipedia/commons/a/a4/GPT-4.pngzvhttps://upload.wikimedia.org/wikipedia/commons/thumb/e/eb/WolframCorporateLogo.svg/1920px-WolframCorporateLogo.svg.pngclientcustomeremployeehumanpersonuseragentai	assistantbotchatbotmachinerobotsystem	exceptionerroradultbabyu   👶boyu   👦childu   🧒girlu   👧manu   👨womanu   👩chatgptgpt3gpt4dalleopenaihuggingfaceu   🤗
calculatoru   🧮	langchainu   🦜	retrieveru   📄toolu   🛠️
translatoru   🌐u   🦙u   🐪)wolframzwolfram alphallamallama2c                  2    e Zd ZU dZded<   ded<   ded<   dS )_FileInputMessagea  
    A dataclass to hold the contents of a file input message.

    Parameters
    ----------
    contents : bytes
        The contents of the file.
    file_name : str
        The name of the file.
    mime_type : str
        The mime type of the file.
    bytescontentsstr	file_name	mime_typeN)__name__
__module____qualname____doc____annotations__     2lib/python3.11/site-packages/panel/chat/message.pyrS   rS   g   s7           OOONNNNNNNNr_   rS   c                       e Zd ZU dZ ej        deeee	fd          Z
 ej        dd          Z ej        dgd	          Z ej        ed
          Z ej        dd          Z ej        dd          Z ej        d          Z ej        edd          Z ej        d          Z ej        dd          Z ej        dd          Z ej        dd          Z ej        dd          Z  ej        dd          Z! ej        dd          Z" ej        dd          Z# ej        dd          Z$ ej%        d           Z& ej        d!d"          Z'e( d#gZ)d$e*d%<   dZ+d&e*d'<   d] fd(	Z,d) Z-d* Z.	 	 d^d_d2Z/d`d3Z0e1dad5            Z2	 	 dbdcd>Z3e4ddd@            Z5dedBZ6dfdEZ7dF Z8e4dG             Z9d]dHZ:dgdJZ;d]dKZ<dL Z=d]dMZ> ej?        dNd?dO          dP             Z@dQ ZAd]dh fdSZBdidUZC	 	 djdkd[ZD	 	 d^dld\ZE xZFS )mChatMessageu  
    A widget for displaying chat messages with support for various content types.

    This widget provides a structured view of chat messages, including features like:
    - Displaying user avatars, which can be text, emoji, or images.
    - Showing the user's name.
    - Displaying the message timestamp in a customizable format.
    - Associating reactions with messages and mapping them to icons.
    - Rendering various content types including text, images, audio, video, and more.

    Reference: https://panel.holoviz.org/reference/chat/ChatMessage.html

    :Example:

    >>> ChatMessage(object="Hello world!", user="New User", avatar="😊")
     a  
        The avatar to use for the user. Can be a single character
        text, an emoji, or anything supported by `pn.pane.Image`. If
        not set, checks if the user is available in the
        default_avatars mapping; else uses the first character of the
        name.)defaultclass_docNz
        A function that can lookup an `avatar` from a user name. The
        function signature should be `(user: str) -> Avatar`. If this
        is set, `default_avatars` is disregarded.)rd   rf   zchat-messagez0
        The CSS classes to apply to the widget.z
        A default mapping of user names to their corresponding avatars
        to use when the user is specified but the avatar is. You can
        modify, but not replace the dictionary.i  )r   N)rd   boundsFzO
        The message contents. Can be any Python object that panel can display.)
allow_refsrf   z1
        Reactions to associate with the message.)rf   zu
        A mapping of reactions to their reaction icons; if not provided
        defaults to `{"favorite": "heart"}`.)re   rf   rh   zA
        Timestamp of the message. Defaults to the creation time.z%H:%MzThe timestamp format.a*  
        The timezone to used for the creation timestamp; only applicable
        if timestamp is not set. If None, tries to use pn.state.browser_info.timezone,
        else, the default tz of datetime.datetime.now(); see `zoneinfo.available_timezones()`
        for a list of valid timezones.
    Tz4
         Whether to display the avatar of the user.z1
        Whether to display the name of the user.z9
        Whether to display the timestamp of the message.z/
        Whether to display the reaction icons.z*
        Whether to display the copy icon.z*
        Whether to show the activity dot.a,  
        A callable or list of callables that accept the object and return a
        Panel object to render the object. If a list is provided, will
        attempt to use the first renderer that does not raise an
        exception. If None, will attempt to infer the renderer
        from the object.Userz/
        Name of the user who sent the message.zcss/chat_message.csszClassVar[List[str]]_stylesheetszClassVar[bool]_updatesc           	     J   t                      | _        t          ddddg          | _        |                    d          |                    d          }|t          |          }n;t          j        r/t          j        j        rt          t          j        j                  }t          j	        
                    |          |d<   |                    dd	d
i          }t          |t                    r*t          |dd|                    dg                     |d<   d| _         t                      j        dd|i| | j                            | dd           | j        j        | j        _        | j        s|                                  |                                  d S )NF   z	copy-icon)visiblewidthheightcss_classes	timestamptimestamp_tz)tzreaction_iconsfavoriteheart	reactions)optionsro   rp   valueTobject)rz   bidirectionalr^   )r   _exit_stackr(   chat_copy_icongetr   r   browser_infotimezonedatetimenow
isinstancedictr)   	_internalsuper__init__ru   linkparamshow_reaction_iconsrn   avatar_update_avatar_build_layout)selfr{   paramsrt   ru   	__class__s        r`   r   zChatMessage.__init__   s   $;;*B[M
 
 
 ::k""*N++B~b\\# ;(:(C ;e09::"*"3"7"72"7">">F;$4z76KLLnd++ 	'8&bjjb11( ( (F#$ 111&111  [ MMM&*j&D#{ 	"!!!r_   c           
     d    t          ddg j        j                   _        t	                                           dddg j         j        j        d           x _        } j        	                     j
        d                                 j                   _                                          t           j         j        d	g j        d 
           _         j        	                     j        d           t           j        j        ddg j        j         j                   _        t           j        j                                                             j        j                  dg j        j                   _        t	          t           j         j         j         j        ddg           j         j        dg j        d 
          x _        } fd j        D             } j         j        j                                        z   |d<   t          ||fi | _        d S )Nu   ●zactivity-dot)rq   rn   <   d   left)	max_widthrp   rq   stylesheetsrn   sizing_moder   center)rq   r   r   r{      name)rp   rq   rn   r   rr   stretch_widthheader)r   r   rq   rightc                p    i | ]2}|t           j        v r"|t           j        v |d k    $|j        |         3S )r   )r%   r   ).0pr   s     r`   
<dictcomp>z-ChatMessage._build_layout.<locals>.<dictcomp>'  sJ     
 
 
!"A4G4GHN""qF{{ tz!}'2{{r_   r   ) r   r   show_activity_dot_activity_dotr   _render_avatarrj   show_avatar	_left_colwatch_update_avatar_pane_create_panelr{   _object_panel_update_chat_copy_iconr   ru   _center_row_update_object_paner2   	show_user
_user_htmlrr   rxstrftimetimestamp_formatshow_timestamp_timestamp_htmlr~   
_right_colr   
_composite)r   left_col	right_colviewable_paramss   `   r`   r   zChatMessage._build_layout   s]   !/9U
 
 
 %+!!)J*%
 %
 %
 	
 	
18<<<!//<<##%%%!
)
 
 
 	
18<<<JOBVHJ(d6G
 
 
  $J ##%%..tz/JKK$J- 
  
  

 '-#" -+%J     	)'
 '
 '
 	
)
 
 
 
&*j
 
 
 *.):TZ=S=V=V=X=X)X&h	EE_EEr_   c                n    |j         }t          |          j        }|                    |          s|s|}|S )z
        Get the label for the object; defaults to specified object name;
        if unspecified, defaults to the type name.
        )r   typerY   
startswith)r   objlabel	type_names       r`   _get_obj_labelzChatMessage._get_obj_label.  sB    
 II&	 I&& 	e 	Er_   r   r   prefix_with_viewable_labelboolprefix_with_container_labelreturnrV   c                ,    t          |t                    rt          |t                    st           fd|D                       }rst	          |          dk    r!                     |           d|d          dS t          d                    |          d          }                     |           d	| d
S dd                    |           dS |}t          |d          r|j	        }nt          |d          r|j
        }t          |d          st          |t                    r2 j                            d|                                 |          S r1t          |t                    r                     |          }| d|}|S )z?
        Recursively serialize the object to a string.
        c              3  H   K   | ]}                     |           V  dS )r   r   N)_serialize_recursively)r   or   r   r   s     r`   	<genexpr>z5ChatMessage._serialize_recursively.<locals>.<genexpr>E  sW        
 	 ++/I0K ,       r_   r'   (r   )z,
z    )prefixz(
z
)z, rz   r{   decodezhSerializing byte-like objects are not supported yet; using the label of the object as a placeholder for =)r   r   rV   tuplelenr   r	   joinhasattrrz   r{   r   r   warningr%   )r   r   r   r   contentindented_contentstringr   s   ` ``    r`   r   z"ChatMessage._serialize_recursively;  s    c8$$ 	1ZS-A-A 	1      
     G + 1w<<1$$"11#66FFFFFF'-ejj.A.A''R'R'R$ #11#66PP;KPPPP 1499W--00003   	 YFFS(## 	 ZF68$$ 	,
67(C(C 	,JLFIL L   &&s+++% 	+*S(*C*C 	+'',,E****Fr_   c                *    |                                  S )z;
        Serialize the message object to a string.
        )	serializer   s    r`   __str__zChatMessage.__str__n  s     ~~r_   	List[str]c                    g S Nr^   r   s    r`   _synced_paramszChatMessage._synced_paramst  s    	r_   rf   r*   rootModel | NoneparentcommComm | Noner+   c                v    | j                             ||||          }|p|j        d         }||f| j        |<   |S )Nid)r   
_get_modelref_models)r   rf   r   r   r   modelr   s          r`   r   zChatMessage._get_modelx  sE     **3fdCC}u!$'"FOSr_   r2   c                R    t          j        dd|                                           S )zu
        Convert the user name to an alpha numeric string,
        removing all non-alphanumeric characters.
        z\W+rc   )resublower)r2   s    r`   _to_alpha_numericzChatMessage._to_alpha_numeric  s$     vfb$''--///r_   Avatarc                
                          |          }t                                          }|                     j                    fd|                                D             }|                    | j                  S )z1
        Lookup the avatar for the user.
        c                B    i | ]\  }}                     |          |S r^   )r   )r   keyrz   r   s      r`   r   z.ChatMessage._avatar_lookup.<locals>.<dictcomp>  s:     
 
 
3=3D""3''
 
 
r_   )r   DEFAULT_AVATARScopyupdatedefault_avatarsitemsr   r   )r   r2   alpha_numeric_keyupdated_avatarss   `   r`   _avatar_lookupzChatMessage._avatar_lookup  s     !22488)..00t3444
 
 
 
APAVAVAXAX
 
 
 ""#4dkBBBr_   rU   rX   c                   t           }|dk    r?| j                            t          |                    }t	          t
          d          }n|                    d          rc| j                            t          dd                    }|                    |           |	                    d           |j
        }t          }n$|                    d	          r/| j                            t          |                    }t          }n|                    d
          r/| j                            t          |                    }t          }n|                    d          rHddl}t          |          5 }|                    |          }ddd           n# 1 swxY w Y   t"          }n?|                    d          r*t%          |t&                    r|                    d          }||fS )zG
        Determine the renderer to use based on the mime type.
        zapplication/pdfT)embedzaudio/z.mp3F)suffixdeleter   zvideo/zimage/z/csvNtextzutf-8)_panelr}   enter_contextr   r   r   r   r   writeseekr   r"   r#   r   endswithpandasread_csvr   r   rT   r   )r   rU   rX   rendererfilepdbufs          r`   _select_rendererzChatMessage._select_renderer  s
    )))'55gh6G6GHHHs$///HH!!(++ 	4#11"&??? D JJx   IIaLLLyHHH!!(++ 	4'55gh6G6GHHHHH!!(++ 	4'55gh6G6GHHHHH'' 	4"" ,c;;s++, , , , , , , , , , , , , , , HH!!&)) 	4(E** 4#??733!!s   5FFFc                V    t          |d          rY fd|j        D              j        z   |d<   |j        D ]}                     |           |j                            |           dS t          |t                    ot          |t                     }|rCt          t          |j                            dk    rg d |j        D             d|d<   d|d<   n4|j        |j        sd	|d<   |j        t          |t"                    sd
|d<   |j                            |           dS )z?
        Set the sizing mode and height of the object.
        objectsc                &    g | ]}|j         v|S r^   )rj   )r   cssr   s     r`   
<listcomp>z+ChatMessage._set_params.<locals>.<listcomp>  s&    PPP3d>O3O3O3O3O3Or_   rq   Nr   c              3  &   K   | ]}|d k    |V  dS )messageNr^   )r   r  s     r`   r   z*ChatMessage._set_params.<locals>.<genexpr>  s-      *^*^3ST]M]M]3M]M]M]M]*^*^r_   r  r   r   i  rp   )r   r   rj   r  _set_paramsr   r   r   r    r   r   rV   r{   rq   r   ro   rp   r$   )r   r   r   subobj	is_markups   `    r`   r  zChatMessage._set_params  sW    3	"" 	PPPPPPP!" =! + ) )  ((((IV$$$FsL11S*S(:S:S6S	 		'3sz??##a''(j*^*^#/*^*^*^(j`i(j}%$(F=!!&sy&(7}%z!*S-*H*H!#&x 	     r_   c                V    t          | t                    ot          | t                    S r   )r   r   
issubclassr&   )r	  s    r`   _is_widget_rendererzChatMessage._is_widget_renderer  s!    (D))Jj6.J.JJr_   c                   t          |t                    r	d| _        |S d}t          |t                    r(|j        }|j        }|                     ||          \  }}nF	 ddl}|                    |d          }|                     ||          \  }}n# t          $ r Y nw xY w| j
                                        pg }||                    |           |D ]W}	 |                     |          r ||          }n ||          }t          |t                    r ncH# t          $ r Y Tw xY wt          |t                    r.t          |t                    r|                     ||           |S t#          |          }|                     |           t%          |          t%          |          u r| j        rt'          j        ||           |S d| _        |S )z7
        Create a panel object from the value.
        FNr   T)mime)rz   )r{   )r   r%   r   rS   rU   rX   r  magicfrom_buffer	Exception	renderersr   appendr  r!   rV   r  r  r   r   _recursive_update)	r   rz   oldr	  rU   rX   r  r   object_panels	            r`   r   zChatMessage._create_panel  s'    eX&& 	"DNLe.// 	~HI"33HiHHOE88!--e$-??	"&"7"7y"I"Ixx    N''))/R	X&&&! 	) 	)H++H55 3#+8%#8#8#8LL#+8E??LlH55 E    #x(( Zs-C-C   U 333
!%==L&&&99\****t~*-c<@@@s%   4B 
B! B!AD  
D-,D-HTML | Imagec                   | j         }|s| j        r| j        d         }ddgi}t          |t                    rU|}|                    dg           |j        z   |d<   |                    dd           |j                            |           nlt          |t          t          f          s!t          |          dk    rt          |fi |}n/	 t          |fddd|}n# t          $ r t          |fi |}Y nw xY w|S )zI
        Render the avatar pane as some HTML text or Image pane.
        r   rq   r   #   )ro   rp   r'   )r   r2   r   r   r   rq   r   r   r   rT   r   r   r   
ValueError)r   r   avatar_paramsavatar_panes       r`   r   zChatMessage._render_avatar  sS     	"$) 	"Yq\F&
3fi(( 	< K!!-44'( -(   r" 555$$]3333FWe$455 
	<#f++:J:Jv7777KK<#"$R 3@   < < <"6;;];;< s   C C65C6c                Z   |                                  }t          | j        d                   }t          |          }t          |j        t
          t          f          s||ur|g| j        d d <   d S |j                                        }|d=  | j        d         j        j	        di | d S )Nr   r   r^   )
r   r   r   r   r#  r   r   r   valuesr   )r   event
new_avatarold_typenew_typer   s         r`   r   zChatMessage._update_avatar_pane,  s    ((**
q)**
##ei$	!233 	5xx7O7O!+DN111%,,..Fv*DN1#*44V44444r_   c                    dS )z4
        Internals will be updated inplace.
        Nr^   )r   r   
old_modelss      r`   _updatezChatMessage._update7  s      r_   c                    | j         }|                     | j        |          x| _         }||ur
|| j        d<   |                                  d S )N)r#  r   )r   r   r{   r   r   )r   r-  r#  news       r`   r   zChatMessage._update_object_pane<  sZ     #'#5#5dks#5#K#KKSc>>"%DQ##%%%%%r_   avatar_lookup)r   c                    | j         r!|                      | j                  | _        dS |                     | j                  | _        dS )z
        Update the avatar based on the user name.

        We do not use on_init here because if avatar is set,
        we don't want to override the provided avatar.

        However, if the user is updated, we want to update the avatar.
        N)r6  r2   r   r   r   s    r`   r   zChatMessage._update_avatarC  sE      	9,,TY77DKKK--di88DKKKr_   c                "   | j         }t          |t                    r|j        }nt          |t                    r|j        }t          |t                    r!| j        r|| j        _        d| j        _	        d S d| j        _        d| j        _	        d S )NTrc   F)
r   r   r    r{   r&   rz   rV   show_copy_iconr~   rn   )r   r$  s     r`   r   z"ChatMessage._update_chat_copy_iconR  s    )lL11 	.'.LLf-- 	.'-LlC(( 	0T-@ 	0(4D%*.D'''(*D%*/D'''r_   Nonec                z    | j                             |           t                                          |          S )z)
        Cleanup the exit stack.
        )r   _cleanupr   )r   r   r   s     r`   r<  zChatMessage._cleanup_  s3     	  &&&ww%%%r_   tokenc                   d}d}| }d}| j         }t          |t                    rt          |t                    r|}t	          |d          r|}d}|j        |         }d}n?t	          |d          r
d}|j         }n%t	          |d          r
d}|j        }n|	|}d}|dz  }t          |t                    zt          |t                    t          ||||z              dS )a  
        Updates the message with the new token traversing the object to
        allow updating nested objects. When traversing a nested Panel
        the last object that supports rendering strings is updated, e.g.
        in a layout of `Column(Markdown(...), Image(...))` the Markdown
        pane is updated.

        Arguments
        ---------
        token: str
          The token to stream to the text pane.
        Nr{   r  rz   r'   )r{   r   rV   r   r   r  rz   setattr)r   r=  iparent_panelr$  attrr   s          r`   streamzChatMessage.streamf  s    kS#&& 	*\9*M*M 	LsI&& " k!nh'' 	jg&& i)"#Q! S#&& 	*\9*M*M 	" 	dC%K00000r_   rz   dict | ChatMessage | Any
str | Noner   str | bytes | BytesIO | Nonec                .   i }t          |t                    r$|                    |           |r||d<   |r||d<   nGt          |t                    r-||t	          d          |j                                        }n||d<    | j        j        di | dS )a  
        Updates the message with a new value, user and avatar.

        Arguments
        ---------
        value : ChatMessage | dict | Any
            The message contents to send.
        user : str | None
            The user to send as; overrides the message message's user if provided.
        avatar : str | bytes | BytesIO | None
            The avatar to use; overrides the message message's avatar if provided.
        r2   r   NzfCannot set user or avatar when explicitly sending a ChatMessage. Set them directly on the ChatMessage.r{   r^   )r   r   r   rb   r(  r   r,  )r   rz   r2   r   updatess        r`   r   zChatMessage.update  s    $ eT"" 	&NN5!!! '"& +$*!{++ 	&6#5 K   k((**GG %GH
$$G$$$$$r_   c                <    |                      | j        ||          S )a  
        Format the object to a string.

        Arguments
        ---------
        obj : Any
            The object to format.
        prefix_with_viewable_label : bool
            Whether to include the name of the Viewable, or type
            of the viewable if no name is specified.
        prefix_with_container_label : bool
            Whether to include the name of the container, or type
            of the container if no name is specified.

        Returns
        -------
        str
            The serialized string.
        r   )r   r{   )r   r   r   s      r`   r   zChatMessage.serialize  s,    0 **K'A(C + 
 
 	
r_   r   )TT)r   r   r   r   r   r   r   rV   )r   rV   )r   r   )NNN)
rf   r*   r   r   r   r   r   r   r   r+   )r2   rV   r   rV   )r2   rV   r   r   )rU   r   rX   rV   )r   r%  )r   r:  )r=  rV   )NN)rz   rE  r2   rF  r   rG  )r   r   r   r   r   rV   )GrY   rZ   r[   r\   r   ClassSelectorrV   r   rT   r   r   Callabler6  r   rq   r   r   r   Integerr   	Parameterr{   rx   r)   ru   Daterr   Stringr   rs   Booleanr   r   r   r   r9  r   HookListr   r2   r   rj   r]   rk   r   r   r   r   r   propertyr   r   staticmethodr   r   r  r  r  r   r   r   r3  r   dependsr   r   r<  rD  r   r   __classcell__)r   s   @r`   rb   rb   {   s#         " !U S'5)4T [   F #EN4 65 6 6 6M
 %*n%5 ;3 4 4 4K !ej ?3 4 4 4O
 d9===IU_ 4R S S SF 
  4 5 5 5I )U(0A H0<AC C CN 
  D E E EI $u|G9PQQQ5< 3 	 	 	L  %- 37 8 8 8K d 14 5 5 5I #U]4 6< = = =N (%- ;2 3 3 3 #U]4 6- . . .N &e :- . . .  $   I 5?6 02 3 3 3D -5)J)J)J(KLKKKK  $H####     47F 7F 7Fr    ,0,0	1 1 1 1 1f           X 379=     0 0 0 \0C C C C #" #" #" #"J! ! !6 K K \K/ / / /b   <	5 	5 	5 	5  
& & & & U]?F$7779 9 8790 0 0& & & & & & &#1 #1 #1 #1P  /3	"% "% "% "% "%L ,0,0
 
 
 
 
 
 
 
 
r_   rb   )Qr\   
__future__r   r   r   
contextlibr   dataclassesr   	functoolsr   ior   tempfiler   textwrapr	   typingr
   r   r   r   r   r   r   zoneinfor   r   io.resourcesr   io.stater   layoutr   r   	pane.baser   r   r   r  
pane.imager   r   r   r   pane.markupr   r   r    r!   
pane.mediar"   r#   r$   viewabler%   widgets.baser&   iconr(   r)   bokeh.documentr*   bokeh.modelr+   pyviz_commsr,   rV   rT   r   
AvatarDict	USER_LOGOASSISTANT_LOGOSYSTEM_LOGO
ERROR_LOGO
GPT_3_LOGO
GPT_4_LOGOWOLFRAM_LOGOr   rS   rb   r^   r_   r`   <module>ru     s#    # " " " " "  				             ! ! ! ! ! !             ' ' ' ' ' '                               # # # # # #                       B B B B B B B B B B                       & % % % % % % % ! ! ! ! ! !       ! ! ! ! ! ! 1 1 1 1 1 1 1 1 !''''''!!!!!!      	sGUI-	.#v+
	
 E
L
 H-i- 	- 		-
 Y- i- I- ^- 	.- - 
>- ~- ~- ^-" k#-$ %-& Z'-* V+- -, F--. 
6/-0 V1-2 F3-4 
65-6 V7-: z;-< J=-> J?-@ ZA-B jC-D 6E-F &G-H I-J K-L IM-N &O- -P !Y- - -`        &P	
 P	
 P	
 P	
 P	
( P	
 P	
 P	
 P	
 P	
r_   