src/pyams_skin/skin.py
changeset 575 d9128c1432af
parent 487 b6218937c5f9
child 579 4b2f978ac363
equal deleted inserted replaced
574:ecc2ce6a7172 575:d9128c1432af
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
    10 # FOR A PARTICULAR PURPOSE.
    10 # FOR A PARTICULAR PURPOSE.
    11 #
    11 #
    12 
    12 
    13 __docformat__ = 'restructuredtext'
       
    14 
       
    15 import logging
    13 import logging
    16 logger = logging.getLogger('PyAMS (skin)')
       
    17 
    14 
    18 from pyramid.events import subscriber
    15 from pyramid.events import subscriber
    19 from pyramid.threadlocal import get_current_request
    16 from pyramid.threadlocal import get_current_request
    20 from pyramid_zope_request import PyramidPublisherRequest
    17 from pyramid_zope_request import PyramidPublisherRequest
    21 from zope.interface import implementer, directlyProvidedBy, directlyProvides
    18 from zope.interface import Interface, directlyProvidedBy, directlyProvides, implementer
    22 from zope.schema.fieldproperty import FieldProperty
    19 from zope.schema.fieldproperty import FieldProperty
    23 from zope.traversing.interfaces import IBeforeTraverseEvent
    20 from zope.traversing.interfaces import IBeforeTraverseEvent
    24 
    21 
    25 from pyams_file.interfaces import DELETED_FILE
    22 from pyams_file.interfaces import DELETED_FILE, IFileInfo
    26 from pyams_file.property import FileProperty
    23 from pyams_file.property import FileProperty
    27 from pyams_skin.interfaces import ISkin, ISkinnable, IUserSkinnable, SkinChangedEvent
    24 from pyams_skin.interfaces import ISkin, ISkinnable, IUserSkinnable, SkinChangedEvent
    28 from pyams_skin.layer import IBaseLayer, IPyAMSLayer
    25 from pyams_skin.layer import IBaseLayer, IPyAMSLayer
       
    26 from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config
    29 from pyams_utils.interfaces.site import ISiteRoot
    27 from pyams_utils.interfaces.site import ISiteRoot
       
    28 from pyams_utils.interfaces.tales import ITALESExtension
    30 from pyams_utils.registry import utility_config
    29 from pyams_utils.registry import utility_config
    31 from pyams_utils.traversing import get_parent
    30 from pyams_utils.traversing import get_parent
    32 from pyams_utils.zodb import volatile_property
    31 from pyams_utils.zodb import volatile_property
    33 
    32 
       
    33 
       
    34 __docformat__ = 'restructuredtext'
       
    35 
    34 from pyams_skin import _
    36 from pyams_skin import _
       
    37 
       
    38 
       
    39 logger = logging.getLogger('PyAMS (skin)')
    35 
    40 
    36 
    41 
    37 @implementer(ISkinnable)
    42 @implementer(ISkinnable)
    38 class SkinnableContent(object):
    43 class SkinnableContent(object):
    39     """Skinnable content base class"""
    44     """Skinnable content base class"""
    40 
    45 
    41     _inherit_skin = FieldProperty(ISkinnable['inherit_skin'])
    46     _inherit_skin = FieldProperty(ISkinnable['inherit_skin'])
    42     _skin = FieldProperty(IUserSkinnable['skin'])
    47     _skin = FieldProperty(IUserSkinnable['skin'])
    43 
    48 
       
    49     _container_class = FieldProperty(ISkinnable['container_class'])
    44     _custom_stylesheet = FileProperty(ISkinnable['custom_stylesheet'])
    50     _custom_stylesheet = FileProperty(ISkinnable['custom_stylesheet'])
    45     _editor_stylesheet = FileProperty(ISkinnable['editor_stylesheet'])
    51     _editor_stylesheet = FileProperty(ISkinnable['editor_stylesheet'])
    46     _custom_script = FileProperty(ISkinnable['custom_script'])
    52     _custom_script = FileProperty(ISkinnable['custom_script'])
    47 
    53 
    48     @property
    54     @property
    87         if not self.inherit_skin:
    93         if not self.inherit_skin:
    88             self._skin = value
    94             self._skin = value
    89         del self.skin_parent
    95         del self.skin_parent
    90 
    96 
    91     @property
    97     @property
       
    98     def container_class(self):
       
    99         if not self.inherit_skin:
       
   100             return self._container_class
       
   101         else:
       
   102             return self.skin_parent.container_class
       
   103 
       
   104     @container_class.setter
       
   105     def container_class(self, value):
       
   106         if not self.inherit_skin:
       
   107             self._container_class = value
       
   108 
       
   109     @property
    92     def custom_stylesheet(self):
   110     def custom_stylesheet(self):
    93         if not self.inherit_skin:
   111         if not self.inherit_skin:
    94             return self._custom_stylesheet
   112             return self._custom_stylesheet
    95         else:
   113         else:
    96             return self.skin_parent.custom_stylesheet
   114             return self.skin_parent.custom_stylesheet
    99     def custom_stylesheet(self, value):
   117     def custom_stylesheet(self, value):
   100         if not self.inherit_skin:
   118         if not self.inherit_skin:
   101             self._custom_stylesheet = value
   119             self._custom_stylesheet = value
   102             if value and (value is not DELETED_FILE):
   120             if value and (value is not DELETED_FILE):
   103                 self._custom_stylesheet.content_type = 'text/css'
   121                 self._custom_stylesheet.content_type = 'text/css'
       
   122                 IFileInfo(self._custom_stylesheet).filename = 'skin.css'
   104 
   123 
   105     @property
   124     @property
   106     def editor_stylesheet(self):
   125     def editor_stylesheet(self):
   107         if not self.inherit_skin:
   126         if not self.inherit_skin:
   108             return self._editor_stylesheet
   127             return self._editor_stylesheet
   113     def editor_stylesheet(self, value):
   132     def editor_stylesheet(self, value):
   114         if not self.inherit_skin:
   133         if not self.inherit_skin:
   115             self._editor_stylesheet = value
   134             self._editor_stylesheet = value
   116             if value and (value is not DELETED_FILE):
   135             if value and (value is not DELETED_FILE):
   117                 self._editor_stylesheet.content_type = 'text/css'
   136                 self._editor_stylesheet.content_type = 'text/css'
       
   137                 IFileInfo(self._editor_stylesheet).filename = 'editor-skin.css'
   118 
   138 
   119     @property
   139     @property
   120     def custom_script(self):
   140     def custom_script(self):
   121         if not self.inherit_skin:
   141         if not self.inherit_skin:
   122             return self._custom_script
   142             return self._custom_script
   127     def custom_script(self, value):
   147     def custom_script(self, value):
   128         if not self.inherit_skin:
   148         if not self.inherit_skin:
   129             self._custom_script = value
   149             self._custom_script = value
   130             if value and (value is not DELETED_FILE):
   150             if value and (value is not DELETED_FILE):
   131                 self._custom_script.content_type = 'text/javascript'
   151                 self._custom_script.content_type = 'text/javascript'
       
   152                 IFileInfo(self._custom_stylesheet).filename = 'skin.js'
   132 
   153 
   133     def get_skin(self, request=None):
   154     def get_skin(self, request=None):
   134         parent = self.skin_parent
   155         parent = self.skin_parent
   135         if parent is self:
   156         if parent is self:
   136             return self.skin
   157             return self.skin
   140                 if request is None:
   161                 if request is None:
   141                     request = get_current_request()
   162                     request = get_current_request()
   142                 return request.registry.queryUtility(ISkin, skin)
   163                 return request.registry.queryUtility(ISkin, skin)
   143 
   164 
   144 
   165 
       
   166 @adapter_config(name='container_class',
       
   167                 context=(Interface, IPyAMSLayer, Interface),
       
   168                 provides=ITALESExtension)
       
   169 class ContainerClassTALESExtension(ContextRequestViewAdapter):
       
   170     """Container class TALES extension"""
       
   171 
       
   172     def render(self, context=None, default=''):
       
   173         if context is None:
       
   174             context = self.context
       
   175         result = default
       
   176         skin = get_parent(context, ISkinnable)
       
   177         if skin is not None:
       
   178             result = skin.container_class or result
       
   179         return result
       
   180 
       
   181 
   145 @implementer(IUserSkinnable)
   182 @implementer(IUserSkinnable)
   146 class UserSkinnableContent(SkinnableContent):
   183 class UserSkinnableContent(SkinnableContent):
   147     """User skinnable content base class"""
   184     """User skinnable content base class"""
   148 
   185 
   149 
   186