[Grok-dev] Re: Skinning/themeing
Martin Aspeli
optilude at gmx.net
Sat May 19 17:45:05 EDT 2007
Martijn Faassen wrote:
> kevin at mcweekly.com wrote:
> [snip]
>> Yes, that's what it's for, to relate viewlet name -> viewletmanager name.
>> This does bring up a good point, where is the line drawn for
>> convention-over-configuration. I think that Martijn and Phillip have
>> done a great job of deliberating this and I certainly defer to them in
>> these aesthetic matters.
>
> I'm still grasping to find my way around viewlets. I think we need to do
> some more thinking before we fold this into the Grok core (which I hope
> we can over time). Hopefully we can find out a way to make this less
> magic without increasing the verbosity. On my end, this will require
> some thought about what viewlets are for. If we could (somehow) get rid
> of one of the entities (viewlet reference in view, viewlet manager and
> viewlets) that would help. If we can fix the ordering issue by taking
> definition order by default that would also help.
I don't find viewlets so bad, but maybe that's just because I've been
using them for a while. I'll try to explain them the way I see them, if
that helps. I'm sure you understand them too, but maybe the perspective
is useful.
- A "content provider" is just a named component (multi-adapter) which
can be rendered as part of a view - I think a "snippet" would've been a
better name. You use them like this:
<div tal:content="structure:content-provider-name" />
- A "content provider" is registered (as a named multi-adapter) for
(context, request, view). This allows you to have a different
implementation for different types of context, request (skin) and the
view it's being made part of
- A "viewlet manager" is a special case of a "content provider"
- A "viewlet manager" has a particular interface (though the
<browser:viewletManager /> ZCML directive will generate one for you if
you didn't specify one)
- Any number of "viewlets" can be registered for a "viewlet manager"
(via the aforementioned interface).
- When the "viewlet manager" "content provider" is rendered, it will
look up all "viewlets" assigned to it, order them, and render them.
Different types of "viewlet managers" may render e.g. a border around
its "viewlets" or perform some kind of filtering.
The end result is that you can define "holes" (to avoid using the word
"slot") in a page where your code or other people's code can plug in new
viewlets. In Plone 3, for example, we have lots of viewlets:
http://dev.plone.org/plone/browser/plone.app.layout/trunk/plone/app/layout/viewlets/configure.zcml#L33
These are referenced in various places, such as main_template:
http://dev.plone.org/plone/browser/CMFPlone/trunk/skins/plone_templates/main_template.pt#L122
Now, Plone and third party products can register viewlets for e.g. the
"above content" viewlet manager on the lines shown above. This means
that I can, for example:
o Show banner ads on all pages, regardles of context type, skin or view
o Add a "rate this content item" box on any IRatable
o Show a "give feedback" form on all views marked with IUserFeedback
o Override a viewlet for a particular skin (i.e. marker on the request)
In a Grok sense, I think the registration can be simplified a bit. I
haven't looked too closely at megrok.quarry, but I think this uses these
patterns or something similar:
class AboveContent(grok.ViewletManager):
"""A viewlet manager for things above the content
"""
grok.name('abovecontent')
# maybe override update(), render() or filter() here
# if we need special semantics
And in a template:
<div tal:replace="structure provider:abovecontent />
To register some new viewlets:
class BannerAds(grok.Viewlet):
"""A viewlet showing ads, on any context
"""
grok.viewlet_manager(AboveContent)
def render(self):
...
class Ratings(grok.Viewlet):
"""Show ratings on any IRatable
"""
grok.viewlet_manager(AboveContent)
grok.context(IRatable)
def render(self):
...
class FeedbackForm(grok.Viewlet):
"""Show the feedback form on any IUserFeedback-marked view
"""
grok.viewlet_manager(AboveContent)
grok.view(FeedbackForm
def render(self):
...
Those are a few examples. Note that the viewlets could come from an
entirely different package to the viewlet manager.
Even if you don't need this kind of pluggability, viewlets can make your
life easier because you can manage "tangental" or "infrastructural" UI
elements separately, across views. Things like portlet columns (which in
Plone 3 are content providers, not viewlets, because they use
plone.portlets to allow changes in what's being shown where at runtime),
footers and so forth can make sense as viewlets. If you find that you
need another one, or need some more complex rendering for common UI
elements (say, to have different behaviour depending on a user's role)
then those elements can be managed (and evolve) separately from the views.
Martin
More information about the Grok-dev
mailing list