10 # FOR A PARTICULAR PURPOSE. |
10 # FOR A PARTICULAR PURPOSE. |
11 # |
11 # |
12 |
12 |
13 __docformat__ = 'restructuredtext' |
13 __docformat__ = 'restructuredtext' |
14 |
14 |
15 # import standard library |
|
16 import logging |
15 import logging |
17 logger = logging.getLogger('PyAMS (skin)') |
16 logger = logging.getLogger('PyAMS (skin)') |
18 |
17 |
19 # import interfaces |
|
20 from pyams_skin.interfaces import ISkin, ISkinnable, IUserSkinnable, SkinChangedEvent |
|
21 from pyams_skin.layer import IBaseLayer, IPyAMSLayer |
|
22 from pyams_utils.interfaces.site import ISiteRoot |
|
23 from zope.traversing.interfaces import IBeforeTraverseEvent |
|
24 |
|
25 # import packages |
|
26 from pyams_utils.registry import utility_config |
|
27 from pyams_utils.traversing import get_parent |
|
28 from pyams_utils.zodb import volatile_property |
|
29 from pyramid.events import subscriber |
18 from pyramid.events import subscriber |
30 from pyramid.threadlocal import get_current_request |
19 from pyramid.threadlocal import get_current_request |
31 from pyramid_zope_request import PyramidPublisherRequest |
20 from pyramid_zope_request import PyramidPublisherRequest |
32 from zope.interface import implementer, directlyProvidedBy, directlyProvides |
21 from zope.interface import implementer, directlyProvidedBy, directlyProvides |
33 from zope.schema.fieldproperty import FieldProperty |
22 from zope.schema.fieldproperty import FieldProperty |
|
23 from zope.traversing.interfaces import IBeforeTraverseEvent |
|
24 |
|
25 from pyams_file.interfaces import DELETED_FILE |
|
26 from pyams_file.property import FileProperty |
|
27 from pyams_skin.interfaces import ISkin, ISkinnable, IUserSkinnable, SkinChangedEvent |
|
28 from pyams_skin.layer import IBaseLayer, IPyAMSLayer |
|
29 from pyams_utils.interfaces.site import ISiteRoot |
|
30 from pyams_utils.registry import utility_config |
|
31 from pyams_utils.traversing import get_parent |
|
32 from pyams_utils.zodb import volatile_property |
34 |
33 |
35 from pyams_skin import _ |
34 from pyams_skin import _ |
36 |
35 |
37 |
36 |
38 @implementer(ISkinnable) |
37 @implementer(ISkinnable) |
39 class SkinnableContent(object): |
38 class SkinnableContent(object): |
40 """Skinnable content base class""" |
39 """Skinnable content base class""" |
41 |
40 |
42 _inherit_skin = FieldProperty(ISkinnable['inherit_skin']) |
41 _inherit_skin = FieldProperty(ISkinnable['inherit_skin']) |
43 _skin = FieldProperty(IUserSkinnable['skin']) |
42 _skin = FieldProperty(IUserSkinnable['skin']) |
|
43 |
|
44 _custom_stylesheet = FileProperty(ISkinnable['custom_stylesheet']) |
|
45 _editor_stylesheet = FileProperty(ISkinnable['editor_stylesheet']) |
|
46 _custom_script = FileProperty(ISkinnable['custom_script']) |
44 |
47 |
45 @property |
48 @property |
46 def can_inherit_skin(self): |
49 def can_inherit_skin(self): |
47 return get_parent(self, ISkinnable, allow_context=False) is not None |
50 return get_parent(self, ISkinnable, allow_context=False) is not None |
48 |
51 |
61 return not bool(self.inherit_skin) |
64 return not bool(self.inherit_skin) |
62 |
65 |
63 @no_inherit_skin.setter |
66 @no_inherit_skin.setter |
64 def no_inherit_skin(self, value): |
67 def no_inherit_skin(self, value): |
65 self.inherit_skin = not bool(value) |
68 self.inherit_skin = not bool(value) |
66 |
|
67 @property |
|
68 def skin(self): |
|
69 if not self.inherit_skin: |
|
70 return self._skin |
|
71 else: |
|
72 return self.skin_parent.skin |
|
73 |
|
74 @skin.setter |
|
75 def skin(self, value): |
|
76 if not self.inherit_skin: |
|
77 self._skin = value |
|
78 del self.skin_parent |
|
79 |
69 |
80 @volatile_property |
70 @volatile_property |
81 def skin_parent(self): |
71 def skin_parent(self): |
82 if (not self._inherit_skin) and self.skin: |
72 if (not self._inherit_skin) and self.skin: |
83 return self |
73 return self |
84 parent = get_parent(self, ISkinnable, allow_context=False) |
74 parent = get_parent(self, ISkinnable, allow_context=False) |
85 if parent is not None: |
75 if parent is not None: |
86 return parent.skin_parent |
76 return parent.skin_parent |
|
77 |
|
78 @property |
|
79 def skin(self): |
|
80 if not self.inherit_skin: |
|
81 return self._skin |
|
82 else: |
|
83 return self.skin_parent.skin |
|
84 |
|
85 @skin.setter |
|
86 def skin(self, value): |
|
87 if not self.inherit_skin: |
|
88 self._skin = value |
|
89 del self.skin_parent |
|
90 |
|
91 @property |
|
92 def custom_stylesheet(self): |
|
93 if not self.inherit_skin: |
|
94 return self._custom_stylesheet |
|
95 else: |
|
96 return self.skin_parent.custom_stylesheet |
|
97 |
|
98 @custom_stylesheet.setter |
|
99 def custom_stylesheet(self, value): |
|
100 if not self.inherit_skin: |
|
101 self._custom_stylesheet = value |
|
102 if value and (value is not DELETED_FILE): |
|
103 self._custom_stylesheet.content_type = 'text/css' |
|
104 |
|
105 @property |
|
106 def editor_stylesheet(self): |
|
107 if not self.inherit_skin: |
|
108 return self._editor_stylesheet |
|
109 else: |
|
110 return self.skin_parent.editor_stylesheet |
|
111 |
|
112 @editor_stylesheet.setter |
|
113 def editor_stylesheet(self, value): |
|
114 if not self.inherit_skin: |
|
115 self._editor_stylesheet = value |
|
116 if value and (value is not DELETED_FILE): |
|
117 self._editor_stylesheet.content_type = 'text/css' |
|
118 |
|
119 @property |
|
120 def custom_script(self): |
|
121 if not self.inherit_skin: |
|
122 return self._custom_script |
|
123 else: |
|
124 return self.skin_parent.custom_script |
|
125 |
|
126 @custom_script.setter |
|
127 def custom_script(self, value): |
|
128 if not self.inherit_skin: |
|
129 self._custom_script = value |
|
130 if value and (value is not DELETED_FILE): |
|
131 self._custom_script.content_type = 'text/javascript' |
87 |
132 |
88 def get_skin(self, request=None): |
133 def get_skin(self, request=None): |
89 parent = self.skin_parent |
134 parent = self.skin_parent |
90 if parent is self: |
135 if parent is self: |
91 return self.skin |
136 return self.skin |