Ignore:
Timestamp:
22 Apr 2011, 01:35:13 (14 years ago)
Author:
uli
Message:

Add a source for themes (aka skins) and show how to make use of the
ZCA to make things extendible in third-party packages.

This is the first step in an effort to provide clean and extendible
themes with waeup.sirp.

'clean' means: it was not clean yet to hardcode CSS file names (which
should be business of the browser subpackage) in the central
interfaces definitions file waeup.sirp.interfaces.

It was also not too clean, that we

It was also impossible for extension packages to define new own themes
yet or extend existing themes by adding some CSS file.

'extendible' means: with the new theme-source and theme-provider we
define clearly, what interface we expect from another package (for
instance the browser subpackage or any third-party package) to
retrieve a list of available themes at all. This list is then used by
the manage-view of University instances to provide a list of themes to
select for all pages.

The browser subpackage will also provide a theme-provider that looks
up all themes defined somewhere (in waeup.sirp _and_ other packags) at
runtime.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.sirp/trunk/src/waeup/sirp/interfaces.py

    r5899 r5955  
    99    # BBB
    1010    from zope.app.catalog.interfaces import ICatalog
    11 from zope.interface import Interface, Attribute
     11from zope.interface import Interface, Attribute, implements
    1212from zope import schema
    1313from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
    1414from waeup.sirp.permissions import RoleSource
    1515
     16class IThemeProvider(Interface):
     17    """A component that delivers all themes defined.
     18
     19    We normally do not deal with browser-related stuff in `waeup.sirp`
     20    but leave that to the `browser` subpackage. With themes (aka
     21    skins) we cannot follow that path because we need a theme as an
     22    attribute of each `University` instance.
     23
     24    Therefore we must tell the browser subpackage how we expect themes
     25    to be announced code-wise.
     26
     27    What we tell here is that we might ask for a utility providing
     28    IThemeProvider and that this component then should be callable to
     29    give us a list of themes and their respective internal names.
     30    """
     31    def __call__():
     32        """Get a list of all themes available.
     33
     34        Returns a list of ``(<NAME>, <THEME>)`` tuples where
     35        ``<NAME>`` is the internal name under which a theme was
     36        registered and ``<THEME>`` is the real theme.
     37        """
     38
     39class ThemeSource(BasicSourceFactory):
     40    """A source for themes.
     41    """
     42    def getValues(self):
     43        """Get names of themes.
     44        """
     45        theme_provider = getUtility(IThemeProvider, name="default")
     46        return [x for x, y in theme_provider()]
     47   
     48    def getTitle(self, value):
     49        """Get a user-presentable description for a theme.
     50        """
     51        theme_provider = getUtility(IThemeProvider, name="default")
     52        for name, theme in theme_provider():
     53            if name == value:
     54                return theme.description
     55        return u'unnamed'
     56
     57class ThemeSourceBinder(object):
     58    """A source binder for the `ThemeSource`.
     59
     60    Normally, we can pass instances of a source (like `ThemeSource`)
     61    directly to fields in interfaces (writing something like ``source
     62    = ThemeSource()``. With `ThemeSource` we cannot do this, because
     63    the set of available themes is not available before the whole
     64    `waeup.sirp` package was grokked (and parsed).
     65
     66    We bypass that problem by defining this trivial source-binder,
     67    which is asked for themes only when the values of the source are
     68    really needed and after the process of grokking and parsing
     69    everything on startup.
     70
     71    So, although this binder binds to some context (`IUniversity` is
     72    currently the only interface making use of this source, so
     73    `University` instances are the only context used), the context
     74    does not really matter.
     75    """
     76    implements(schema.interfaces.IContextSourceBinder)
     77
     78    def __call__(self, context):
     79        return ThemeSource()
     80
    1681class FatalCSVError(Exception):
    1782    """Some row could not be processed.
     
    2691            SimpleTerm(value, value, title) for title, value in terms])
    2792
     93
    2894class IWAeUPObject(Interface):
    2995    """A WAeUP object.
     
    40106        required = True,
    41107        )
    42    
     108
     109       
    43110    skin = schema.Choice(
    44111        title = u'Skin',
    45112        default = u'waeuptheme-gray1.css',
    46         #values = ['waeuptheme-gray1.css', 'waeuptheme-red1.css'],
    47         vocabulary = SimpleWAeUPVocabulary(
    48             ('Henrik\'s Gray Theme', 'waeuptheme-gray1.css'), ('Uli\'s Red Theme', 'waeuptheme-red1.css')),
     113        source = ThemeSourceBinder(),
    49114        required = True,
    50115        )
Note: See TracChangeset for help on using the changeset viewer.