U
    Pe y                     @   s.  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mZmZmZmZmZmZmZ dd	lmZ dd
lmZ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$m%Z%m&Z& ddl'm(Z( ddl)m*Z* e$edZ+G dd de	Z,e-dkr*ddl.m/Z/ e,ddZ0e/e0 dS )uJ  
VKeyboard
=========

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

.. versionadded:: 1.0.8


VKeyboard is an onscreen keyboard for Kivy. Its operation is intended to be
transparent to the user. Using the widget directly is NOT recommended. Read the
section `Request keyboard`_ first.

Modes
-----

This virtual keyboard has a docked and free mode:

* docked mode (:attr:`VKeyboard.docked` = True)
  Generally used when only one person is using the computer, like a tablet or
  personal computer etc.
* free mode: (:attr:`VKeyboard.docked` = False)
  Mostly for multitouch surfaces. This mode allows multiple virtual
  keyboards to be used on the screen.

If the docked mode changes, you need to manually call
:meth:`VKeyboard.setup_mode` otherwise the change will have no impact.
During that call, the VKeyboard, implemented on top of a
:class:`~kivy.uix.scatter.Scatter`, will change the
behavior of the scatter and position the keyboard near the target (if target
and docked mode is set).


Layouts
-------

The virtual keyboard is able to load a custom layout. If you create a new
layout and put the JSON in :file:`<kivy_data_dir>/keyboards/<layoutid>.json`,
you can load it by setting :attr:`VKeyboard.layout` to your layoutid.

The JSON must be structured like this::

    {
        "title": "Title of your layout",
        "description": "Description of your layout",
        "cols": 15,
        "rows": 5,

        ...
    }

Then, you need to describe the keys in each row, for either a "normal",
"shift" or a "special" (added in version 1.9.0) mode. Keys for this row
data must be named `normal_<row>`, `shift_<row>` and `special_<row>`.
Replace `row` with the row number.
Inside each row, you will describe the key. A key is a 4 element list in
the format::

    [ <text displayed on the keyboard>, <text to put when the key is pressed>,
      <text that represents the keycode>, <size of cols> ]

Here are example keys::

    # f key
    ["f", "f", "f", 1]
    # capslock
    ["↹", "	", "tab", 1.5]

Finally, complete the JSON::

    {
        ...
        "normal_1": [
            ["`", "`", "`", 1],    ["1", "1", "1", 1],    ["2", "2", "2", 1],
            ["3", "3", "3", 1],    ["4", "4", "4", 1],    ["5", "5", "5", 1],
            ["6", "6", "6", 1],    ["7", "7", "7", 1],    ["8", "8", "8", 1],
            ["9", "9", "9", 1],    ["0", "0", "0", 1],    ["+", "+", "+", 1],
            ["=", "=", "=", 1],    ["⌫", null, "backspace", 2]
        ],

        "shift_1": [ ... ],
        "normal_2": [ ... ],
        "special_2": [ ... ],
        ...
    }


Request Keyboard
----------------

The instantiation of the virtual keyboard is controlled by the configuration.
Check `keyboard_mode` and `keyboard_layout` in the :doc:`api-kivy.config`.

If you intend to create a widget that requires a keyboard, do not use the
virtual keyboard directly, but prefer to use the best method available on
the platform. Check the :meth:`~kivy.core.window.WindowBase.request_keyboard`
method in the :doc:`api-kivy.core.window`.

If you want a specific layout when you request the keyboard, you should write
something like this (from 1.8.0, numeric.json can be in the same directory as
your main.py)::

    keyboard = Window.request_keyboard(
        self._keyboard_close, self)
    if keyboard.widget:
        vkeyboard = self._keyboard.widget
        vkeyboard.layout = 'numeric.json'

)	VKeyboard    )kivy_data_dir)Vector)Config)Scatter)Label)ObjectPropertyNumericPropertyStringPropertyBooleanPropertyDictPropertyOptionPropertyListPropertyColorProperty)Logger)ColorBorderImageCanvas)Image)resource_find)Clock)open)joinsplitextbasename)listdir)loadsZ	keyboardsc                       s  e Zd ZdZedddZedddZedZee	Z
ei ZedZeddddgZeddddgZed	Zed
d
d
d
gZedZed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dddgZedddZei Z edZ!edZ"edZ#ei Z$edZ%eddZ&dZ'dZ(dZ) fddZ*dd Z+dd Z,dd Z-dd Z.d d! Z/d"d# Z0d$d% Z1d&d' Z2d(d) Z3d*d+ Z4dNd,d-Z5d.d/ Z6d0d1 Z7d2d3 Z8d4d5 Z9d6d7 Z:d8d9 Z;d:d; Z<d<d= Z=d>d? Z>d@dA Z?dBdC Z@dDdE ZAdFdG ZBdHdI ZC fdJdKZD fdLdMZE  ZFS )Or   a  
    VKeyboard is an onscreen keyboard with multitouch support.
    Its layout is entirely customizable and you can switch between available
    layouts using a button in the bottom right of the widget.

    :Events:
        `on_key_down`: keycode, internal, modifiers
            Fired when the keyboard received a key down event (key press).
        `on_key_up`: keycode, internal, modifiers
            Fired when the keyboard received a key up event (key release).
    NT)Z	allownoneF皙?gQ?   g      4@   z5atlas://data/images/defaulttheme/vkeyboard_backgroundz>atlas://data/images/defaulttheme/vkeyboard_disabled_backgroundz5atlas://data/images/defaulttheme/vkeyboard_key_normalz3atlas://data/images/defaulttheme/vkeyboard_key_down      normal)r"   shiftspecial)optionszdata/fonts/DejaVuSans.ttf)on_key_down	on_key_upon_textinputc              	      sn  d|kr$d|krd | _ d|kr$d | _d|krHd|kr:d| _d|krHd| _d	|krVd
| _d|krdd| _d|krrd| _t| j	 }| _
t| j }| _t| j }| _| j}|d| j |d| |d| |d| |d| |d| tt| jf | |   | j}|std | jd kr8tdd| _n|   | 
  | j t | _t | _W 5 Q R X d S )NZ	size_hintsize_hint_xsize_hint_ysizewidthi  height   	scale_ming?	scale_maxg?dockedF
have_shifthave_capslockhave_speciallayout_pathlayoutz)VKeyboard: unable to load default layoutskivyZkeyboard_layout)r)   r*   r,   r-   r/   r0   r1   r   Zcreate_trigger_update_layout_modeZ_trigger_update_layout_mode_load_layouts_trigger_load_layouts_load_layoutZ_trigger_load_layoutfbind
setup_modesuperr   __init__available_layoutsr   criticalr6   r   getZcanvasr   background_key_layeractive_keys_layer)selfkwargslayout_modeZlayoutsr6   r<   r@   	__class__ 6/tmp/pip-unpacked-wheel-xzebddm3/kivy/uix/vkeyboard.pyr?   ^  sX    








zVKeyboard.__init__c                 C   s   |    d S N)refresh_keys)rE   instancevaluerJ   rJ   rK   on_disabled  s    zVKeyboard.on_disabledc                 G   s@   | j | jk}|rdnd}| jr"d}|| jkr<|| _| d d S )Nr#   r"   r$   F)r3   r2   r4   rG   refresh)rE   lmoderJ   rJ   rK   r8     s    
zVKeyboard._update_layout_modec                 G   s   | j jr|   | j   | j}| j}| jdd  dkrX||krXt| j}| || j |s`d S ||kr|dkrt	d|  d| _| 
d d S )N.jsonZqwertyzXVkeyboard: <%s> keyboard layout mentioned in conf file was not found, fallback on qwertyT)r:   Zis_triggeredr9   cancelr6   r@   r   _load_layout_fnr   errorrQ   )rE   largsrO   r@   fnrJ   rJ   rK   r;     s&    

zVKeyboard._load_layoutc                 G   s6   | j }t|D ]"}| t||tt|d  qd S )Nr   )r5   r   rW   r   r   r   )rE   rY   rO   rZ   rJ   rJ   rK   r9     s
    zVKeyboard._load_layoutsc              	   C   sP   | j }|dd  dkrd S t|ddd}| }t|}W 5 Q R X |||< d S )NrT   rU   rzutf-8)encoding)r@   r   readr   )rE   rZ   namer@   fdZjson_contentr6   rJ   rJ   rK   rW     s    zVKeyboard._load_layout_fnc                 G   s   | j r|   n|   dS )a  Call this method when you want to readjust the keyboard according to
        options: :attr:`docked` or not, with attached :attr:`target` or not:

        * If :attr:`docked` is True, it will call :meth:`setup_mode_dock`
        * If :attr:`docked` is False, it will call :meth:`setup_mode_free`

        Feel free to overload these methods to create new
        positioning behavior.
        N)r1   setup_mode_docksetup_mode_freerE   rY   rJ   rJ   rK   r=     s    

zVKeyboard.setup_modec                 G   sN   d| _ d| _d| _d| _|  }|jt| j }|| _d| _|j	| j
d dS )aV  Setup the keyboard in docked mode.

        Dock mode will reset the rotation, disable translation, rotation and
        scale. Scale and position will be automatically adjusted to attach the
        keyboard to the bottom of the screen.

        .. note::
            Don't call this method directly, use :meth:`setup_mode` instead.
        Fr   r   r   )Z	on_resizeN)do_translationdo_rotationdo_scalerotationget_parent_windowr,   floatscaleposbind_update_dock_mode)rE   rY   winrj   rJ   rJ   rK   r`     s    
zVKeyboard.setup_mode_dockc                 G   s    |j t| j  }|| _d| _d S )Nrc   )r,   ri   rj   rk   )rE   rn   rY   rj   rJ   rJ   rK   rm     s    zVKeyboard._update_dock_modec           	      C   s   d| _ d| _d| _| j}|s dS tdd}t|dd}t|dd| }|| | _t| | jd | j	}t||j
|j}|| }t| j| jd  | j| j	 t| | jd | j	 }||8 }| | _dS )a  Setup the keyboard in free mode.

        Free mode is designed to let the user control the position and
        orientation of the keyboard. The only real usage is for a multiuser
        environment, but you might found other ways to use it.
        If a :attr:`target` is set, it will place the vkeyboard under the
        target.

        .. note::
            Don't call this method directly, use :meth:`setup_mode` instead.
        TNr   r   g       @)rd   re   rf   targetr   Z	to_windowZanglerg   r,   r-   Zcenter_xyxZ	to_parentrk   )	rE   ro   abcZdposcposZdiffZdiff2rJ   rJ   rK   ra     s$    
zVKeyboard.setup_mode_freec                 C   s   d S rL   rJ   )rE   rJ   rJ   rK   change_layout&  s    zVKeyboard.change_layoutc                 C   s(   |    |r|   |   |   dS )ze(internal) Recreate the entire widget and graphics according to the
        selected layout.
        N)Zclear_widgetsrefresh_keys_hintrM   refresh_active_keys_layer)rE   forcerJ   rJ   rK   rQ   *  s
    zVKeyboard.refreshc           	   	   C   s   | j   | j}| j}t| j}t|ddj}| j H t| j	  |
 D ].\}}|d|  | \}}t|||| jd qHW 5 Q R X d S )NTZmipmapLINE_%dtexturerk   r+   border)rD   clearactive_keyslayout_geometryr   key_background_downr   r}   r   key_background_colorvaluesr   
key_border)	rE   r   r   
backgroundr}   line_nbindexrk   r+   rJ   rJ   rK   rx   4  s    


z#VKeyboard.refresh_active_keys_layerc                 C   s  | j | j }|d }|d }| j}| j\}}}}d| | }	d| | }
d| }d| }d| |	 }d| |
 }||f|d< ||
 }td|d D ]n}||8 }d| j|f }d| }g ||< |}|| D ]6}|| ||f|d	 | |fg ||d	 | 7 }qq|| _d S )
Ncolsrows      ?r   U_HINTr   %s_%dLINE_HINT_%d   )r@   r6   r   margin_hintrangerG   append)rE   r6   Zlayout_colslayout_rowsr   mtopmrightmbottommleftZel_hintZeh_hintZex_hintZey_hintuw_hintuh_hintZcurrent_y_hintr   Z	line_nameZ	line_hintZcurrent_x_hintkeyrJ   rJ   rK   rw   C  s4    zVKeyboard.refresh_keys_hintc                 C   s  | j | j }|d }| j}| j\}}| j\}}}}	|d \}
}td|d D ]}g  }|d| < |j}|d|  D ]}|d \}}|d \}}|| }|| }|| }|| }t||	 }t|| }t||	 | }t|| | }||f}||f}|||f qrqL|| _|   d S )Nr   r   r   r{   r   r   )	r@   r6   r   r+   
key_marginr   r   int	draw_keys)rE   r6   r   r   whZkmtopZkmrightZkmbottomZkmleftr   r   r   ZllgZ
llg_appendr   x_hinty_hintZw_hintZh_hintZkxkykwZkhrk   r+   rJ   rJ   rK   rM   i  s2    
zVKeyboard.refresh_keysc              	   C   sr  | j | j }|d }| j}| j}t| jr.| jn| j}t|ddj	}| j
  | j
" t| j  t|| j| jd W 5 Q R X t| jr| jn| j}t|ddj	}| j
L t| j  td|d D ],}|d|  D ]\}	}
t||	|
| jd qqW 5 Q R X td|d D ]f}d}|d|  D ]N\}	}
||d	 t|  | d }t|| j|	|
| jd
}| | |d7 }qqd S )Nr   Trz   )r}   r+   r~   r   r{   r|   r   _)text	font_sizerk   r+   	font_name)r@   r6   r   rG   r   disabledbackground_disabledr   r   r}   rC   r   r   background_colorr   r+   background_borderZkey_background_disabled_normalkey_background_normalr   r   r   strr   r   r   Z
add_widget)rE   r6   r   r   rG   r   r}   Z
key_normalr   rk   r+   Zkey_nbr   zrJ   rJ   rK   r     sN    



 
zVKeyboard.draw_keysc                 G   s   d S rL   rJ   rb   rJ   rJ   rK   r&     s    zVKeyboard.on_key_downc                 G   s   d S rL   rJ   rb   rJ   rJ   rK   r'     s    zVKeyboard.on_key_upc                 G   s   d S rL   rJ   rb   rJ   rJ   rK   r(     s    zVKeyboard.on_textinputc                 C   s  | j \}}|| }| j}| j| j }|d }| j\}	}
}}|||	 |  }|| }|||  }|t||  }||krz|}|dk rd}d}d}|d|  D ]B}||d d kr||d d |d d  k r|} qq|d7 }q|dkrd S |d| j|f  | }|||fgS )Nr   r    r   r   r   )r+   r   r@   r6   r   r   rG   )rE   rq   rp   r   r   r   r   r6   r   r   r   r   r   Ze_heightZline_heightr   	key_indexZcurrent_key_indexr   rJ   rJ   rK   get_key_at_pos  s2    
,
zVKeyboard.get_key_at_posc           	      C   sR   | j \}}}}|| j }|| j }||krN|d| k rN||krN|d| k rNdS dS )zcDo a collision test, and return True if the (x, y) is inside the
        vkeyboard margin.
        r   FT)r   r,   r-   )	rE   rq   rp   r   r   r   r   r   r   rJ   rJ   rK   collide_margin  s    


zVKeyboard.collide_marginc                 C   s>  |sd S | j |j \}}| ||}|s,d S |d }|\}}}}	|d \}
}i  }|j| j< ||d< |j}|d k	r|dkr| jd k	r| j  d | _d | _|dkr| j | _d}n0|dkrd| _	n |d	krd| _
n|d
kr|   |}|  }|  jjdkr|r| d| n| d||| |d | j|< |   d S )Nr   r   r   )capslockr#   r6   r$   r   r#   Tr$   r6   zkivy.core.window.window_sdl2r(   r&   )to_localrk   r   uduid_start_repeat_key_evrV   repeat_touchr3   r2   r4   rv   _get_modifiersrh   rI   
__module__dispatchr   rx   )rE   touchrq   rp   r   key_datadisplayed_charinternalspecial_charr+   r   r   r   r   	b_keycodeb_modifiersrJ   rJ   rK   process_key_on  sL    



zVKeyboard.process_key_onc                 C   s   |j }| j |jkrd S |j| j  d \}}|\}}}}|}	|  }
| d|	||
 |dkr^d}|| jkr| j|d  |dkrd| _n|dkrd| _|dkr| jr|| jd< | 	  d S )Nr   r'   r   r   r#   Fr$   )
r   r   r   r   r   popr2   r4   r3   rx   )rE   r   r   r   r   r   r   r   r+   r   r   rJ   rJ   rK   process_key_up  s&    

zVKeyboard.process_key_upc                 C   s(   g }| j r|d | jr$|d |S )Nr#   r   )r2   r   r3   )rE   retrJ   rJ   rK   r   9  s    

zVKeyboard._get_modifiersc                 G   s   t | jd| _d S )Nr   )r   Zschedule_interval_repeat_key_repeat_key_evrE   rF   rJ   rJ   rK   _start_repeat_keyA  s    zVKeyboard._start_repeat_keyc                 G   s   |  | j d S rL   )r   r   r   rJ   rJ   rK   r   D  s    zVKeyboard._repeat_keyc                    s   |j \}}| ||sd S | jr$dS | ||\}}| ||sz| jd krZt| jd| _	|| _| 
| |j| dd ntt| | dS )NTg      ?)Z	exclusive)rk   Zcollide_pointr   r   r   r   r   Zschedule_oncer   r   r   Zgrabr>   r   on_touch_down)rE   r   rq   rp   rH   rJ   rK   r   G  s"    

 
zVKeyboard.on_touch_downc                    sh   |j | krX| | | jd k	r.| j  d | _|| jkrX| jd k	rR| j  d | _d | _tt| |S rL   )	Zgrab_currentr   r   rV   r   r   r>   r   on_touch_up)rE   r   rH   rJ   rK   r   \  s    






zVKeyboard.on_touch_up)F)G__name__r   __qualname____doc__r   ro   callbackr
   r6   default_layout_pathr5   r   r@   r   r1   r   r   r   r	   r   r   r   r   r   r   r   Zkey_disabled_background_normalr   r   r   r   rG   r   r3   r2   r4   r   r   r   r   r   Z
__events__r?   rP   r8   r;   r9   rW   r=   r`   rm   ra   rv   rQ   rx   rw   rM   r   r&   r'   r(   r   r   r   r   r   r   r   r   r   __classcell__rJ   rJ   rH   rK   r      s   	


	

:
	/

& +%0r   __main__)runTouchAppZazerty)r6   N)1r   __all__r7   r   Zkivy.vectorr   Zkivy.configr   Zkivy.uix.scatterr   Zkivy.uix.labelr   Zkivy.propertiesr   r	   r
   r   r   r   r   r   Zkivy.loggerr   Zkivy.graphicsr   r   r   Zkivy.core.imager   Zkivy.resourcesr   Z
kivy.clockr   ior   os.pathr   r   r   osr   jsonr   r   r   r   Z	kivy.baser   ZvkrJ   rJ   rJ   rK   <module>   s6   o(
     i

