diff -r 81281f49aeb4 -r 06915aa059c5 src/source/howto-renderer.rst --- a/src/source/howto-renderer.rst Fri May 25 14:28:29 2018 +0200 +++ b/src/source/howto-renderer.rst Tue Jun 19 16:11:57 2018 +0200 @@ -1,5 +1,133 @@ .. _rendererhowto: -How to create a new renderer? -============================= +How to create a Renderer? +========================= + + +**Renderer** are the layout of the utility data content. A renderer combine un context, a skin and +a template to produce the front office html + + To create new renderer you can override an already exist renderer or create a new one from scratch. Steps below + we will create a renderer for a `IContact` paragraph + + +1. Override a Renderer +---------------------- + +The simplest is to create a new class that inherits from the existing **Renderer** and modify this template. +After that all you have to define a new adapter name and a new label. + + +.. code-block:: python + :linenos: + + # New custom contact paragraph renderer + + @adapter_config(name='custom', context=(IContactParagraph, IPyAMSLayer), provides=IContentRenderer) + @template_config(template='templates/contact-custom.pt', layer=IPyAMSLayer) + class ContactParagraphCustomRenderer(ContactParagraphDefaultRenderer): + """Context paragraph custom renderer""" + + label = _("Custom contact renderer") + settings_interface = IContactParagraphDefaultRendererSettings + + +In this example, we have defined an adapter named 'custom' with :py:class:`IContactParagraph`, +:py:class:`IPyAMSLayer` as context and provides :py:class:`IContentRenderer` interface. + +Using ``@template_config()`` decorator, the renderer will be displayed in html container according to the template + +The new renderer inherit of :py:class:`ContactParagraphDefaultRenderer`, have a new **label** (line 8) +and is associated an **settings_interface** (line 9) + +.. tip:: + + You can override the template of a renderer easily with the function :py:func:`pyams_template.template.override_template` + It's takes the context and the new template path as params. + + +2. Create a new Renderer from scratch +------------------------------------- + +We can define a new settings interface for the renderer, to do that we start by creating an interface + + +a) Create setting interface for the renderer +"""""""""""""""""""""""""""""""""""""""""""" + +.. code-block:: python + + class IPhotoRendererSettings(Interface): + """Custom renderer settings interface""" + + + display_photo = Bool(title=_("Show photo?"), + description=_("Display contact photo"), + required=True, + default=True) + + can_display_photo = Attribute("Check if photo can be displayed") + + +We have created an interface with two attributes *display_photo* and *can_display_photo* +Then we create an implemantation of the interface + +.. code-block:: python + + @implementer(IPhotoRendererSettings) + class PhotoRendererSettings(Persistent, Location): + """Custom renderer settings""" + + display_photo = FieldProperty(IPhotoRendererSettings['display_photo']) + + @property + def can_display_photo(self): + contact = IContactParagraph(self.__parent__) + if not contact.photo: + return False + return self.display_photo + + + +b) Create an adapter for the render setting interface +""""""""""""""""""""""""""""""""""""""""""""""""""""" + +With :py:func:`@adapter_config()` we declare a new adapter that applies to a context and provide the interface of + renderer settings + +.. code-block:: python + + PHOTO_RENDERER_SETTINGS_KEY = 'pyams_content.contact.renderer:photo' + + @adapter_config(context=IContactParagraph, provides=IPhotoRendererSettings) + def custom_renderer_settings_factory(context): + """Contact paragraph default renderer settings factory""" + return get_annotation_adapter(context, PHOTO_RENDERER_SETTINGS_KEY, + CustomRendererSettings) + + +In this example the settings interface adapter is defined with `IContactParagraph` as context +and provide `IPhotoRendererSettings`. + + + +c) Create an adapter for the render interface +""""""""""""""""""""""""""""""""""""""""""""" + +.. code-block:: python + + @adapter_config(context=(IContactParagraph, IPyAMSLayer), provides=IContentRenderer) + @template_config(template='templates/contact-custom.pt', layer=IPyAMSLayer) + class PhotoRenderer(BaseContentRenderer): + """Context paragraph custom renderer""" + + label = _("Custom contact renderer") + settings_interface = IPhotoRendererSettings + + +Add settings interface to the renderer `settings_interface = IPhotoRendererSettings` + +.. tip:: + When a setting_interface is associated to a renderer, you can access to `settings` attributes through the template +