ó
X–Tc           @   s]   d  Z  d d l Z d d l Z d d l Z d e f d „  ƒ  YZ d e j f d „  ƒ  YZ d S(   sP   This module defines the Form class, a subclass of Views that can manage
widgets.iÿÿÿÿNt   _FormFieldMetac           B   s   e  Z d  Z d „  Z RS(   s÷   
    Black magic for wrapping widgets defined as class attributes. See python
    documentation on overriding Python
    `__metaclass__ <http://docs.python.org/2/reference/datamodel.html#customizing-class-creation>`_
    for more information.
    c         C   sI   t  j |  | | | ƒ } d „  } t t j | | ƒ d d „  ƒ| _ | S(   Nc         S   s   t  |  t j j ƒ S(   N(   t
   isinstancet   spyralt   widgetst   _WidgetWrapper(   t   obj(    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyt   <lambda>   s    t   keyc         S   s   |  d j  S(   Ni   (   t   creation_counter(   t   i(    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR      s    (   t   typet   __new__t   sortedt   inspectt
   getmemberst   fields(   t   metat   namet   basest   dictt   clst
   is_wrapper(    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR      s
    	(   t   __name__t
   __module__t   __doc__R   (    (    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR       s   t   Formc           B   sª   e  Z d  Z e Z d „  Z d „  Z d „  Z d „  Z d „  Z	 d „  Z
 d „  Z d d „ Z d	 „  Z e e ƒ Z d
 „  Z d d „ Z d „  Z e d „ Z e d „ Z RS(   sÎ  
    Forms are a subclass of :class:`Views <spyral.View>` that hold a set of
    :ref:`Widgets <api.widgets>`. Forms will manage focus and event delegation between the widgets,
    ensuring that only one widget is active at a given time. Forms are defined 
    using a special class-based syntax::

        class MyForm(spyral.Form):
            name = spyral.widgets.TextInput(100, "Current Name")
            remember_me = spyral.widgets.Checkbox()
            save = spyral.widgets.ToggleButton("Save")

        my_form = MyForm()

    When referencing widgets in this way, the "Widget" part of the widget's name
    is dropped: ``spyral.widgets.ButtonWidget`` becomes ``spyral.widgets.Button``.
    Every widget in a form is accessible as an attribute of the form:

        >>> print my_form.remember_me.value
        "up"

    :param scene: The Scene or View that this Form belongs to.
    :type scene: :class:`Scene <spyral.Scene>` or :class:`View <spyral.View>`.
    c         C   s“  t  j j |  | ƒ d t f d „  ƒ  Y} g  |  _ i  |  _ d  |  _ d  |  _ d  |  _	 t  j
 j d |  j d | ƒt  j
 j d |  j d | ƒt  j
 j d |  j d | ƒt  j
 j d |  j d | ƒt  j
 j d |  j d | ƒt  j
 j d	 |  j d | ƒt  j
 j d
 |  j d | ƒ|  j } | ƒ  |  _ xS | D]K \ } } | |  | ƒ } t | d | ƒ t |  | | ƒ |  j | | ƒ q6W|  j ƒ  d  S(   Nt   Fieldsc           B   s   e  Z RS(    (   R   R   (    (    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR   2   s   s   input.mouse.up.leftt   scenes   input.mouse.down.lefts   input.mouse.motions   input.keyboard.down.tabs   input.keyboard.up.tabs   input.keyboard.ups   input.keyboard.downR   (   R   t   Viewt   __init__t   objectt   _widgetst   _tab_orderst   Nonet   _current_focust   _mouse_currently_overt   _mouse_down_ont   eventt   registert   _handle_mouse_upt   _handle_mouse_downt   _handle_mouse_motiont   _handle_tabt   _handle_key_upt   _handle_key_downR   t   setattrt
   add_widgett   focus(   t   selfR   R   R   R   t   widgett   w(    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR   0   s:    						c         C   s0   |  j  d k r t S|  j  j | ƒ d |  _  d S(   sÏ   
        Delegate the mouse being released to the widget that is currently being
        clicked.

        :param event: The associated event data.
        :type event: :class:`Event <spyral.Event>`
        N(   R$   R!   t   FalseR'   (   R0   R%   (    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR'   X   s    c         C   sQ   xJ |  j  D]? } | j | j ƒ r
 |  j | ƒ | |  _ | j | ƒ t Sq
 Wt S(   sÖ   
        Delegate the mouse being clicked down to any widget that it is currently
        hovering over.

        :param event: The associated event data.
        :type event: :class:`Event <spyral.Event>`
        (   R   t   collide_pointt   posR/   R$   R(   t   TrueR3   (   R0   R%   R1   (    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR(   e   s    	c         C   sÁ   |  j  d k	 r" |  j  j | ƒ n  d } x9 |  j D]. } | j | j ƒ r2 | j | ƒ | } q2 q2 W| |  j k r½ |  j d k	 r• |  j j | ƒ n  | |  _ | d k	 r½ | j | ƒ q½ n  d S(   s–  
        Delegate the mouse being hovered over any widget that it is currently
        hovering over. If the widget being hovered over is no longer the
        previous widget that was being hovered over, it notifies the old widget
        (mouse out event) and the new widget (mouse over event).

        :param event: The associated event data.
        :type event: :class:`Event <spyral.Event>`
        N(	   R$   R!   R)   R   R4   R5   R#   t   _handle_mouse_outt   _handle_mouse_over(   R0   R%   t	   now_hoverR1   (    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR)   u   s    
	c         C   sU   |  j  d k r d S| j d k r& t S| j t j j @rG |  j ƒ  t S|  j	 ƒ  t S(   s  
        If this form has focus, advances to the next widget in the tab order.
        Unless the shift key is held, in which case the previous widget is
        focused.

        :param event: The associated event data.
        :type event: :class:`Event <spyral.Event>`
        Nt   down(
   R"   R!   R
   R6   t   modR   t   modst   shiftt   previoust   next(   R0   R%   (    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR*      s    	

c         C   s&   |  j  d k	 r" |  j  j | ƒ n  d S(   s¹   
        Notifies the currently focused widget that a key has been pressed.

        :param event: The associated event data.
        :type event: :class:`Event <spyral.Event>`
        N(   R"   R!   R,   (   R0   R%   (    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR,       s    c         C   s&   |  j  d k	 r" |  j  j | ƒ n  d S(   sº   
        Notifies the currently focused widget that a key has been released.

        :param event: The associated event data.
        :type event: :class:`Event <spyral.Event>`
        N(   R"   R!   R+   (   R0   R%   (    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR+   ª   s    c         C   sz   | d k rS t |  j ƒ d k r= t |  j j ƒ  ƒ d } n d } | |  j | <n  |  j j | ƒ t |  j | | ƒ d S(   s4  
        Adds a new widget to this form. When this method is used to add a Widget
        to a Form, you create the Widget as you would create a normal Sprite. It
        is preferred to use the class-based method instead of this; consider
        carefully whether you can achieve dynamicity through visibility and
        disabling.

        >>> my_widget = spyral.widgets.ButtonWidget(my_form, "save")
        >>> my_form.add_widget("save", my_widget)

        :param str name: A unique name for this widget.
        :param widget: The new Widget.
        :type widget: :ref:`Widget <api.widgets>`
        :param int tab_order: Sets the tab order for this widget explicitly. If
                              tab-order is None, it is set to one higher than
                              the highest tab order.
        i    i   N(	   R!   t   lenR    t   maxt
   itervaluesR   t   appendR-   R   (   R0   R   R1   t	   tab_order(    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR.   µ   s    c         C   s   t  d „  |  j Dƒ ƒ S(   sŸ   
        A dictionary of the values for all the fields, mapping the name
        of each widget with the value associated with that widget. Read-only.
        c         s   s!   |  ] } | j  | j f Vq d  S(   N(   R   t   value(   t   .0R1   (    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pys	   <genexpr>Ö   s    (   R   R   (   R0   (    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyt   _get_valuesÑ   s    c         C   s]   t  j d d d | d |  ƒ } |  j j d i |  j j d 6| j d 6| ƒ | j | ƒ d S(   sµ   
        Queues an event indicating that a widget has lost focus.

        :param widget: The widget that is losing focus.
        :type widget: :ref:`Widget <api.widgets>`
        R   t   blurredR1   t   forms%   form.%(form_name)s.%(widget)s.blurredt	   form_nameN(   R   t   EventR   t   _queue_eventt	   __class__R   R   t   _handle_blur(   R0   R1   t   e(    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyt   _blurÚ   s    c         C   sÌ   | d k rD |  j s d St |  j j ƒ  d t j d ƒ ƒd } n  |  j d k	 rf |  j |  j ƒ n  | |  _ t	 j
 d d d | d |  ƒ } |  j j d	 i |  j j d
 6| j d 6| ƒ | j | ƒ d S(   s0  
        Sets the focus to be on a specific widget. Focus by default goes
        to the first widget added to the form.

        :param widget: The widget that is gaining focus; if None, then the first
                       widget gains focus.
        :type widget: :ref:`Widget <api.widgets>`
        NR   i   i    R   t   focusedR1   RI   s%   form.%(form_name)s.%(widget)s.focusedRJ   (   R!   R   t   minR    t	   iteritemst   operatort
   itemgetterR"   RP   R   RK   R   RL   RM   R   R   t   _handle_focus(   R0   R1   RO   (    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR/   è   s    
		c         C   s/   |  j  d k	 r+ |  j |  j  ƒ d |  _  n  d S(   s,   
        Defocuses the entire form.
        N(   R"   R!   RP   (   R0   (    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyt   blur  s    c         C   sâ   |  j  d k r |  j ƒ  d S|  j s* d S|  j |  j  } g  |  j j ƒ  D]$ \ } } | | k rJ | | f ^ qJ } t | ƒ d k r™ | s d Sd } n t | d t j	 d ƒ ƒd } |  j
 |  j  ƒ d |  _  |  j | ƒ d S(   sÁ   
        Focuses on the next widget in tab order.

        :param bool wrap: Whether to continue to the first widget when the end
                          of the tab order is reached.
        Ni    R   i   (   R"   R!   R/   R   R    RS   R@   RR   RT   RU   RP   (   R0   t   wrapt   curR1   t   ordert
   candidates(    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR?     s"    
			c         C   s  |  j  d k r |  j ƒ  d S|  j s* d S|  j |  j  } g  |  j j ƒ  D]$ \ } } | | k  rJ | | f ^ qJ } t | ƒ d k r» | s d St |  j j ƒ  d t j	 d ƒ ƒd } n t | d t j	 d ƒ ƒd } |  j
 |  j  ƒ d |  _  |  j | ƒ d S(   sÃ   
        Focuses the previous widget in tab order.

        :param bool wrap: Whether to continue to the last widget when the first
                          of the tab order is reached.
        Ni    R   i   (   R"   R!   R/   R   R    RS   R@   RA   RT   RU   RP   (   R0   RX   RY   R1   RZ   R[   (    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR>   +  s$    
		N(   R   R   R   R    t   __metaclass__R   R'   R(   R)   R*   R,   R+   R!   R.   RG   t   propertyt   valuesRP   R/   RW   R6   R?   R>   (    (    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyR      s"   	(					
			 	(   R   R   RT   R   R
   R    R   R   (    (    (    s/   /usr/lib/python2.7/site-packages/spyral/form.pyt   <module>   s
   