# HG changeset patch # User Thierry Florac # Date 1626156055 -7200 # Node ID d9128c1432af1e715f2f0d1228ded3efc849f21b # Parent ecc2ce6a71726d57c2b6e4a440ac6f1c4f51dc7e Added container class to skin configuration diff -r ecc2ce6a7172 -r d9128c1432af src/pyams_skin/interfaces/__init__.py --- a/src/pyams_skin/interfaces/__init__.py Thu May 27 14:15:54 2021 +0200 +++ b/src/pyams_skin/interfaces/__init__.py Tue Jul 13 08:00:55 2021 +0200 @@ -78,6 +78,10 @@ def get_skin(self, request=None): """Get skin matching this content""" + container_class = TextLine(title=_("Container class"), + description=_("Main page container class"), + required=False) + custom_stylesheet = FileField(title=_("Custom stylesheet"), description=_("This custom stylesheet will be used to override selected theme styles"), required=False) diff -r ecc2ce6a7172 -r d9128c1432af src/pyams_skin/skin.py --- a/src/pyams_skin/skin.py Thu May 27 14:15:54 2021 +0200 +++ b/src/pyams_skin/skin.py Tue Jul 13 08:00:55 2021 +0200 @@ -10,30 +10,35 @@ # FOR A PARTICULAR PURPOSE. # -__docformat__ = 'restructuredtext' - import logging -logger = logging.getLogger('PyAMS (skin)') from pyramid.events import subscriber from pyramid.threadlocal import get_current_request from pyramid_zope_request import PyramidPublisherRequest -from zope.interface import implementer, directlyProvidedBy, directlyProvides +from zope.interface import Interface, directlyProvidedBy, directlyProvides, implementer from zope.schema.fieldproperty import FieldProperty from zope.traversing.interfaces import IBeforeTraverseEvent -from pyams_file.interfaces import DELETED_FILE +from pyams_file.interfaces import DELETED_FILE, IFileInfo from pyams_file.property import FileProperty from pyams_skin.interfaces import ISkin, ISkinnable, IUserSkinnable, SkinChangedEvent from pyams_skin.layer import IBaseLayer, IPyAMSLayer +from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config from pyams_utils.interfaces.site import ISiteRoot +from pyams_utils.interfaces.tales import ITALESExtension from pyams_utils.registry import utility_config from pyams_utils.traversing import get_parent from pyams_utils.zodb import volatile_property + +__docformat__ = 'restructuredtext' + from pyams_skin import _ +logger = logging.getLogger('PyAMS (skin)') + + @implementer(ISkinnable) class SkinnableContent(object): """Skinnable content base class""" @@ -41,6 +46,7 @@ _inherit_skin = FieldProperty(ISkinnable['inherit_skin']) _skin = FieldProperty(IUserSkinnable['skin']) + _container_class = FieldProperty(ISkinnable['container_class']) _custom_stylesheet = FileProperty(ISkinnable['custom_stylesheet']) _editor_stylesheet = FileProperty(ISkinnable['editor_stylesheet']) _custom_script = FileProperty(ISkinnable['custom_script']) @@ -89,6 +95,18 @@ del self.skin_parent @property + def container_class(self): + if not self.inherit_skin: + return self._container_class + else: + return self.skin_parent.container_class + + @container_class.setter + def container_class(self, value): + if not self.inherit_skin: + self._container_class = value + + @property def custom_stylesheet(self): if not self.inherit_skin: return self._custom_stylesheet @@ -101,6 +119,7 @@ self._custom_stylesheet = value if value and (value is not DELETED_FILE): self._custom_stylesheet.content_type = 'text/css' + IFileInfo(self._custom_stylesheet).filename = 'skin.css' @property def editor_stylesheet(self): @@ -115,6 +134,7 @@ self._editor_stylesheet = value if value and (value is not DELETED_FILE): self._editor_stylesheet.content_type = 'text/css' + IFileInfo(self._editor_stylesheet).filename = 'editor-skin.css' @property def custom_script(self): @@ -129,6 +149,7 @@ self._custom_script = value if value and (value is not DELETED_FILE): self._custom_script.content_type = 'text/javascript' + IFileInfo(self._custom_stylesheet).filename = 'skin.js' def get_skin(self, request=None): parent = self.skin_parent @@ -142,6 +163,22 @@ return request.registry.queryUtility(ISkin, skin) +@adapter_config(name='container_class', + context=(Interface, IPyAMSLayer, Interface), + provides=ITALESExtension) +class ContainerClassTALESExtension(ContextRequestViewAdapter): + """Container class TALES extension""" + + def render(self, context=None, default=''): + if context is None: + context = self.context + result = default + skin = get_parent(context, ISkinnable) + if skin is not None: + result = skin.container_class or result + return result + + @implementer(IUserSkinnable) class UserSkinnableContent(SkinnableContent): """User skinnable content base class"""