=============
Object Widget
=============

The following example shows a Family with Mother and Father.
First define the interface for a person:

  >>> from zope.interface import Interface, implements
  >>> from zope.schema import TextLine

  >>> class IPerson(Interface):
  ...     """Interface for Persons."""
  ...
  ...     name = TextLine(title=u'Name', description=u'The first name')

Let's define the class:

  >>> class Person(object):
  ...
  ...     implements(IPerson)
  ...
  ...     def __init__(self, name=''):
  ...         self.name = name

Let's define the interface family:

  >>> from zope.schema import Object

  >>> class IFamily(Interface):
  ...     """The familiy interface.""" 
  ...  
  ...     mother = Object(title=u'Mother',
  ...                     required=False, 
  ...                     schema=IPerson)
  ...
  ...     father = Object(title=u'Father',
  ...                     required=False, 
  ...                     schema=IPerson)

Let's define the class familiy with FieldProperty's mother and father
FieldProperty validate the values if they get added:

  >>> from zope.schema.fieldproperty import FieldProperty

  >>> class Family(object):
  ...     """The familiy interface."""
  ...
  ...     implements(IFamily)
  ...
  ...     mother = FieldProperty(IFamily['mother'])
  ...     father = FieldProperty(IFamily['father'])
  ...
  ...     def __init__(self, mother=None, father=None):
  ...         self.mother = mother
  ...         self.father = father

Let's make a instance of Family with None attributes:

  >>> family = Family()
  >>> bool(family.mother == None)
  True

  >>> bool(family.father == None)
  True

Let's make a instance of Family with None attributes:

  >>> mother = Person(u'Margrith')
  >>> father = Person(u'Joe')
  >>> family = Family(mother, father)
  >>> IPerson.providedBy(family.mother)
  True

  >>> IPerson.providedBy(family.father)
  True

Let's define a dummy class which doesn't implements IPerson:

  >>> class Dummy(object):
  ...     """Dummy class."""
  ...     def __init__(self, name=''):
  ...         self.name = name

Raise a SchemaNotProvided exception if we add a Dummy instance to a Family 
object:

  >>> foo = Dummy('foo')
  >>> bar = Dummy('bar')
  >>> family = Family(foo, bar)
  Traceback (most recent call last):
  ...
  SchemaNotProvided

Now let's setup a enviroment for use the widget like in a real application:

  >>> from zope.app.tests import ztapi
  >>> from zope.publisher.browser import TestRequest
  >>> from zope.schema.interfaces import ITextLine
  >>> from zope.schema import TextLine
  >>> from zope.app.form.browser import TextWidget
  >>> from zope.app.form.browser import ObjectWidget
  >>> from zope.app.form.interfaces import IInputWidget

Register the TextLine widget used in the IPerson interface for the field 'name'.

  >>> ztapi.browserViewProviding(ITextLine, TextWidget, IInputWidget)

Let's define a request and provide input value for the mothers name used
in the family object:

  >>> request = TestRequest(HTTP_ACCEPT_LANGUAGE='pl')
  >>> request.form['field.mother.name'] = u'Margrith Ineichen'

Before we update the object let's check the value name of the mother
instance on the family object:

  >>> family.mother.name
  u'Margrith'

Now let's initialize a ObjectWidget with the right attributes:

  >>> mother_field = IFamily['mother']
  >>> factory = Person
  >>> widget = ObjectWidget(mother_field, request, factory)

Now comes the magic. Apply changes means we force the ObjectWidget to read 
the request, extract the value and save it on the content. The ObjectWidget 
instance uses a real Person class (factory) for add the value. The value is 
temporary stored in this factory class. The ObjectWidget reads the value from 
this factory and set it to the attribute 'name' of the instance mother 
(The object mother is allready there). If we don't have a instance mother 
allready store in the family object, the factory instance will be stored 
directly to the family attribute mother. For more information see the method 
'applyChanges()' in the interface 
zope.app.form.browser.objectwidget.ObjectWidget.

  >>> widget.applyChanges(family)
  True

Test the updated mother's name value on the object family:

  >>> family.mother.name
  u'Margrith Ineichen'
  
  >>> IPerson.providedBy(family.mother)
  True

So, now you know my mothers and fathers name. I hope it's also clear how to 
use the Object field and the ObjectWidget.
