--- a/src/pyams_content/component/gallery/__init__.py Sun Feb 11 12:11:05 2018 +0100
+++ b/src/pyams_content/component/gallery/__init__.py Thu Feb 15 15:08:29 2018 +0100
@@ -16,8 +16,8 @@
# import standard library
# import interfaces
-from pyams_content.component.gallery.interfaces import IGallery, IGalleryTarget, \
- GALLERY_CONTAINER_KEY, IGalleryRenderer
+from pyams_content.component.gallery.interfaces import IBaseGallery, IGallery, IGalleryTarget, \
+ GALLERY_CONTAINER_KEY
from pyams_content.component.paragraph import IBaseParagraph
from pyams_content.features.checker.interfaces import IContentChecker
from pyams_content.shared.common.interfaces import IWfSharedContent
@@ -31,18 +31,16 @@
# import packages
from pyams_catalog.utils import index_object
from pyams_content.features.checker import BaseContentChecker
+from pyams_content.features.renderer import RenderedContentMixin
from pyams_utils.adapter import adapter_config, ContextAdapter
from pyams_utils.container import BTreeOrderedContainer
-from pyams_utils.request import check_request
from pyams_utils.traversing import get_parent
-from pyams_utils.vocabulary import vocabulary_config
from pyramid.events import subscriber
from pyramid.threadlocal import get_current_registry
from zope.interface import implementer
from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent
from zope.location import locate
from zope.schema.fieldproperty import FieldProperty
-from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
from pyams_content import _
@@ -52,7 +50,7 @@
#
@implementer(IGallery)
-class Gallery(BTreeOrderedContainer):
+class Gallery(BTreeOrderedContainer, RenderedContentMixin):
"""Gallery persistent class"""
title = FieldProperty(IGallery['title'])
@@ -179,18 +177,3 @@
def GalleryTargetContentChecker(context):
gallery = IGallery(context)
return IContentChecker(gallery, None)
-
-
-@vocabulary_config(name='PyAMS gallery renderers')
-class GalleryRendererVocabulary(SimpleVocabulary):
- """Gallery renderer utilities vocabulary"""
-
- def __init__(self, context=None):
- request = check_request()
- translate = request.localizer.translate
- registry = request.registry
- context = Gallery()
- terms = [SimpleTerm(name, title=translate(adapter.label))
- for name, adapter in sorted(registry.getAdapters((context, request), IGalleryRenderer),
- key=lambda x: x[1].weight)]
- super(GalleryRendererVocabulary, self).__init__(terms)
--- a/src/pyams_content/component/gallery/interfaces/__init__.py Sun Feb 11 12:11:05 2018 +0100
+++ b/src/pyams_content/component/gallery/interfaces/__init__.py Thu Feb 15 15:08:29 2018 +0100
@@ -17,15 +17,15 @@
# import interfaces
from pyams_content.component.paragraph.interfaces import IBaseParagraph
+from pyams_content.features.renderer.interfaces import IRenderedContent
from zope.container.interfaces import IOrderedContainer
-from zope.contentprovider.interfaces import IContentProvider
# import packages
from pyams_file.schema import MediaField, AudioField
from pyams_i18n.schema import I18nTextLineField, I18nTextField
from zope.annotation.interfaces import IAttributeAnnotatable
from zope.container.constraints import contains, containers
-from zope.interface import Interface, Attribute
+from zope.interface import Interface
from zope.schema import Bool, TextLine, Choice
from pyams_content import _
@@ -34,11 +34,15 @@
GALLERY_CONTAINER_KEY = 'pyams_content.gallery'
-class IGalleryFile(Interface):
- """Gallery file marker interface"""
+class IGalleryItem(Interface):
+ """Gallery item base interface"""
containers('.IGallery')
+
+class IGalleryFile(IGalleryItem):
+ """Gallery file marker interface"""
+
title = I18nTextLineField(title=_("Legend"),
required=False)
@@ -83,7 +87,7 @@
default=True)
-class IBaseGallery(IOrderedContainer, IAttributeAnnotatable):
+class IBaseGallery(IOrderedContainer, IAttributeAnnotatable, IRenderedContent):
"""Base gallery interface"""
title = I18nTextLineField(title=_("Title"),
@@ -113,13 +117,7 @@
class IGallery(IBaseGallery):
"""Gallery interface"""
- contains(IGalleryFile)
-
-
-class IGalleryRenderer(IContentProvider):
- """Gallery renderer utility interface"""
-
- label = Attribute("Renderer label")
+ contains(IGalleryItem)
class IGalleryTarget(IAttributeAnnotatable):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/component/gallery/renderer.py Thu Feb 15 15:08:29 2018 +0100
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+
+# import interfaces
+from pyams_content.component.gallery.interfaces import IBaseGallery
+from pyams_content.features.renderer.interfaces import IContentRenderer
+
+# import packages
+from pyams_content.component.gallery import Gallery
+from pyams_utils.request import check_request
+from pyams_utils.vocabulary import vocabulary_config
+from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
+
+
+@vocabulary_config(name='PyAMS gallery renderers')
+class GalleryRendererVocabulary(SimpleVocabulary):
+ """Gallery renderer utilities vocabulary"""
+
+ def __init__(self, context=None):
+ request = check_request()
+ translate = request.localizer.translate
+ registry = request.registry
+ if not IBaseGallery.providedBy(context):
+ context = Gallery()
+ terms = [SimpleTerm(name, title=translate(adapter.label))
+ for name, adapter in sorted(registry.getAdapters((context, request), IContentRenderer),
+ key=lambda x: x[1].weight)]
+ super(GalleryRendererVocabulary, self).__init__(terms)
--- a/src/pyams_content/component/gallery/zmi/__init__.py Sun Feb 11 12:11:05 2018 +0100
+++ b/src/pyams_content/component/gallery/zmi/__init__.py Thu Feb 15 15:08:29 2018 +0100
@@ -20,8 +20,9 @@
from io import BytesIO
# import interfaces
-from pyams_content.component.gallery.interfaces import IGallery, IGalleryRenderer
+from pyams_content.component.gallery.interfaces import IGallery
from pyams_content.component.gallery.zmi.interfaces import IGalleryMediasAddFields, IGalleryContentsView
+from pyams_content.features.renderer.interfaces import IContentRenderer
from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
from pyams_file.interfaces import IFileInfo
from pyams_form.interfaces.form import IWidgetsPrefixViewletsManager
@@ -32,10 +33,12 @@
# import packages
from pyams_content.shared.common.zmi import WfSharedContentPermissionMixin
+from pyams_content.features.renderer.zmi import BaseContentRenderer
+from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
from pyams_form.form import AJAXEditForm
from pyams_pagelet.pagelet import pagelet_config
-from pyams_template.template import template_config, get_view_template
-from pyams_utils.adapter import adapter_config, ContextRequestAdapter
+from pyams_template.template import template_config
+from pyams_utils.adapter import adapter_config
from pyams_utils.url import absolute_url
from pyams_viewlet.viewlet import viewlet_config, Viewlet
from pyams_zmi.form import AdminDialogEditForm, AdminDialogDisplayForm
@@ -61,6 +64,8 @@
icon_css_class = 'fa fa-fw fa-picture-o'
fields = field.Fields(IGallery).omit('__parent__', '__file__')
+ fields['renderer'].widgetFactory = RendererFieldWidget
+
ajax_handler = 'properties.json'
edit_permission = MANAGE_CONTENT_PERMISSION
@@ -154,28 +159,6 @@
#
-# Gallery renderers
-#
-
-class BaseGalleryRenderer(ContextRequestAdapter):
- """Base gallery renderer"""
-
- def update(self):
- pass
-
- render = get_view_template()
-
-
-@adapter_config(name='default', context=(IGallery, IPyAMSLayer), provides=IGalleryRenderer)
-@template_config(template='templates/renderer-default.pt', layer=IPyAMSLayer)
-class DefaultGalleryRenderer(BaseGalleryRenderer):
- """Default gallery renderer"""
-
- label = _("Default gallery renderer")
- weight = 1
-
-
-#
# Gallery medias downloader
#
--- a/src/pyams_content/component/gallery/zmi/paragraph.py Sun Feb 11 12:11:05 2018 +0100
+++ b/src/pyams_content/component/gallery/zmi/paragraph.py Thu Feb 15 15:08:29 2018 +0100
@@ -15,10 +15,8 @@
# import standard library
-from datetime import datetime
-
# import interfaces
-from pyams_content.component.gallery.interfaces import IGalleryParagraph, IBaseGallery, IGalleryRenderer
+from pyams_content.component.gallery.interfaces import IGalleryParagraph, IBaseGallery
from pyams_content.component.gallery.zmi.interfaces import IGalleryContentsView
from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
IParagraphSummary
@@ -35,6 +33,7 @@
from pyams_content.component.gallery.paragraph import Gallery
from pyams_content.component.paragraph.zmi import BaseParagraphAJAXAddForm, BaseParagraphAJAXEditForm, \
BaseParagraphAddMenu, BaseParagraphPropertiesEditForm
+from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
from pyams_content.shared.common.zmi import WfSharedContentPermissionMixin
from pyams_pagelet.pagelet import pagelet_config
from pyams_skin.viewlet.toolbar import ToolbarAction
@@ -100,6 +99,8 @@
icon_css_class = 'fa fa-fw fa-picture-o'
fields = field.Fields(IGalleryParagraph).omit('__parent__', '__name__', 'visible')
+ fields['renderer'].widgetFactory = RendererFieldWidget
+
ajax_handler = 'properties.json'
edit_permission = MANAGE_CONTENT_PERMISSION
@@ -192,8 +193,7 @@
def __init__(self, context, request):
super(GalleryParagraphSummary, self).__init__(context, request)
- self.renderer = request.registry.queryMultiAdapter((context, request), IGalleryRenderer,
- name=self.context.renderer)
+ self.renderer = self.context.get_renderer(request)
language = None
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/component/gallery/zmi/renderer.py Thu Feb 15 15:08:29 2018 +0100
@@ -0,0 +1,41 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+
+# import interfaces
+from pyams_content.component.gallery import IGallery
+from pyams_content.features.renderer.interfaces import IContentRenderer
+from pyams_skin.layer import IPyAMSLayer
+
+# import packages
+from pyams_content.features.renderer.zmi import BaseContentRenderer
+from pyams_template.template import template_config
+from pyams_utils.adapter import adapter_config
+
+from pyams_content import _
+
+
+class BaseGalleryRenderer(BaseContentRenderer):
+ """Base gallery renderer"""
+
+
+@adapter_config(name='default', context=(IGallery, IPyAMSLayer), provides=IContentRenderer)
+@template_config(template='templates/renderer-default.pt', layer=IPyAMSLayer)
+class DefaultGalleryRenderer(BaseGalleryRenderer):
+ """Default gallery renderer"""
+
+ label = _("Default gallery renderer")
+ weight = 1
--- a/src/pyams_content/component/illustration/__init__.py Sun Feb 11 12:11:05 2018 +0100
+++ b/src/pyams_content/component/illustration/__init__.py Thu Feb 15 15:08:29 2018 +0100
@@ -16,7 +16,7 @@
# import standard library
# import interfaces
-from pyams_content.component.illustration.interfaces import IIllustrationRenderer, IIllustration, IIllustrationTarget, \
+from pyams_content.component.illustration.interfaces import IIllustration, IIllustrationTarget, \
ILLUSTRATION_KEY
from pyams_content.features.checker.interfaces import IContentChecker, MISSING_VALUE, MISSING_LANG_VALUE
from pyams_file.interfaces import IFileInfo, IImage, IResponsiveImage
@@ -29,12 +29,12 @@
# import packages
from persistent import Persistent
from pyams_content.features.checker import BaseContentChecker
+from pyams_content.features.renderer import RenderedContentMixin
from pyams_i18n.property import I18nFileProperty
from pyams_utils.adapter import adapter_config, ContextAdapter
from pyams_utils.registry import query_utility, get_utility
from pyams_utils.request import check_request
from pyams_utils.traversing import get_parent
-from pyams_utils.vocabulary import vocabulary_config
from pyramid.events import subscriber
from pyramid.threadlocal import get_current_registry
from zope.container.contained import Contained
@@ -42,13 +42,12 @@
from zope.lifecycleevent import ObjectCreatedEvent, ObjectAddedEvent
from zope.location import locate
from zope.schema.fieldproperty import FieldProperty
-from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
from pyams_content import _
@implementer(IIllustration)
-class Illustration(Persistent, Contained):
+class Illustration(Persistent, Contained, RenderedContentMixin):
"""Illustration persistent class"""
title = FieldProperty(IIllustration['title'])
@@ -67,7 +66,7 @@
@data.setter
def data(self, value):
self._data = value
- for data in self._data.values():
+ for data in (self._data or {}).values():
if IImage.providedBy(data):
alsoProvides(data, IResponsiveImage)
@@ -181,18 +180,3 @@
illustration = IIllustration(context, None)
if illustration is not None:
return IContentChecker(illustration)
-
-
-@vocabulary_config(name='PyAMS illustration renderers')
-class IllustrationRendererVocabulary(SimpleVocabulary):
- """Illustration renderer utilities vocabulary"""
-
- def __init__(self, context=None):
- request = check_request()
- translate = request.localizer.translate
- registry = request.registry
- context = Illustration()
- terms = [SimpleTerm(name, title=translate(adapter.label))
- for name, adapter in sorted(registry.getAdapters((context, request), IIllustrationRenderer),
- key=lambda x: x[1].weight)]
- super(IllustrationRendererVocabulary, self).__init__(terms)
--- a/src/pyams_content/component/illustration/interfaces/__init__.py Sun Feb 11 12:11:05 2018 +0100
+++ b/src/pyams_content/component/illustration/interfaces/__init__.py Thu Feb 15 15:08:29 2018 +0100
@@ -17,12 +17,11 @@
# import interfaces
from pyams_content.component.paragraph.interfaces import IBaseParagraph
+from pyams_content.features.renderer.interfaces import IRenderedContent
from pyams_i18n.schema import I18nTextLineField, I18nTextField, I18nThumbnailMediaField
from zope.annotation.interfaces import IAttributeAnnotatable
-from zope.contentprovider.interfaces import IContentProvider
# import packages
-from zope.interface import Interface, Attribute
from zope.schema import Choice, TextLine
from pyams_content import _
@@ -35,7 +34,7 @@
ILLUSTRATION_KEY = 'pyams_content.illustration'
-class IIllustration(Interface):
+class IIllustration(IRenderedContent):
"""Illustration paragraph"""
title = I18nTextLineField(title=_("Legend"),
@@ -63,7 +62,8 @@
renderer = Choice(title=_("Illustration template"),
description=_("Presentation template used for illustration"),
- vocabulary='PyAMS illustration renderers')
+ vocabulary='PyAMS illustration renderers',
+ default='hidden')
language = Choice(title=_("Language"),
description=_("File's content language"),
@@ -75,12 +75,6 @@
"""Illustration target marker interface"""
-class IIllustrationRenderer(IContentProvider):
- """Illustration renderer utility interface"""
-
- label = Attribute("Renderer label")
-
-
class IIllustrationParagraph(IIllustration, IBaseParagraph):
"""Illustration paragraph"""
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/component/illustration/renderer.py Thu Feb 15 15:08:29 2018 +0100
@@ -0,0 +1,41 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+
+# import interfaces
+from pyams_content.features.renderer.interfaces import IContentRenderer
+
+# import packages
+from pyams_content.component.illustration import Illustration, IIllustration
+from pyams_utils.request import check_request
+from pyams_utils.vocabulary import vocabulary_config
+from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
+
+
+@vocabulary_config(name='PyAMS illustration renderers')
+class IllustrationRendererVocabulary(SimpleVocabulary):
+ """Illustration renderer utilities vocabulary"""
+
+ def __init__(self, context=None):
+ request = check_request()
+ translate = request.localizer.translate
+ registry = request.registry
+ if not IIllustration.providedBy(context):
+ context = Illustration()
+ terms = [SimpleTerm(name, title=translate(adapter.label))
+ for name, adapter in sorted(registry.getAdapters((context, request), IContentRenderer),
+ key=lambda x: x[1].weight)]
+ super(IllustrationRendererVocabulary, self).__init__(terms)
--- a/src/pyams_content/component/illustration/zmi/__init__.py Sun Feb 11 12:11:05 2018 +0100
+++ b/src/pyams_content/component/illustration/zmi/__init__.py Thu Feb 15 15:08:29 2018 +0100
@@ -16,10 +16,9 @@
# import standard library
# import interfaces
-from pyams_content.component.illustration.interfaces import IIllustration, IIllustrationRenderer, IIllustrationTarget
+from pyams_content.component.illustration.interfaces import IIllustration, IIllustrationTarget
from pyams_content.component.paragraph.zmi.interfaces import IParagraphContainerTable, IParagraphTitleToolbar
from pyams_form.interfaces.form import IInnerSubForm, IWidgetsPrefixViewletsManager
-from pyams_i18n.interfaces import II18n
from pyams_skin.layer import IPyAMSLayer
from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION
from pyams_utils.interfaces.data import IObjectData
@@ -27,11 +26,12 @@
from transaction.interfaces import ITransactionManager
# import packages
+from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
from pyams_content.skin import pyams_content
from pyams_form.security import ProtectedFormObjectMixin
from pyams_skin.viewlet.toolbar import JsToolbarAction
-from pyams_template.template import get_view_template, template_config
-from pyams_utils.adapter import ContextRequestAdapter, adapter_config
+from pyams_template.template import template_config
+from pyams_utils.adapter import adapter_config
from pyams_utils.fanstatic import get_resource_path
from pyams_viewlet.viewlet import viewlet_config, Viewlet
from pyams_zmi.form import InnerAdminEditForm
@@ -42,63 +42,6 @@
#
-# Illustration renderers
-#
-
-class BaseIllustrationRenderer(ContextRequestAdapter):
- """Base illustration renderer"""
-
- language = None
-
- def update(self):
- i18n = II18n(self.context)
- if self.language:
- self.legend = i18n.get_attribute('alt_title', self.language, request=self.request)
- else:
- self.legend = i18n.query_attribute('alt_title', request=self.request)
-
- render = get_view_template()
-
-
-@adapter_config(name='hidden', context=(IIllustration, IPyAMSLayer), provides=IIllustrationRenderer)
-class HiddenIllustrationRenderer(BaseIllustrationRenderer):
- """Hidden illustration renderer"""
-
- label = _("Hidden illustration")
- weight = -999
-
- def render(self):
- return ''
-
-
-@adapter_config(name='default', context=(IIllustration, IPyAMSLayer), provides=IIllustrationRenderer)
-@template_config(template='templates/renderer-default.pt', layer=IPyAMSLayer)
-class DefaultIllustrationRenderer(BaseIllustrationRenderer):
- """Default illustration renderer"""
-
- label = _("Centered illustration")
- weight = 1
-
-
-@adapter_config(name='left+zoom', context=(IIllustration, IPyAMSLayer), provides=IIllustrationRenderer)
-@template_config(template='templates/renderer-left.pt', layer=IPyAMSLayer)
-class LeftIllustrationWithZoomRenderer(BaseIllustrationRenderer):
- """Illustrtaion renderer with small image and zoom"""
-
- label = _("Small illustration on the left with zoom")
- weight = 2
-
-
-@adapter_config(name='right+zoom', context=(IIllustration, IPyAMSLayer), provides=IIllustrationRenderer)
-@template_config(template='templates/renderer-right.pt', layer=IPyAMSLayer)
-class RightIllustrationWithZoomRenderer(BaseIllustrationRenderer):
- """Illustrtaion renderer with small image and zoom"""
-
- label = _("Small illustration on the right with zoom")
- weight = 3
-
-
-#
# Illustration properties inner edit form
#
@@ -138,6 +81,8 @@
legend_class = 'illustration switcher no-y-padding padding-right-10 pull-left width-auto'
fields = field.Fields(IIllustration).omit('__parent__', '__name__')
+ fields['renderer'].widgetFactory = RendererFieldWidget
+
hide_widgets_prefix_div = True
weight = 10
@@ -155,7 +100,8 @@
def get_ajax_output(self, changes):
output = super(IllustrationPropertiesInnerEditForm, self).get_ajax_output(changes)
- if 'data' in changes.get(IIllustration, ()):
+ illustration_changes = changes.get(IIllustration, ())
+ if ('data' in illustration_changes) or ('renderer' in illustration_changes):
# we have to commit transaction to be able to handle blobs...
ITransactionManager(self.context).get().commit()
form = IllustrationPropertiesInnerEditForm(self.context, self.request)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/component/illustration/zmi/interfaces.py Thu Feb 15 15:08:29 2018 +0100
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+# import standard library
+
+# import interfaces
+
+# import packages
+from zope.interface import Interface
+from zope.schema import Bool
+
+from pyams_content import _
+
+
+class IIllustrationWithZoomSettings(Interface):
+ """Illustration with zoom interface"""
+
+ zoom_on_click = Bool(title=_("Zoom on click?"),
+ description=_("If 'yes', a click on illustration thumbnail is required to zoom"),
+ required=True,
+ default=True)
--- a/src/pyams_content/component/illustration/zmi/paragraph.py Sun Feb 11 12:11:05 2018 +0100
+++ b/src/pyams_content/component/illustration/zmi/paragraph.py Thu Feb 15 15:08:29 2018 +0100
@@ -18,7 +18,7 @@
# import interfaces
from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, \
IParagraphContainer, IParagraphSummary
-from pyams_content.component.illustration.interfaces import IIllustrationRenderer, IIllustration, IIllustrationParagraph
+from pyams_content.component.illustration.interfaces import IIllustration, IIllustrationParagraph
from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor, IParagraphContainerView
from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
from pyams_form.interfaces.form import IInnerForm, IEditFormButtons
@@ -32,6 +32,7 @@
from pyams_content.component.illustration.paragraph import Illustration
from pyams_content.component.paragraph.zmi import BaseParagraphAJAXAddForm, BaseParagraphAJAXEditForm, \
BaseParagraphAddMenu, BaseParagraphPropertiesEditForm
+from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
from pyams_pagelet.pagelet import pagelet_config
from pyams_utils.adapter import adapter_config
from pyams_viewlet.viewlet import viewlet_config, BaseContentProvider
@@ -99,6 +100,8 @@
icon_css_class = 'fa fa-fw fa-file-image-o'
fields = field.Fields(IIllustrationParagraph).omit('__parent__', '__name__', 'visible')
+ fields['renderer'].widgetFactory = RendererFieldWidget
+
ajax_handler = 'properties.json'
edit_permission = MANAGE_CONTENT_PERMISSION
@@ -191,8 +194,7 @@
def __init__(self, context, request):
super(IllustrationSummary, self).__init__(context, request)
- self.renderer = request.registry.queryMultiAdapter((context, request), IIllustrationRenderer,
- name=self.context.renderer)
+ self.renderer = self.context.get_renderer()
language = None
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/component/illustration/zmi/renderer.py Thu Feb 15 15:08:29 2018 +0100
@@ -0,0 +1,119 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+from persistent import Persistent
+
+# import interfaces
+from pyams_content.component.illustration.interfaces import IIllustration
+from pyams_content.component.illustration.zmi.interfaces import IIllustrationWithZoomSettings
+from pyams_i18n.interfaces import II18n
+from pyams_content.features.renderer.interfaces import IContentRenderer
+from pyams_skin.layer import IPyAMSLayer
+from zope.annotation.interfaces import IAnnotations
+
+# import packages
+from pyams_content.features.renderer.zmi import BaseContentRenderer
+from pyams_template.template import template_config
+from pyams_utils.adapter import adapter_config
+from zope.interface import implementer
+from zope.location import locate, Location
+from zope.schema.fieldproperty import FieldProperty
+
+from pyams_content import _
+
+
+#
+# Illustration renderers
+#
+
+class BaseIllustrationRenderer(BaseContentRenderer):
+ """Base illustration renderer"""
+
+ language = None
+
+ def update(self):
+ i18n = II18n(self.context)
+ if self.language:
+ self.legend = i18n.get_attribute('alt_title', self.language, request=self.request)
+ else:
+ self.legend = i18n.query_attribute('alt_title', request=self.request)
+
+
+@adapter_config(name='hidden', context=(IIllustration, IPyAMSLayer), provides=IContentRenderer)
+class HiddenIllustrationRenderer(BaseIllustrationRenderer):
+ """Hidden illustration renderer"""
+
+ label = _("Hidden illustration")
+ weight = -999
+
+ def render(self):
+ return ''
+
+
+@adapter_config(name='default', context=(IIllustration, IPyAMSLayer), provides=IContentRenderer)
+@template_config(template='templates/renderer-default.pt', layer=IPyAMSLayer)
+class DefaultIllustrationRenderer(BaseIllustrationRenderer):
+ """Default illustration renderer"""
+
+ label = _("Centered illustration")
+ weight = 1
+
+
+@adapter_config(name='left+zoom', context=(IIllustration, IPyAMSLayer), provides=IContentRenderer)
+@template_config(template='templates/renderer-left.pt', layer=IPyAMSLayer)
+class LeftIllustrationWithZoomRenderer(BaseIllustrationRenderer):
+ """Illustration renderer with small image and zoom"""
+
+ label = _("Small illustration on the left with zoom")
+ weight = 2
+
+ target_interface = IIllustrationWithZoomSettings
+
+
+@adapter_config(name='right+zoom', context=(IIllustration, IPyAMSLayer), provides=IContentRenderer)
+@template_config(template='templates/renderer-right.pt', layer=IPyAMSLayer)
+class RightIllustrationWithZoomRenderer(BaseIllustrationRenderer):
+ """Illustration renderer with small image and zoom"""
+
+ label = _("Small illustration on the right with zoom")
+ weight = 3
+
+ target_interface = IIllustrationWithZoomSettings
+
+
+#
+# Illustration renderer with zoom settings
+#
+
+ILLUSTRATION_ZOOM_RENDERER_SETTINGS_KEY = 'pyams_content.illustration.renderer:zoom'
+
+
+@implementer(IIllustrationWithZoomSettings)
+class IllustrationZoomSettings(Persistent, Location):
+ """Illustration zoom renderer settings"""
+
+ zoom_on_click = FieldProperty(IIllustrationWithZoomSettings['zoom_on_click'])
+
+
+@adapter_config(context=IIllustration, provides=IIllustrationWithZoomSettings)
+def IllustrationWithZoomSettingsFactory(context):
+ """Illustration zoom renderer settings factory"""
+ annotations = IAnnotations(context)
+ settings = annotations.get(ILLUSTRATION_ZOOM_RENDERER_SETTINGS_KEY)
+ if settings is None:
+ settings = annotations[ILLUSTRATION_ZOOM_RENDERER_SETTINGS_KEY] = IllustrationZoomSettings()
+ locate(settings, context)
+ return settings
--- a/src/pyams_content/component/paragraph/zmi/html.py Sun Feb 11 12:11:05 2018 +0100
+++ b/src/pyams_content/component/paragraph/zmi/html.py Thu Feb 15 15:08:29 2018 +0100
@@ -18,7 +18,7 @@
# import interfaces
from pyams_content.component.association.interfaces import IAssociationTarget
from pyams_content.component.association.zmi.interfaces import IAssociationsParentForm
-from pyams_content.component.illustration.interfaces import IIllustration, IIllustrationRenderer
+from pyams_content.component.illustration.interfaces import IIllustration
from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
IParagraphSummary
from pyams_content.component.paragraph.interfaces.html import IHTMLParagraph, IRawParagraph
@@ -354,9 +354,7 @@
self.illustration = IIllustration(self.context)
if self.illustration.data:
registry = get_current_registry()
- renderer = self.illustration_renderer = registry.queryMultiAdapter((self.illustration, self.request),
- IIllustrationRenderer,
- name=self.illustration.renderer)
+ renderer = self.illustration_renderer = self.illustration.get_renderer()
if renderer is not None:
renderer.update()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/features/renderer/__init__.py Thu Feb 15 15:08:29 2018 +0100
@@ -0,0 +1,51 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+
+# import interfaces
+from pyams_content.features.renderer.interfaces import IRenderedContent, IContentRenderer, IRendererSettings
+
+# import packages
+from pyams_utils.adapter import adapter_config
+from pyams_utils.request import check_request
+from zope.interface import implementer
+
+
+@implementer(IRenderedContent)
+class RenderedContentMixin(object):
+ """Renderer mixin interface"""
+
+ renderer = None
+
+ def get_renderer(self, request=None):
+ if request is None:
+ request = check_request()
+ return request.registry.queryMultiAdapter((self, request), IContentRenderer, name=self.renderer)
+
+
+@adapter_config(context=IRenderedContent, provides=IContentRenderer)
+def RenderedContentRendererFactory(context):
+ """Rendered content renderer factory"""
+ return context.get_renderer()
+
+
+@adapter_config(context=IRenderedContent, provides=IRendererSettings)
+def RenderedContentRendererSettingsFactory(context):
+ """Rendered content renderer settings factory"""
+ renderer = IContentRenderer(context)
+ if renderer.target_interface is None:
+ return None
+ return renderer.target_interface(context)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/features/renderer/interfaces/__init__.py Thu Feb 15 15:08:29 2018 +0100
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+
+# import interfaces
+from zope.annotation import IAttributeAnnotatable
+from zope.contentprovider.interfaces import IContentProvider
+
+# import packages
+from zope.interface import Interface, Attribute
+
+
+class IRenderedContent(IAttributeAnnotatable):
+ """Generic interface for any rendered content"""
+
+ renderer = Attribute("Selected renderer name")
+
+ def get_renderer(self, request=None):
+ """Get selected renderer implementation"""
+
+
+class IContentRenderer(IContentProvider):
+ """Content renderer interface"""
+
+ label = Attribute("Renderer label")
+
+ target_interface = Attribute("Renderer target interface")
+
+
+class IRendererSettings(Interface):
+ """Base renderer settings interface"""
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/features/renderer/zmi/__init__.py Thu Feb 15 15:08:29 2018 +0100
@@ -0,0 +1,74 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+
+# import interfaces
+from pyams_content.features.renderer.interfaces import IRenderedContent, IContentRenderer, IRendererSettings
+from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
+from pyams_skin.layer import IPyAMSLayer
+
+# import packages
+from pyams_form.form import AJAXEditForm
+from pyams_pagelet.pagelet import pagelet_config
+from pyams_template.template import get_view_template
+from pyams_utils.adapter import ContextRequestAdapter
+from pyams_zmi.form import AdminDialogEditForm
+from pyramid.view import view_config
+from z3c.form import field
+from zope.interface import implementer, Interface
+
+from pyams_content import _
+
+
+@implementer(IContentRenderer)
+class BaseContentRenderer(ContextRequestAdapter):
+ """Base content renderer"""
+
+ target_interface = None
+
+ @property
+ def settings(self):
+ if self.target_interface is None:
+ return None
+ return IRendererSettings(self.context)
+
+ render = get_view_template()
+
+
+@pagelet_config(name='renderer-properties.html', context=IRenderedContent, layer=IPyAMSLayer,
+ permission=MANAGE_CONTENT_PERMISSION)
+class RendererPropertiesEditForm(AdminDialogEditForm):
+ """Renderer properties edit form"""
+
+ legend = _("Edit renderer properties")
+ icon_css_class = 'fa fa-fw fa-pencil-square-o'
+
+ @property
+ def fields(self):
+ renderer = IContentRenderer(self.context)
+ return field.Fields(renderer.target_interface or Interface)
+
+ ajax_handler = 'renderer-properties.json'
+ edit_permission = MANAGE_CONTENT_PERMISSION
+
+ def getContent(self):
+ return IRendererSettings(self.context)
+
+
+@view_config(name='renderer-properties.json', context=IRenderedContent, request_type=IPyAMSLayer,
+ permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True)
+class RendererPropertiesAJAXEditForm(AJAXEditForm, RendererPropertiesEditForm):
+ """Renderer properties edit form, JSON renderer"""
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/features/renderer/zmi/templates/renderer-input.pt Thu Feb 15 15:08:29 2018 +0100
@@ -0,0 +1,43 @@
+<label class="input bordered with-icon" i18n:domain="pyams_security">
+ <tal:var define="render view/show_renderer_properties">
+ <i class="icon-append fa fa-fw fa-pencil-square-o hint align-base opaque"
+ title="Edit renderer properties" i18n:attributes="title"
+ data-ams-hint-gravity="se" data-toggle="modal"
+ tal:condition="render"
+ tal:attributes="data-ams-url extension:absolute_url(context, 'renderer-properties.html');"></i>
+ <i class="icon-append fa fa-fw fa-pencil-square-o opacity-50"
+ tal:condition="not:render"></i>
+ </tal:var>
+ <div class="select2-parent">
+ <select class="select2"
+ tal:attributes='id view/id;
+ name string:${view/name}:list;
+ class string:${view/klass} select2;
+ style view/style;
+ title view/title;
+ lang view/lang;
+ onclick view/onclick;
+ ondblclick view/ondblclick;
+ onmousedown view/onmousedown;
+ onmouseup view/onmouseup;
+ onmouseover view/onmouseover;
+ onmousemove view/onmousemove;
+ onmouseout view/onmouseout;
+ onkeypress view/onkeypress;
+ onkeydown view/onkeydown;
+ onkeyup view/onkeyup;
+ disabled view/disabled;
+ tabindex view/tabindex;
+ onfocus view/onfocus;
+ onblur view/onblur;
+ onchange view/onchange;
+ multiple view/multiple;
+ size view/size;
+ data-ams-data extension:object_data(view);'>
+ <option tal:repeat="entry view/items"
+ tal:attributes="value entry/value;
+ selected python:entry['value'] in view.value;"
+ tal:content="python:view.get_content(entry) if hasattr(view, 'get_content') else entry['content']"></option>
+ </select>
+ </div>
+</label>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/features/renderer/zmi/widget.py Thu Feb 15 15:08:29 2018 +0100
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+
+# import interfaces
+from pyams_content.features.renderer.interfaces import IContentRenderer
+from pyams_form.interfaces.form import IFormLayer
+from z3c.form.interfaces import INPUT_MODE
+
+# import packages
+from pyams_form.widget import Select2Widget, widgettemplate_config
+from z3c.form.widget import FieldWidget
+
+
+@widgettemplate_config(mode=INPUT_MODE, template='templates/renderer-input.pt', layer=IFormLayer)
+class RendererWidget(Select2Widget):
+ """Illustration renderer selection widget"""
+
+ @property
+ def show_renderer_properties(self):
+ renderer = IContentRenderer(self.context)
+ return (renderer is not None) and (renderer.target_interface is not None)
+
+
+def RendererFieldWidget(field, request):
+ return FieldWidget(field, RendererWidget(request))