src/source/howto-renderer.rst
branchdoc-dc
changeset 74 efe71f19939c
parent 72 3f403b9c4220
child 83 ee94d17857a4
equal deleted inserted replaced
73:a3a8642a31b2 74:efe71f19939c
     2 
     2 
     3 
     3 
     4 How to create a new Renderer?
     4 How to create a new Renderer?
     5 =============================
     5 =============================
     6 
     6 
     7 **Renderer** are the layout of the utility data content
     7 **Renderer** are the layout of the utility data content. A renderer combine un context, a skin and
       
     8  a template to produce the front office html
       
     9 
       
    10  To create new renderer you can override an already exist renderer or create a new one from scratch. Steps below
       
    11  we will create a renderer for a `IContact` paragraph
     8 
    12 
     9 
    13 
    10 1. Create a Renderer
    14 1. Override a Renderer
    11 ''''''''''''''''''''
    15 ----------------------
    12 
    16 
    13 The simplest is to create a new class that inherits from the existing **Renderer**, to modify this template and
    17 The simplest is to create a new class that inherits from the existing **Renderer**  and modify this template.
    14 to define a new adapter name. You must also override the label to distinguish rendering modes in the ZMI.
    18 After that all you have to define a new adapter name and a new label.
    15 
       
    16 
    19 
    17 
    20 
    18 .. code-block:: python
    21 .. code-block:: python
    19     :linenos:
    22     :linenos:
    20 
    23 
    26         """Context paragraph custom renderer"""
    29         """Context paragraph custom renderer"""
    27 
    30 
    28         label = _("Custom contact renderer")
    31         label = _("Custom contact renderer")
    29         settings_interface = IContactParagraphDefaultRendererSettings
    32         settings_interface = IContactParagraphDefaultRendererSettings
    30 
    33 
    31 In this example the new renderer inherit of :py:class:`ContactParagraphDefaultRenderer`, we have defined a **label** (line 8)
       
    32 and associated an **settings_interface** (line 9)
       
    33 
    34 
    34 We have declared this adapter with 'custom' name, it takes :py:class:`IContactParagraph`, :py:class:`IPyAMSLayer` as context
    35 In this example, we have defined an adapter named 'custom' with :py:class:`IContactParagraph`,
    35 and provides :py:class:`IContentRenderer` interface.
    36 :py:class:`IPyAMSLayer` as context and provides :py:class:`IContentRenderer` interface.
    36 
    37 
    37 Using ``@template_config()`` decorator, the renderer can be displayed in html container according to the template
    38 Using ``@template_config()`` decorator, the renderer will be displayed in html container according to the template
       
    39 
       
    40 The new renderer inherit of :py:class:`ContactParagraphDefaultRenderer`, have a new **label** (line 8)
       
    41 and is associated an **settings_interface** (line 9)
       
    42 
       
    43 .. tip::
       
    44 
       
    45     You can override the template of a renderer easily with the function :py:func:`pyams_template.template.override_template`
       
    46     It's takes the context and the new template path as params.
    38 
    47 
    39 
    48 
    40 2. Define a Renderer settings
    49 2. Create a new Renderer from scratch
    41 '''''''''''''''''''''''''''''
    50 -------------------------------------
    42 
    51 
    43 In the previous point, we did not change the settings interface of the renderer.
    52 We can define a new settings interface for the renderer, to do that we start by creating an interface
    44 However, we can define a new settings interface for the new renderer, for that we start by creating an interface
       
    45 
    53 
    46 a) Create setting interface
       
    47 """""""""""""""""""""""""""
       
    48 
    54 
       
    55 a) Create setting interface for the renderer
       
    56 """"""""""""""""""""""""""""""""""""""""""""
    49 
    57 
    50 .. code-block:: python
    58 .. code-block:: python
    51 
    59 
    52     class ICustomRendererSettings(Interface):
    60     class IPhotoRendererSettings(Interface):
    53         """Custom renderer settings interface"""
    61         """Custom renderer settings interface"""
    54 
    62 
    55 
    63 
    56         display_photo = Bool(title=_("Show photo?"),
    64         display_photo = Bool(title=_("Show photo?"),
    57                              description=_("Display contact photo"),
    65                              description=_("Display contact photo"),
    58                              required=True,
    66                              required=True,
    59                              default=True)
    67                              default=True)
    60 
    68 
    61         display_phone_number = Bool(title=_("Show phone number?"),
       
    62                              description=_("Display the phone number of the contact?"),
       
    63                              required=True,
       
    64                              default=True)
       
    65 
       
    66         can_display_photo = Attribute("Check if photo can be displayed")
    69         can_display_photo = Attribute("Check if photo can be displayed")
    67 
    70 
    68 
    71 
    69 
    72 We have created an interface with two attributes *display_photo* and *can_display_photo*
    70 b) Create an implemantation of the interface
    73 Then we create an implemantation of the interface
    71 """"""""""""""""""""""""""""""""""""""""""""
       
    72 
    74 
    73 .. code-block:: python
    75 .. code-block:: python
    74 
    76 
    75 
    77     @implementer(IPhotoRendererSettings)
    76     @implementer(ICustomRendererSettings)
    78     class PhotoRendererSettings(Persistent, Location):
    77     class CustomRendererSettings(Persistent, Location):
       
    78         """Custom renderer settings"""
    79         """Custom renderer settings"""
    79 
    80 
    80         display_photo = FieldProperty(ICustomRendererSettings['display_photo'])
    81         display_photo = FieldProperty(IPhotoRendererSettings['display_photo'])
    81         display_phone_number = FieldProperty(ICustomRendererSettings['display_phone_number'])
       
    82 
    82 
    83         @property
    83         @property
    84         def can_display_photo(self):
    84         def can_display_photo(self):
    85             contact = IContactParagraph(self.__parent__)
    85             contact = IContactParagraph(self.__parent__)
    86             if not contact.photo:
    86             if not contact.photo:
    87                 return False
    87                 return False
    88             return self.display_photo
    88             return self.display_photo
    89 
    89 
    90 
    90 
    91 
    91 
    92 c) Create an adapter for the render setting interface
    92 b) Create an adapter for the render setting interface
    93 """""""""""""""""""""""""""""""""""""""""""""""""""""
    93 """""""""""""""""""""""""""""""""""""""""""""""""""""
    94 
    94 
    95 With the wrapper :py:func:`@adapter_config()` we declare a new adapter.
    95 With :py:func:`@adapter_config()` we declare a new adapter that applies to a context and provide the interface of
       
    96  renderer settings
    96 
    97 
    97 .. code-block:: python
    98 .. code-block:: python
    98 
    99 
    99     CUSTOM_RENDERER_SETTINGS_KEY = 'pyams_content.contact.renderer:custom'
   100     PHOTO_RENDERER_SETTINGS_KEY = 'pyams_content.contact.renderer:photo'
   100 
   101 
   101     @adapter_config(context=IContactParagraph, provides=ICustomRendererSettings)
   102     @adapter_config(context=IContactParagraph, provides=IPhotoRendererSettings)
   102     def custom_renderer_settings_factory(context):
   103     def custom_renderer_settings_factory(context):
   103         """Contact paragraph default renderer settings factory"""
   104         """Contact paragraph default renderer settings factory"""
   104         return get_annotation_adapter(context, CUSTOM_RENDERER_SETTINGS_KEY,
   105         return get_annotation_adapter(context, PHOTO_RENDERER_SETTINGS_KEY,
   105                                       CustomRendererSettings)
   106                                       CustomRendererSettings)
   106 
   107 
       
   108 
   107 In this example the settings interface adapter is defined with `IContactParagraph` as context
   109 In this example the settings interface adapter is defined with `IContactParagraph` as context
   108 and provide `ICustomRendererSettings`.
   110 and provide `IPhotoRendererSettings`.
   109 
   111 
   110 d) Add settings interface renderer
       
   111 """"""""""""""""""""""""""""""""""
       
   112 
   112 
   113 In the renderer definition:
   113 
       
   114 c) Create an adapter for the render interface
       
   115 """""""""""""""""""""""""""""""""""""""""""""
   114 
   116 
   115 .. code-block:: python
   117 .. code-block:: python
   116         settings_interface = ICustomRendererSettings
   118 
       
   119     @adapter_config(context=(IContactParagraph, IPyAMSLayer), provides=IContentRenderer)
       
   120     @template_config(template='templates/contact-custom.pt', layer=IPyAMSLayer)
       
   121     class PhotoRenderer(BaseContentRenderer):
       
   122         """Context paragraph custom renderer"""
       
   123 
       
   124         label = _("Custom contact renderer")
       
   125         settings_interface = IPhotoRendererSettings
   117 
   126 
   118 
   127 
       
   128 Add settings interface to the renderer `settings_interface = IPhotoRendererSettings`
       
   129 
   119 .. tip::
   130 .. tip::
   120     When a setting_interface is associated to a renderer, you can acces to `settings` attributs through the template
   131     When a setting_interface is associated to a renderer, you can access to `settings` attributes through the template
   121 
   132