diff -r 7205ae7c43dc -r d632f8d6140b src/source/dev_guide/custom-skin.rst --- a/src/source/dev_guide/custom-skin.rst Thu Dec 20 17:59:43 2018 +0100 +++ b/src/source/dev_guide/custom-skin.rst Fri Dec 21 15:20:06 2018 +0100 @@ -6,14 +6,204 @@ Understading layers and skins ----------------------------- + +.. _skinhowto: + Creating a new skin ---------------------- +------------------- + +A Skin is a tagging interface for associating media, javascript and CSS resources to a **renderer** + + +1) Create a new Layer to your skin +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Build a new interface inherit from `ICustomLayer` + +.. code-block:: python + + class ICustomLayer(ICustomLayer): + """skin layer""" + +Define an utility providing ISkin with the custom label and the layer interface + +.. code-block:: python + + @utility_config(name='Custom skin', provides=ISkin) + class CustomSkin(object): + """custom root skin""" + + label = _("Custom: skin") + layer = ICustomLayer + + +2) Declare the layer adapter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: python + + @adapter_config(context=(Interface, ICustomLayer, Interface), provides=IResources) + class CustomSkinResourcesAdapter(ContextRequestViewAdapter): + """Custom skin resources adapter""" -Adding resources ----------------- + def get_resources(self): + mycms.need() + + +We have defined a Multiadapter with context=(context, request, view). + +.. note:: + + In the ZMI website you can now change the default graphical theme by you custom skin + + .. image:: ../_static/select_skin.png + + + + +Adding resources library +------------------------ + + +.. code-block:: python + + from fanstatic import Library, Resource + from pyams_default_theme import pyams_default_theme + + #Library(name, folder_path) + library = Library('mycms', 'resources') + + #Resource(library, path_to_static) + mycms_css = Resource(library, 'css/mystyle.css',) + + + mycms_js = Resource(library, 'js/pyams-default.js', + depends=(pyams_default_theme, ) + bottom=True + ) + + +:py:class:`Resource` can include others resources already defined with *depends* attribute, here `pyams_default_theme`. + Overriding templates ---------------------- +-------------------- + +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=ISharedContentRenderer) + @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:`ISharedContentRenderer` interface. + +Using ``@template_config()`` decorator, the renderer will be displayed in html container according to the template +`templates/contact-custom.pt` + +The new renderer inherit of :py:class:`ContactParagraphDefaultRenderer`, have a new **label** (line 8) +and this associated **settings_interface** is not modify(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. + + Creating custom renderer ------------------------ + +We can define a new settings 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=ISharedContentRenderer) + @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 +