--- 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)
--- 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"""