src/source/dev_guide/custom-skin.rst
branchdoc-dc
changeset 139 d632f8d6140b
parent 124 696f58cb5bdd
child 142 5a82a9a2ea46
equal deleted inserted replaced
138:7205ae7c43dc 139:d632f8d6140b
     4 ===========================
     4 ===========================
     5 
     5 
     6 Understading layers and skins
     6 Understading layers and skins
     7 -----------------------------
     7 -----------------------------
     8 
     8 
       
     9 
       
    10 .. _skinhowto:
       
    11 
     9 Creating a new skin
    12 Creating a new skin
    10 ---------------------
    13 -------------------
    11 
    14 
    12 Adding resources
    15 A Skin is a tagging interface for associating media, javascript and CSS resources to a **renderer**
    13 ----------------
    16 
       
    17 
       
    18 1) Create a new Layer to your skin
       
    19 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       
    20 
       
    21 Build a new interface inherit from `ICustomLayer`
       
    22 
       
    23 .. code-block:: python
       
    24 
       
    25     class ICustomLayer(ICustomLayer):
       
    26         """skin layer"""
       
    27 
       
    28 Define an utility providing ISkin with the custom label and the layer interface
       
    29 
       
    30 .. code-block:: python
       
    31 
       
    32     @utility_config(name='Custom skin', provides=ISkin)
       
    33     class CustomSkin(object):
       
    34         """custom root skin"""
       
    35 
       
    36         label = _("Custom: skin")
       
    37         layer = ICustomLayer
       
    38 
       
    39 
       
    40 2) Declare the layer adapter
       
    41 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       
    42 
       
    43 .. code-block:: python
       
    44 
       
    45     @adapter_config(context=(Interface, ICustomLayer, Interface), provides=IResources)
       
    46     class CustomSkinResourcesAdapter(ContextRequestViewAdapter):
       
    47     """Custom skin resources adapter"""
       
    48 
       
    49         def get_resources(self):
       
    50             mycms.need()
       
    51 
       
    52 
       
    53 We have defined a Multiadapter with context=(context, request, view).
       
    54 
       
    55 .. note::
       
    56 
       
    57     In the ZMI website you can now change the default graphical theme by you custom skin
       
    58 
       
    59     .. image:: ../_static/select_skin.png
       
    60 
       
    61 
       
    62 
       
    63 
       
    64 Adding resources library
       
    65 ------------------------
       
    66 
       
    67 
       
    68 .. code-block:: python
       
    69 
       
    70     from fanstatic import Library, Resource
       
    71     from pyams_default_theme import pyams_default_theme
       
    72 
       
    73     #Library(name, folder_path)
       
    74     library = Library('mycms', 'resources')
       
    75 
       
    76     #Resource(library, path_to_static)
       
    77     mycms_css = Resource(library, 'css/mystyle.css',)
       
    78 
       
    79 
       
    80     mycms_js = Resource(library, 'js/pyams-default.js',
       
    81                         depends=(pyams_default_theme, )
       
    82                         bottom=True
       
    83                         )
       
    84 
       
    85 
       
    86 :py:class:`Resource` can include others resources already defined with *depends* attribute, here `pyams_default_theme`.
       
    87 
    14 
    88 
    15 Overriding templates
    89 Overriding templates
    16 ---------------------
    90 --------------------
       
    91 
       
    92 The simplest is to create a new class that inherits from the existing **Renderer**  and modify this template.
       
    93 After that all you have to define a new adapter name and a new label.
       
    94 
       
    95 
       
    96 .. code-block:: python
       
    97     :linenos:
       
    98 
       
    99     # New custom contact paragraph renderer
       
   100 
       
   101     @adapter_config(name='custom', context=(IContactParagraph, IPyAMSLayer), provides=ISharedContentRenderer)
       
   102     @template_config(template='templates/contact-custom.pt', layer=IPyAMSLayer)
       
   103     class ContactParagraphCustomRenderer(ContactParagraphDefaultRenderer):
       
   104         """Context paragraph custom renderer"""
       
   105 
       
   106         label = _("Custom contact renderer")
       
   107         #settings_interface = IContactParagraphDefaultRendererSettings
       
   108 
       
   109 
       
   110 In this example, we have defined an adapter named 'custom' with :py:class:`IContactParagraph`,
       
   111 :py:class:`IPyAMSLayer` as context and provides :py:class:`ISharedContentRenderer` interface.
       
   112 
       
   113 Using ``@template_config()`` decorator, the renderer will be displayed in html container according to the template
       
   114 `templates/contact-custom.pt`
       
   115 
       
   116 The new renderer inherit of :py:class:`ContactParagraphDefaultRenderer`, have a new **label** (line 8)
       
   117 and this associated **settings_interface** is not modify(line 9)
       
   118 
       
   119 .. tip::
       
   120 
       
   121     You can override the template of a renderer easily with the function :py:func:`pyams_template.template.override_template`
       
   122     It's takes the context and the new template path as params.
       
   123 
       
   124 
    17 
   125 
    18 Creating custom renderer
   126 Creating custom renderer
    19 ------------------------
   127 ------------------------
       
   128 
       
   129 We can define a new settings for the renderer, to do that we start by creating an interface:
       
   130 
       
   131 
       
   132 a) Create setting interface for the renderer
       
   133 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       
   134 
       
   135 .. code-block:: python
       
   136 
       
   137     class IPhotoRendererSettings(Interface):
       
   138         """Custom renderer settings interface"""
       
   139 
       
   140 
       
   141         display_photo = Bool(title=_("Show photo?"),
       
   142                              description=_("Display contact photo"),
       
   143                              required=True,
       
   144                              default=True)
       
   145 
       
   146         can_display_photo = Attribute("Check if photo can be displayed")
       
   147 
       
   148 
       
   149 We have created an interface with two attributes *display_photo* and *can_display_photo*
       
   150 Then we create an implemantation of the interface
       
   151 
       
   152 .. code-block:: python
       
   153 
       
   154     @implementer(IPhotoRendererSettings)
       
   155     class PhotoRendererSettings(Persistent, Location):
       
   156         """Custom renderer settings"""
       
   157 
       
   158         display_photo = FieldProperty(IPhotoRendererSettings['display_photo'])
       
   159 
       
   160         @property
       
   161         def can_display_photo(self):
       
   162             contact = IContactParagraph(self.__parent__)
       
   163             if not contact.photo:
       
   164                 return False
       
   165             return self.display_photo
       
   166 
       
   167 
       
   168 
       
   169 b) Create an adapter for the render setting interface
       
   170 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       
   171 
       
   172 With :py:func:`@adapter_config()` we declare a new adapter that applies to a context and provide the interface of
       
   173  renderer settings
       
   174 
       
   175 .. code-block:: python
       
   176 
       
   177     PHOTO_RENDERER_SETTINGS_KEY = 'pyams_content.contact.renderer:photo'
       
   178 
       
   179     @adapter_config(context=IContactParagraph, provides=IPhotoRendererSettings)
       
   180     def custom_renderer_settings_factory(context):
       
   181         """Contact paragraph default renderer settings factory"""
       
   182         return get_annotation_adapter(context, PHOTO_RENDERER_SETTINGS_KEY,
       
   183                                       CustomRendererSettings)
       
   184 
       
   185 
       
   186 In this example the settings interface adapter is defined with `IContactParagraph` as context
       
   187 and provide `IPhotoRendererSettings`.
       
   188 
       
   189 
       
   190 
       
   191 c) Create an adapter for the render interface
       
   192 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       
   193 
       
   194 .. code-block:: python
       
   195 
       
   196     @adapter_config(context=(IContactParagraph, IPyAMSLayer), provides=ISharedContentRenderer)
       
   197     @template_config(template='templates/contact-custom.pt', layer=IPyAMSLayer)
       
   198     class PhotoRenderer(BaseContentRenderer):
       
   199         """Context paragraph custom renderer"""
       
   200 
       
   201         label = _("Custom contact renderer")
       
   202         settings_interface = IPhotoRendererSettings
       
   203 
       
   204 
       
   205 Add settings interface to the renderer `settings_interface = IPhotoRendererSettings`
       
   206 
       
   207 .. tip::
       
   208     When a setting_interface is associated to a renderer, you can access to `settings` attributes through the template
       
   209