# HG changeset patch # User Damien Correia # Date 1527254611 -7200 # Node ID 3f403b9c42202c6966d45def097700f02773a80d # Parent b0b289038b2d081ce9169ed6e5de3b0536f85fb1# Parent 81281f49aeb4cf016e6ac33dc0671d98f2a5d05c merge default diff -r 81281f49aeb4 -r 3f403b9c4220 src/source/appextend.rst --- a/src/source/appextend.rst Fri May 25 14:28:29 2018 +0200 +++ b/src/source/appextend.rst Fri May 25 15:23:31 2018 +0200 @@ -8,9 +8,5 @@ :maxdepth: 1 howto-adapter - howto-skin - howto-template + howto-portlet howto-renderer - howto-portlet - howto-paragraph - howto-content diff -r 81281f49aeb4 -r 3f403b9c4220 src/source/howto-portlet.rst --- a/src/source/howto-portlet.rst Fri May 25 14:28:29 2018 +0200 +++ b/src/source/howto-portlet.rst Fri May 25 15:23:31 2018 +0200 @@ -160,9 +160,14 @@ .. code-block:: python @adapter_config(name='another-renderer', - context=(IPortalContext, IPyAMSLayer, Interface, INewPortletSettings), provides=IPortletRenderer) + context=(IPortalContext, IPyAMSLayer, Interface, INewPortletSettings), + provides=IPortletRenderer) @template_config(template='my-portlet-render-2.pt', layer=IPyAMSLayer) class AnotherNewPortletRenderer(PortletRenderer): """Another new portlet renderer""" label = _("Another comment renderer") + +.. tip:: + You can use an other template without create a new renderer component, + with :py:func:`pyams_utils` to override the default template with you own. diff -r 81281f49aeb4 -r 3f403b9c4220 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 Fri May 25 15:23:31 2018 +0200 @@ -1,5 +1,121 @@ .. _rendererhowto: -How to create a new renderer? +How to create a new Renderer? ============================= + +**Renderer** are the layout of the utility data content + + +1. Create a Renderer +'''''''''''''''''''' + +The simplest is to create a new class that inherits from the existing **Renderer**, to modify this template and +to define a new adapter name. You must also override the label to distinguish rendering modes in the ZMI. + + + +.. 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 the new renderer inherit of :py:class:`ContactParagraphDefaultRenderer`, we have defined a **label** (line 8) +and associated an **settings_interface** (line 9) + +We have declared this adapter with 'custom' name, it takes :py:class:`IContactParagraph`, :py:class:`IPyAMSLayer` as context +and provides :py:class:`IContentRenderer` interface. + +Using ``@template_config()`` decorator, the renderer can be displayed in html container according to the template + + +2. Define a Renderer settings +''''''''''''''''''''''''''''' + +In the previous point, we did not change the settings interface of the renderer. +However, we can define a new settings interface for the new renderer, for that we start by creating an interface + +a) Create setting interface +""""""""""""""""""""""""""" + + +.. code-block:: python + + class ICustomRendererSettings(Interface): + """Custom renderer settings interface""" + + + display_photo = Bool(title=_("Show photo?"), + description=_("Display contact photo"), + required=True, + default=True) + + display_phone_number = Bool(title=_("Show phone number?"), + description=_("Display the phone number of the contact?"), + required=True, + default=True) + + can_display_photo = Attribute("Check if photo can be displayed") + + + +b) Create an implemantation of the interface +"""""""""""""""""""""""""""""""""""""""""""" + +.. code-block:: python + + + @implementer(ICustomRendererSettings) + class CustomRendererSettings(Persistent, Location): + """Custom renderer settings""" + + display_photo = FieldProperty(ICustomRendererSettings['display_photo']) + display_phone_number = FieldProperty(ICustomRendererSettings['display_phone_number']) + + @property + def can_display_photo(self): + contact = IContactParagraph(self.__parent__) + if not contact.photo: + return False + return self.display_photo + + + +c) Create an adapter for the render setting interface +""""""""""""""""""""""""""""""""""""""""""""""""""""" + +With the wrapper :py:func:`@adapter_config()` we declare a new adapter. + +.. code-block:: python + + CUSTOM_RENDERER_SETTINGS_KEY = 'pyams_content.contact.renderer:custom' + + @adapter_config(context=IContactParagraph, provides=ICustomRendererSettings) + def custom_renderer_settings_factory(context): + """Contact paragraph default renderer settings factory""" + return get_annotation_adapter(context, CUSTOM_RENDERER_SETTINGS_KEY, + CustomRendererSettings) + +In this example the settings interface adapter is defined with `IContactParagraph` as context +and provide `ICustomRendererSettings`. + +d) Add settings interface renderer +"""""""""""""""""""""""""""""""""" + +In the renderer definition: + +.. code-block:: python + settings_interface = ICustomRendererSettings + + +.. tip:: + When a setting_interface is associated to a renderer, you can acces to `settings` attributs through the template +