
    fږ              
          d Z ddlmZmZmZ ddlmZ ddlZddlm	Z	m
Z
mZmZ ddlmZ ddlZ ej                   d      ZddlmZ  e       Z e ed	d
            \
  ZZZZZZZZZZ  e ed            \  Z!Z"Z#e!e"e#dZ$ G d d      Z% G d d      Z& G d d      Z' G d de      Z( G d de(      Z) G d de)      Z* G d d      Z+ G d d      Z,y)z
KeyCommon hosts the abstract classes for the various types of Keys.
UI-specific keys should be defined in KeyGtk or KeyKDE files.
    )divisionprint_functionunicode_literals)piN)RectLABEL_MODIFIERS	Modifierspolygon_to_rounded_path)
LayoutItem	KeyCommon)Config         )zsingle-strokezdelayed-strokezdouble-strokec            
           e Zd ZdZ e ed            \	  ZZZZ	Z
ZZZZeeee	e
eeeed	Zed        Zed        Zed        Zed        Zed        Zed	        Zed
        Zy)StickyBehaviorz enum for sticky key behaviors 	   )	cycledblclicklatchlockzlatch-lock-nocyclezdblclick-nocyclezlatch-nocyclezlock-nocyclepushc                 (    t         j                  |    S )z Raises KeyError r   values)	str_values    3/usr/lib/python3/dist-packages/Onboard/KeyCommon.pyfrom_stringzStickyBehavior.from_stringb   s     $$Y//    c                 B    | t         j                  j                         v S Nr   behaviors    r   is_validzStickyBehavior.is_validg   s    >0077999r   c                     | t         j                  t         j                  t         j                  t         j                  t         j
                  t         j                  fv S )z
        Can sticky key enter latched state?
        Latched keys are automatically released when a
        non-sticky key is pressed.
        )r   CYCLEDOUBLE_CLICK
LATCH_ONLYLATCH_LOCK_NOCYCLEDOUBLE_CLICK_NOCYCLELATCH_NOCYCLEr"   s    r   	can_latchzStickyBehavior.can_latchk   sK     N00*77*55*==*??*88: : 	:r   c                 Z    t         j                  |       xs t         j                  |       S r!   )r   can_lock_on_single_clickcan_lock_on_double_clickr"   s    r   can_lockzStickyBehavior.can_locky   s*    66x@ A66x@	Ar   c                     | t         j                  t         j                  t         j                  t         j                  fv S )zr
        Can sticky key enter locked state?
        Locked keys stay active until they are pressed again.
        )r   r&   	LOCK_ONLYr)   LOCK_NOCYCLEr"   s    r   r.   z'StickyBehavior.can_lock_on_single_click~   s9     N00*44*==*779 9 	9r   c                 R    | t         j                  k(  xs | t         j                  k(  S )z
        Can sticky key enter locked state on double click?
        Locked keys stay active until they are pressed again.
        )r   r'   r*   r"   s    r   r/   z'StickyBehavior.can_lock_on_double_click   s*     >666 ?>>>>	?r   c                     | t         j                  t         j                  t         j                  t         j                  fv S )z
        Can sticky key return to normal state?
        Latched keys are still automatically released when a
        non-sticky key is pressed.
        )r   r&   r'   r(   r2   r"   s    r   	can_cyclezStickyBehavior.can_cycle   s9     N00*77*55*446 6 	6r   N)__name__
__module____qualname____doc__tupleranger&   r'   r(   r2   r)   r*   r+   r3   PUSH_BUTTONr   staticmethodr   r$   r,   r0   r.   r/   r6    r   r   r   r   I   s    ) 	eAh
 &+%1%/%.%7%9%2%1%0	F 0 0 : : : : A A 9 9 ? ? 	6 	6r   r   c                   4    e Zd ZdZ e ed            \  ZZZy)LODz enum for level of detail r   N)	r7   r8   r9   r:   r;   r<   MINIMALREDUCEDFULLr?   r   r   rA   rA      s     $
 	eAh	r   rA   c                       e Zd ZdZdZy)	ImageSlotr   r   N)r7   r8   r9   NORMALACTIVEr?   r   r   rF   rF      s    FFr   rF   c                      e Zd ZdZdZdZdZdZdZdZ	dZ
dZdZdZdZdZdZdZdZdZdZdZdZdZdZej4                  Zej8                  Zej<                  ZdZ dZ!d Z"d	 Z#d%d
Z$d Z%d Z&d Z'd Z(d Z)d Z*d&dZ+e,d        Z-e,d        Z.e,d        Z/d%dZ0d Z1d Z2d Z3d Z4d Z5d Z6d Z7d Z8d Z9d Z:d  Z;d! Z<d" Z=d# Z>d$ Z?y)'r   z]
    library-independent key class. Specific rendering options
    are stored elsewhere.
    NFr    r   Tc                 .    t        j                  |        y r!   )r   __init__selfs    r   rL   zKeyCommon.__init__  s    D!r   c                    t         j                  }| j                  }|dx| _        | _        y |j                  |      }||t        z  }|j                  |      }d }|c||z  r|| z  }n||z  }|j                  |      }||t        z  }|j                  |      }|#|j                         |j                         k(  rd }||t         j                  z  r1|t         j                  z  r
d|v r|d   }nWd|v r|d   }nMd|v rI|d   }nC|t         j                  z  r
d|v r|d   }n&|t         j                  z  rd|v r|d   }n	d|v r|d   }||j                  d      }|d}|| _
        || _        || _        |j                  d      | _        y )NrJ      r         r   0x)r	   SHIFTlabelslabelsecondary_labelgetr   upperALTGRCAPSmod_mask
startswithignore_group)rN   r\   rT   rU   rV   maskrW   s          r   configure_labelzKeyCommon.configure_label  s   >022DJ- 

8$=o-DJJt$E }%5&(%'$jj.O&o-"(**T"2 #*$$&%++-7"&=)//)ioo-#-"3KE&["1IE&["1IEIOO+vsINN*;"1IE&["1IE=JJqME=E 
. ",,T2r   c                     t               r!   )NotImplementedErrorrN   contexts     r   
draw_labelzKeyCommon.draw_labelF  s    !##r   c                 4    || _         | j                  d       y )Nr   )rU   r`   )rN   rU   s     r   
set_labelszKeyCommon.set_labelsI  s    Qr   c                     | j                   S r!   )rV   rM   s    r   	get_labelzKeyCommon.get_labelM      zzr   c                     | j                   S r!   )rW   rM   s    r   get_secondary_labelzKeyCommon.get_secondary_labelP  s    ###r   c                     | j                   d uS r!   )typerM   s    r   	is_activezKeyCommon.is_activeS  s    99$$r   c                      yNrJ   r?   rM   s    r   get_idzKeyCommon.get_idV      r   c                      yrq   r?   rM   s    r   
get_svg_idzKeyCommon.get_svg_idY  rs   r   c                     | j                  |      \  | _        | _        |r|| _        |s| j                  | _        y || _        y r!   )parse_idtheme_ididsvg_id)rN   ry   rx   rz   s       r   set_idzKeyCommon.set_id\  s6    !%r!2tw$DM%+dggr   c                 6    | }| j                  d      d   }||fS )ah  
        The theme id has the form <id>.<arbitrary identifier>, where
        the identifier should be a description of the location of
        the key relative to its surroundings, e.g. 'DELE.next-to-backspace'.
        Don't use layout names or layer ids for the theme id, they lose
        their meaning when layouts are copied or renamed by users.
        .r   )split)valuerx   ry   s      r   rw   zKeyCommon.parse_idb  s&     [[a |r   c                 b    | j                  d      }t        |      dk(  r|d   dfS |d   |d   fS )zV
        Simple split in prefix (id) before the dot and suffix after the dot.
        r}   r   r   rJ   )r~   len)rx   
componentss     r   split_theme_idzKeyCommon.split_theme_ido  s@    
 ^^C(
z?aa="$$!}jm++r   c                     |r| dz   |z   S | S )Nr}   r?   )prefixpostfixs     r   build_theme_idzKeyCommon.build_theme_idy  s    C<'))r   c                 |    || j                   }|}| j                  j                  d      dd  }|r|d|d   z   z  }|S )Nr}   r   r   )ry   rx   r~   )rN   r   rx   compss       r   get_similar_theme_idzKeyCommon.get_similar_theme_id  sJ    >WWF##C(,eAh&Hr   c                 8    | j                   j                  d      S )Nlayerry   r]   rM   s    r   is_layer_buttonzKeyCommon.is_layer_button  s    ww!!'**r   c                 8    | j                   j                  d      S )N
predictionr   rM   s    r   is_prediction_keyzKeyCommon.is_prediction_key  s    ww!!,//r   c                 X    | j                   j                  d      xs | j                   dv S )N
correction)zexpand-correctionsr   rM   s    r   is_correction_keyzKeyCommon.is_correction_key  s+    ww!!,/ 1ww00	1r   c                 F    | j                         xs | j                         S r!   )r   r   rM   s    r   is_word_suggestionzKeyCommon.is_word_suggestion  s    %%'C4+A+A+CCr   c                 ,    t        | j                        S )z
        Modifiers are all latchable/lockable non-button keys:
        "LWIN", "RTSH", "LFSH", "RALT", "LALT",
        "RCTL", "LCTL", "CAPS", "NMLK"
        )boolmodifierrM   s    r   is_modifierzKeyCommon.is_modifier  s     DMM""r   c                     | j                   dv S )N)singleclicksecondaryclickmiddleclickdoubleclick	dragclickry   rM   s    r   is_click_type_keyzKeyCommon.is_click_type_key  s    ww ( ( 	(r   c                 (    | j                   t        k(  S r!   )rn   BUTTON_TYPErM   s    r   	is_buttonzKeyCommon.is_button  s    yyK''r   c                 p    | j                   xr) | j                  xs | j                  xs | j                   S r!   )pressedactivelockedscannedrM   s    r   is_pressed_onlyzKeyCommon.is_pressed_only  s6    || 3T[[ &2%)[[&2%)\\!3 	3r   c                    | j                         sq| j                  t        t        t        t
        t        t        t        fv r@| j                  }|j                  d      r|dd  j                         s|t        g d      vryy)NFr   )LEFTRGHTUPDOWNHOMEENDPGUPPGDNINSESCMENUPrntPauseScrollTF)r   rn   KEYCODE_TYPEKEYSYM_TYPE	CHAR_TYPEKEYPRESS_NAME_TYPE
MACRO_TYPE	WORD_TYPECORRECTION_TYPEry   r]   isdigitsetrN   ry   s     r   is_text_changingzKeyCommon.is_text_changing  su    !yy\(&/'&,. . BMM#&2ab6>>+; 9 : : r   c                 2    | j                   }|dk(  xs |dk(  S )NRTRNKPENr   r   s     r   	is_returnzKeyCommon.is_return  s#    WWf f	r   c                 2    | j                   }|dk(  xs |dk(  S )NSPCETABr   r   s     r   is_separatorzKeyCommon.is_separator  s#    WWf e	r   c                 |    | j                         xs+ | j                         xs | j                  t        g d      v S )z1 Should this key cancel pending word separators? )r   r   DELEr   r   r   r   r   r   r   r   r   r   r   r   r   r   )r   r   ry   r   rM   s    r   is_separator_cancellingz!KeyCommon.is_separator_cancelling  s?    &&( < <3 
 ; 
< 
<	=r   c                 V    | j                         sJ t        | j                  dd        S )N   )r   intry   rM   s    r   get_layer_indexzKeyCommon.get_layer_index  s)    ##%&%47712;r   c                 R    | j                   r| j                  | j                         S y r!   )popup_idfind_sublayoutrM   s    r   get_popup_layoutzKeyCommon.get_popup_layout  s!    ==&&t}}55r   c                     | j                          xr8 | j                          xr% | j                  d uxr t        | j                        S r!   )r   r   rn   r   label_popuprM   s    r   can_show_label_popupzKeyCommon.can_show_label_popup  sP    ##%% &''))&99$& D$$%	&r   r!   )NN)@r7   r8   r9   r:   rx   rz   r   actionrn   codestickysticky_behaviorr   prelightr   r   r   r   	activated	font_sizerU   rV   r\   rW   image_filenamesconfigDEFAULT_LABEL_X_ALIGNlabel_x_alignDEFAULT_LABEL_Y_ALIGNlabel_y_alignLABEL_MARGINlabel_margintooltipr   rL   r`   re   rg   ri   rl   ro   rr   ru   r{   r>   rw   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r?   r   r   r   r      s    H F H F D D F O H H G F F G I I F E H O O 00M 00M &&L G K">3@$ $%8 
 
 , ,  
+01D#((3
$

=  
&r   c                   $   e Zd ZdZdZdZdZdZdZdZ	dZ
dZd Zd Zd Zd Zd(dZd)d	Zd)d
Zd)dZd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Z d Z!d Z"d(dZ#e$d(d       Z%d Z&d(dZ'd Z(d  Z)d! Z*d" Z+d# Z,d$ Z-d(d%Z.d(d&Z/d' Z0y)*RectKeyCommonz4 An abstract class for rectangular keyboard buttons NTc                     t         j                  |        || _        i | _        ||| j
                  _        y t	               | j
                  _        y r!   )r   rL   ry   colorsr   rd   log_rect)rN   ry   border_rects      r   rL   zRectKeyCommon.__init__  sC    4 '2': !,@D 	r   c                     | j                   S r!   r   rM   s    r   rr   zRectKeyCommon.get_id  s    wwr   c                     | j                   S r!   )rz   rM   s    r   ru   zRectKeyCommon.get_svg_id	  s    {{r   c                     i }| j                   |d<   | j                  |d<   | j                  |d<   | j                  |d<   | j                  |d<   | j
                  |d<   |S )Nr   r   r   r   r   	sensitive)r   r   r   r   r   r   )rN   states     r   	get_statezRectKeyCommon.get_state  s^    !]]j!\\i![[h![[h!\\i!^^kr   c                      y r!   r?   rc   s     r   drawzRectKeyCommon.draw  s    r   c                     | j                   }| j                  }|sd|z
  }||d   |d   z
  z  }||d   |d   z
  z  }||fS - returns x- and yoffset of the aligned label       ?r   r   )r   r   rN   
label_sizekey_sizeltrr   r   xoffsetyoffsets           r   align_labelzRectKeyCommon.align_label  s^    ****-/M8A;A#>?8A;A#>?r   c                 X    d}d}|sd|z
  }||d   |d   z
  z  }||d   |d   z
  z  }||fS )r   g
ףp=
?        r   r   r   r?   r   s           r   align_secondary_labelz#RectKeyCommon.align_secondary_label#  sR    -/M8A;A#>?8A;A#>?r   c                 l    d}| j                   }|sd|z
  }||d   |d   z
  z  }||d   |d   z
  z  }||fS r   )r   r   s           r   align_popup_indicatorz#RectKeyCommon.align_popup_indicator-  sX    **-/M8A;A#>?8A;A#>?r   c                 f    | j                   | j                   S t        j                  j                  S r!   )styler   theme_settings	key_stylerM   s    r   	get_stylezRectKeyCommon.get_style7  s(    zz!::$$...r   c                 <    t         j                  j                  dz  S N      Y@)r   r  key_stroke_widthrM   s    r   get_stroke_widthzRectKeyCommon.get_stroke_width<  s    $$55==r   c                 <    t         j                  j                  dz  S r  )r   r  key_stroke_gradientrM   s    r   get_stroke_gradientz!RectKeyCommon.get_stroke_gradient?  s    $$885@@r   c                 J    t         j                  j                  t        z  dz  S )Ng     f@)r   r  key_gradient_directionr   rM   s    r   get_light_directionz!RectKeyCommon.get_light_directionB  s    $$;;b@5HHr   c                 $    | j                  d      S )Nfill
_get_colorrM   s    r   get_fill_colorzRectKeyCommon.get_fill_colorE  s    v&&r   c                 $    | j                  d      S )Nstroker  rM   s    r   get_stroke_colorzRectKeyCommon.get_stroke_colorH  s    x((r   c                 $    | j                  d      S )NrV   r  rM   s    r   get_label_colorzRectKeyCommon.get_label_colorK  s    w''r   c                 $    | j                  d      S )Nzsecondary-labelr  rM   s    r   get_secondary_label_colorz'RectKeyCommon.get_secondary_label_colorN  s    011r   c                 $    | j                  d      S )Nzdwell-progressr  rM   s    r   get_dwell_progress_colorz&RectKeyCommon.get_dwell_progress_colorQ  s    /00r   c                 v    | j                         j                  d      }| j                  j                  |      S )N      ?)get_label_rectinflaterd   log_to_canvas_rectrN   rects     r   get_dwell_progress_canvas_rectz,RectKeyCommon.get_dwell_progress_canvas_rectT  s0    ""$,,S1||..t44r   c                 V   || j                   | j                  | j                  | j                  | j                  | j
                  f}| j                  j                  |      }|sF| j                  r| j                  j                  | |      }n|dk(  rg d}ng d}|| j                  |<   |S )NrV   )r  r  r  r   )r   r   r   r   )
r   r   r   r   r   r   r   rX   color_schemeget_key_rgba)rN   element	color_keyrgbas       r   r  zRectKeyCommon._get_colorX  s    dmmT\\"kk4;;"nndll<	 {{y)  ((55dGDG#++%)DKK	"r   c                 ,    t        j                  |       S )zA Get bounding box of the key at 100% size in logical coordinates )r   get_rectrM   s    r   get_fullsize_rectzRectKeyCommon.get_fullsize_rectg  s    ""4((r   c                 T    | j                   j                  | j                               S )z@ Get bounding box of the key at 100% size in canvas coordinates )rd   r-  r9  rM   s    r   get_canvas_fullsize_rectz&RectKeyCommon.get_canvas_fullsize_rectk  s     ||..t/E/E/GHHr   c                 D    | j                         }| j                  |      S )z
        Get bounding box in logical coordinates.
        Just the relatively static unpressed rect withough fake key action.
        )r9  _apply_key_sizer.  s     r   get_unpressed_rectz RectKeyCommon.get_unpressed_recto  s#    
 %%'##D))r   c                 "    | j                         S )z) Get bounding box in logical coordinates )get_sized_rectrM   s    r   r8  zRectKeyCommon.get_rectw  s    ""$$r   c                 0   | j                         }| j                  ri| j                         \  }}}}|xj                  |z  c_        |xj                  |z  c_        |xj
                  |z  c_        |xj                  |z  c_        | j                  ||      S r!   )r9  r   get_pressed_deltasxywhr=  )rN   
horizontalr/  dxdydwdhs          r   r@  zRectKeyCommon.get_sized_rect{  sv    %%' <<!446NBBFFbLFFFbLFFFbLFFFbLF##D*55r   c                     dt         j                  j                  dz  z
  dz  }| j                  |z  }| j                  |z  }|| j                  | j                  k  }|r|}n|}| j                  ||      S )z shrink keys to key_size r   r  r*  )r   r  r  rE  rF  deflate)r/  rG  scalebxbys        r   r=  zRectKeyCommon._apply_key_size  su     v,,55==DVVe^VVe^$&&JB B||B##r   c                 X    | j                         }|dk(  rd}n
|dk(  rd}nd}|d|z  ddfS )zq
        dx, dy, dw, dh for fake physical key action of pressed keys.
        Logical coordinate system.
        gradientg?dishg?r  rQ   )r  )rN   r  ks      r   rB  z RectKeyCommon.get_pressed_deltas  sB    
 NN$	
"A& AA!A#sCr   c                 P   || j                         }| j                         }|dk(  rg| j                         }t        j                  \  }}||z  }||z  }|j                  ||      }|xj                  t        j                  |z  z  c_        |S  |j
                  | j                   S )z# Label area in logical coordinates rS  )	r8  r  r  r   DISH_KEY_BORDERrM  rD  DISH_KEY_Y_OFFSETr   )rN   r/  r  stroke_widthborder_xborder_ys         r   r+  zRectKeyCommon.get_label_rect  s    <==?D F? 113L!'!7!7Hh$H$H<<(3DFFf..==FK4<<!2!233r   c                 X    | j                         }| j                  j                  |      S r!   )r+  rd   r-  )rN   r   s     r   get_canvas_label_rectz#RectKeyCommon.get_canvas_label_rect  s%    &&(||..x88r   c                 6    | j                   j                         S )z8 Original path including border in logical coordinates. )geometryget_full_size_pathrM   s    r   get_border_pathzRectKeyCommon.get_border_path  s    }}//11r   c                 h    | j                         \  }}}}| j                  j                  ||||      S )zx
        Path of the key geometry in logical coordinates.
        Key size and fake press movement are applied.
        )get_key_offset_sizer^  get_transformed_path)rN   offset_xoffset_ysize_xsize_ys        r   get_pathzRectKeyCommon.get_path  s=    
 .2-E-E-G*(FF}}11(H28&B 	Br   c                 X    | j                         }| j                  j                  |      S r!   )r`  rd   log_to_canvas_pathrN   paths     r   get_canvas_border_pathz$RectKeyCommon.get_canvas_border_path  s%    ##%||..t44r   c                 X    | j                         }| j                  j                  |      S r!   )rh  rd   rj  rk  s     r   get_canvas_pathzRectKeyCommon.get_canvas_path  s"    }}||..t44r   c                 "    | j                         S r!   )rm  rM   s    r   get_hit_pathzRectKeyCommon.get_hit_path  s    **,,r   c                     | j                   | j                   S |s;| j                  r| j                         j                         }n| j	                         }t        |j                  |j                        dz  S )z> Max size of the rounded corner areas in logical coordinates. r*  )chamfer_sizer^  r`  
get_boundsr8  minrE  rF  r.  s     r   get_chamfer_sizezRectKeyCommon.get_chamfer_size  s`      ($$$}}++-88:}}466466"S((r   c                    t         j                  j                  dz  x}}dx}}| j                  rS| j	                         \  }}}}|dk7  s|dk7  r4|| j
                  }|j                  ||f      \  }}||dz  z  }||dz  z  }||||fS )Nr  r  r*  )r   r  r  r   rB  r^  scale_log_to_size)rN   r^  rf  rg  rd  re  rJ  rK  s           r   rb  z!RectKeyCommon.get_key_offset_size  s     //885@@!!8<<)-)@)@)B&HhBSyB#I##}}H!33RH=B"s(""s("6611r   c                     |j                  ||||      }| j                  j                  |      }	t        |	j	                               }
|
D cg c]  }t        |||       c}}|
|fS c c}w r!   )rc  rd   rj  listiter_polygonsr
   )rN   r^  rd  re  rf  rg  
radius_pctrs  rl  canvas_pathpolygonsppolygon_pathss                r   get_canvas_polygonsz!RectKeyCommon.get_canvas_polygons  sy     ,,XxPll55d;1134  %Q
LA  	 &&s   A(r!   )T)1r7   r8   r9   r:   r^  rs  r  	show_faceshow_border
show_label
show_imageshow_activerL   rr   ru   r   r   r  r  r
  r  r  r  r  r  r"  r$  r&  r(  r0  r  r9  r;  r>  r8  r@  r>   r=  rB  r+  r\  r`  rh  rm  ro  rq  rv  rb  r  r?   r   r   r   r     s    > H L E IKJJ KG   /
>AI')(215)I*%6 $ $$ 4 92B55-	)2	'r   r   c                   (    e Zd ZdZdZdZdZd Zd Zy)InputlineKeyCommonz2 An abstract class for InputLine keyboard buttons rJ   Nr   c                 2    t         j                  | ||       y r!   )r   rL   )rN   namer   s      r   rL   zInputlineKeyCommon.__init__  s    tT;7r   c                      yrq   r?   rM   s    r   ri   zInputlineKeyCommon.get_label  rs   r   )	r7   r8   r9   r:   line
word_infoscursorrL   ri   r?   r   r   r  r    s    <DJF8r   r  c                   b    e Zd ZdZdZdZed        Zed        Z	 	 ddZ	d Z
d Zd Zd	 Zd
 Zy)KeyGeometrya!  
    Full description of a key's shape.

    This class generates path variants for a given key_size by path
    interpolation. This allows for key_size dependent shape changes,
    controlled solely by a SVG layout file. See 'Return' key in
    'Full Keyboard' layout for an example.
    Nc                 2   t        |       dk\  sJ | d   }d }t        |       dk\  r| d   }t        |j                        t        |j                        k7  rAt        dj                  t        |j                        t        |j                                    t	        t        |j                              D ]G  }|j                  |   \  }}|j                  |   \  }}||k7  s-t        dj                  |||             t               }||_        ||_        |S )Nr   r   rQ   z=paths to interpolate differ in number of segments ({} vs. {})zPpaths to interpolate have different operations at segment {} (op. {} vs. op. {}))r   segments
ValueErrorformatr<   r  path0path1)	pathsr  r  iop0coords0op1coords1r^  s	            r   
from_pathszKeyGeometry.from_paths  s   5zQau:?!HE 5>>"c%..&99 "ENN 3S5HIK K 3u~~./ 2$~~a0W$~~a0W#:$<#VAsC02 2	2 =r   c                 N    t               }t        j                  |       |_        |S r!   )r  KeyPath	from_rectr  )r/  r^  s     r   r  zKeyGeometry.from_rect5  s     = **40r   c                    | j                   }| j                  }|r%d|z
  dz  }d|z
  dz  }|j                  |||||      S | j                         }	| j	                         }
|
j                  |dz
  |	j                  |
j                  z
  z  |dz
  |	j                  |
j                  z
  z        }|xj                  |z  c_        |xj                  |z  c_	        |j                  |      S )zg
        Everything in the logical coordinate system.
        size: 1.0 => path0, 0.5 => path1
        r          @r*  )r  r  linintget_full_size_boundsget_half_size_boundsr,  rE  rF  rC  rD  fit_in_rect)rN   rd  re  rf  rg  r  r  pos_xpos_yr0r1r/  s               r   rc  z KeyGeometry.get_transformed_path;  s     



Z3&EZ3&E<<ueXxHH**,B**,B::v|rtt<%|rtt<>DFFhFFFhF$$T**r   c                     | j                   S r!   )r  rM   s    r   r_  zKeyGeometry.get_full_size_pathP  rj   r   c                 6    | j                   j                         S )z+
        Bounding box at size 1.0.
        )r  rt  rM   s    r   r  z KeyGeometry.get_full_size_boundsS  s     zz$$&&r   c                    | j                   }|r|j                         }|S | j                  j                         }|j                  |j                  k  r|j                  dz  x}}n|j                  dz  x}}|j                  ||      }|S )z+
        Bounding box at size 0.5.
        g      ?)r  rt  r  rF  rE  rM  )rN   r  r/  rH  rI  s        r   r  z KeyGeometry.get_half_size_boundsY  s     

##%D  ::((*Dvv&&4-'R&&4-'R<<B'Dr   c                     | j                         }| j                         }|j                  |j                  z
  dz  }|j                  |j                  z
  dz  }|d   |z  |d   |z  fS z+ Scale from logical distances to key size. r  r   r   r  r  rF  rE  rN   vr  r  log_hlog_ws         r   rx  zKeyGeometry.scale_log_to_sizei  j    &&(&&(##!u!u 	r   c                     | j                         }| j                         }|j                  |j                  z
  dz  }|j                  |j                  z
  dz  }|d   |z  |d   |z  fS r  r  r  s         r   scale_size_to_logzKeyGeometry.scale_size_to_logr  r  r   )r  r  r   r   )r7   r8   r9   r:   r  r  r>   r  r  rc  r_  r  r  rx  r  r?   r   r   r  r  	  s`     EE <  
 ?B47+*' r   r  c                       e Zd ZdZ ed      \  ZZZdZdZ	d Z
ed        Zed        Z ej                  d      Zd	 Zd
 Zd Zed        Zd Zd ZddZd Z	 	 ddZd Zd Zed        Zy)r  z
    Cairo-friendly path description for non-rectangular keys.
    Can handle straight line-loops/polygons, but not arcs and splines.
    r   )r  r  Nc                     g | _         y r!   )r  rM   s    r   rL   zKeyPath.__init__  s	    r   c                 <    t               }|j                  |        |S r!   )r  append_svg_path)path_strrl  s     r   from_svg_pathzKeyPath.from_svg_path  s    yX&r   c                 8   | j                   }| j                  }| j                         }| j                         }t	               }t        j
                  ||ggt        j                  ||||||ggt        j                  g gg|_        | j                         |_
        |S r!   )rC  rD  rightbottomr  MOVE_TOLINE_TO
CLOSE_PATHr  copy_bounds)r/  x0y0x1y1rl  s         r   r  zKeyPath.from_rect  s    VVVVZZ\[[]y!//B84!//BBB+CD!,,b13 yy{r   z([+-]?[0-9.]+)c                     t               }| j                  D ]%  \  }}|j                  j                  ||d d  g       ' |S r!   )r  r  append)rN   resultopcoordss       r   r  zKeyPath.copy  s?    -- 	4JBOO""Bq	?3	4r   c                 P   d}g }| j                  |      }|D ]  }	 t        |      }|j                  |       ! |r| j                  ||       yy# t        $ rL |j	                         r|r| j                  ||       |}g }n |dk(  rnt        dj                  |            Y w xY w)aI  
        Append a SVG path data string to the path.

        Doctests:
        # absolute move_to command
        >>> p = KeyPath.from_svg_path("M 100 200 120 -220")
        >>> print(p.segments)
        [[0, [100.0, 200.0]], [1, [120.0, -220.0]]]

        # relative move_to command
        >>> p = KeyPath.from_svg_path("m 100 200 10 -10")
        >>> print(p.segments)
        [[0, [100.0, 200.0]], [1, [110.0, 190.0]]]

        # relative move_to and close_path segments
        >>> p = KeyPath.from_svg_path("m 100 200 10 -10 z")
        >>> print(p.segments)
        [[0, [100.0, 200.0]], [1, [110.0, 190.0]], [2, []]]

        # spaces and commas and are optional where possible
        >>> p = KeyPath.from_svg_path("m100,200 10-10z")
        >>> print(p.segments)
        [[0, [100.0, 200.0]], [1, [110.0, 190.0]], [2, []]]
        rJ   ,z&unexpected token '{}' in svg path dataN)_tokenize_svg_pathfloatr  r  isalphaappend_commandr  )rN   r  cmd_strr  tokenstokenvals          r   r  zKeyPath.append_svg_path  s    4 ((2 	*E*Elc"	*& 0   *==?++GV<#GFc\ %B!6%=* **s   AAB%$B%c                    |dv re| j                   rd}| j                  \  }}nd}|d   |d   }}t        |t        |      d      D ]"  }|||   z  }|||dz      z  }|||<   |||dz   <   $ |j	                         }|dk(  rc| j                   j                  | j                  |dd g       t        |      dkD  r| j                   j                  | j                  |dd g       nY|dk(  r(| j                   j                  | j                  |g       n,|dk(  r'| j                   j                  | j                  g g       t        |      dk\  r|d	d | _        yy)
a>  
        Append a single command and it's coordinate data to the path.

        Doctests:
        # first lowercase move_to position is absolute
        >>> p = KeyPath()
        >>> p.append_command("m", [100, 200])
        >>> print(p.segments)
        [[0, [100, 200]]]

        # move_to segments become line_to segments after the first position
        >>> p = KeyPath()
        >>> p.append_command("M", [100, 200, 110, 190])
        >>> print(p.segments)
        [[0, [100, 200]], [1, [110, 190]]]

        # further lowercase move_to positions are relative, must become absolute
        >>> p = KeyPath()
        >>> p.append_command("m", [100, 200, 10, -10, 10, -10])
        >>> print(p.segments)
        [[0, [100, 200]], [1, [110, 190, 120, 180]]]

        # further lowercase segments must still be become absolute
        >>> p = KeyPath()
        >>> p.append_command("m", [100, 200, 10, -10, 10, -10])
        >>> p.append_command("l", [1, -1, 1, -1])
        >>> print(p.segments)
        [[0, [100, 200]], [1, [110, 190, 120, 180]], [1, [121, 179, 122, 178]]]
        )mlr   rQ   r   r  Nr  z)	r  _last_abs_posr<   r   lowerr  r  r  r  )rN   r  r  startrC  rD  r  cmds           r   r  zKeyPath.append_command  sW   @ j  }}))1ay&)15#f+q1  VAYVAaC[ q	qs	  mmo#:MM  $,,r
!;<6{Q$$dllF12J%?@CZMM  $,,!78CZMM  $//2!67 v;!!'D r   c                     t         j                  j                  |       D cg c]  }|j                          }}|D cg c]  }|s|	 c}S c c}w c c}w )al  
        Split SVG path date into command and coordinate tokens.

        Doctests:
        >>> KeyPath._tokenize_svg_path("m 10,20")
        ['m', '10', ',', '20']
        >>> KeyPath._tokenize_svg_path("   m   10  , \n  20 ")
        ['m', '10', ',', '20']
        >>> KeyPath._tokenize_svg_path("m 10,20 30,40 z")
        ['m', '10', ',', '20', '30', ',', '40', 'z']
        >>> KeyPath._tokenize_svg_path("m10,20 30,40z")
        ['m', '10', ',', '20', '30', ',', '40', 'z']
        >>> KeyPath._tokenize_svg_path("M100.32 100.09 100. -100.")
        ['M', '100.32', '100.09', '100.', '-100.']
        >>> KeyPath._tokenize_svg_path("m123+23 20,-14L200,200")
        ['m', '123', '+23', '20', ',', '-14', 'L', '200', ',', '200']
        >>> KeyPath._tokenize_svg_path("m123+23 20,-14L200,200")
        ['m', '123', '+23', '20', ',', '-14', 'L', '200', ',', '200']
        )r  _svg_path_patternr~   strip)r  r  r  s      r   r  zKeyPath._tokenize_svg_path  sW    ,  '88>>xHJ ++- J J#)3%U33J3s   AAAc                 P    | j                   }|| j                         }|| _         |S r!   )r  _calc_bounds)rN   boundss     r   rt  zKeyPath.get_bounds4  s*    >&&(F!DLr   c                 p   	 | j                   d   d   d   x}}| j                   d   d   d   x}}| j                   D ]L  }|d   }t        dt	        |      d      D ],  }||   }||dz      }	||kD  r|}||k  r|}||	kD  r|	}||	k  s+|	}. N t        ||||z
  ||z
        S # t        $ r t               cY S w xY w)a  
        Compute the bounding box of the path.

        Doctests:
        # Simple move_to path, something inkscape would create.
        >>> p = KeyPath.from_svg_path("m 100,200 10,-10 z")
        >>> print(p.get_bounds())
        Rect(x=100.0 y=190.0 w=10.0 h=10.0)
        r   r   rQ   )r  
IndexErrorr   r<   r   )
rN   xminxmaxyminymaxcommandr  r  rC  rD  s
             r   r  zKeyPath._calc_bounds;  s    	--*1-a00D4--*1-a00D4 }} 	GQZF1c&k1- 
1I1Q3K!8D!8D!8D!8D
	 D$tTD[99#  	6M	s   .B B54B5c                 d    | j                         j                  ||      }| j                  |      S )zO
        Returns a new path which is larger by dx and dy on all sides.
        )rt  r,  r  )rN   rH  rI  r/  s       r   r,  zKeyPath.inflate\  s.      ((R0%%r   c                    | j                         }| j                         }|j                  |j                  z  }|j                  |j                  z  }|j	                         \  }}|j
                  ||j
                  |z
  |z  z   z
  }|j                  ||j                  |z
  |z  z   z
  }	|j                  D ]N  \  }
}t        dt        |      d      D ]0  }||z   ||   |z
  |z  z   ||<   |	|z   ||dz      |z
  |z  z   ||dz   <   2 P |S )zc
        Scales and translates the path so that rect
        becomes its new bounding box.
        r   rQ   r   )
r  rt  rE  rF  
get_centerrC  rD  r  r<   r   )rN   r/  r  r  scalexscaleydorgxdorgyrH  rI  r  r  r  s                r   r  zKeyPath.fit_in_rectc  s   
 "&(("&(("((*uVVu5 0F::;VVu5 0F::; // 	JJB1c&k1- JJ&)e*;v)EEq	 5jF1Q3K%,?6+IIqsJ	J
 r   c                 d   | j                         }|j                  }|j                  }t        t        |            D ]p  }	||	   \  }
}||	   \  }}t        dt        |      d      D ]E  }||   }||dz      }||   }||dz      }||z
  }||z
  }|||z  z   |z   ||<   |||z  z   |z   ||dz   <   G r |S )z
        Interpolate between self and path1.
        Paths must have the same structure (length and operations).
        pos: 0.0 = self, 1.0 = path1.
        r   rQ   r   )r  r  r<   r   )rN   r  r  r  rd  re  r  r  	segments1r  r  r  r  r  jrC  rD  r  r  rH  rI  s                        r   r  zKeyPath.linintw  s     ??NN	s8}% 	8A!!JB$Q<LC1c&k1- 81I1Q3KQZQqS\!V!V
NX5q	%"*nx7qs8	8 r   c              #      K   g }| j                   D ]]  \  }}|| j                  k(  r|j                  |       '|| j                  k(  rg }|j                  |       J|| j                  k(  sZ| _ yw)z
        Loop through all independent polygons in the path.
        Can't handle splines and arcs, everything has to
        be polygons from here.
        N)r  r  extendr  r  )rN   polygonr  r  s       r   r{  zKeyPath.iter_polygons  sj      -- 
	JBT\\!v&t||#v&t&
	s   A(A2+A2c                 d    | j                         D ]  }| j                  ||d   |d         s y y )Nr   r   T)r{  is_point_in_polygon)rN   pointr  s      r   is_point_withinzKeyPath.is_point_within  s7    ))+ 	G''q58D	r   c                    d}t        |       }	 | |dz
     }| |dz
     }t        d|d      D ]A  }| |   }| |dz      }	|	|k  r||k  s
||k  r||	k  r|||z
  ||	z
  z  ||	z
  z  |z   k  r| }|}|	}C |S # t        $ r Y yw xY w)NFrQ   r   r   )r   r  r<   )
verticesrC  rD  cnr  r  r  r  r  s
             r   r  zKeyPath.is_point_in_polygon  s    M	!a%B!a%B q!Q 	A!B!A#BaAFbAg!b&R"WR(BG4r99EBB	   		s   A2 2	A>=A>r!   )r   r   r  r  )r7   r8   r9   r:   r<   r  r  r  r  r  rL   r>   r  r  recompiler  r  r  r  r  rt  r  r,  r  r  r{  r  r  r?   r   r   r  r  |  s     	a	 MG  
 
 
 #

#3411f>-@ 4 40:B&( 25*-2(
  r   r  )-r:   
__future__r   r   r   mathr   r  Onboard.utilsr   r   r	   r
   Onboard.Layoutr   logging	getLogger_loggerOnboard.Configr   r   r;   r<   r   r   r   r   SCRIPT_TYPEr   r   LEGACY_MODIFIER_TYPEr   r   SINGLE_STROKE_ACTIONDELAYED_STROKE_ACTIONDOUBLE_STROKE_ACTIONactionsr   rA   rF   r   r   r  r  r  r?   r   r   <module>r     s  .
 B A  	2 2 & 
'

K
( "	 
%2, 
%(O	 332S6 S6l  y&
 y&x	Q'I Q'h p pfA Ar   