Dynamic views

 Plone 2.1 adds the 'display' menu, which can be used to set a display of an object on a per-instance basis. RichDocument uses this functionality in two ways:
 
o It tells Plone that a RichDocument can be used as a default-page for a folder. That is, the user can go to a folder, select "Choose content item as default view" and select a RichDocument to represent that folder.

o It lets users select different layouts for how their RichDocuments will be displayed - as a plain document, with a floating first image, or with a box of image thumbnails - and more views can be added by third party products or an administrator.

Telling Plone that a RichDocument is an acceptable default-page type is easy. In 'Extensions/Install.py', we simply have to add RichDocument to the list of 'default_page_types' in 'portal_properties/site_properties'::

 # Add to default_page_types
 defaultPageTypes = list(siteProperties.getProperty('default_page_types'))
 if 'RichDocument' not in defaultPageTypes:
     defaultPageTypes.append('RichDocument')
 siteProperties.manage_changeProperties(default_page_types = defaultPageTypes)

Letting RichDocument make use of the 'display' menu itself is more interesting. The magic happens in CMFDynamicViewFTI, which is an extension of the standard CMF Factory Type Information class to allow different view methods to be defined. 

If you look in 'portal_types', you will probably see some blue and some yellow icons. The yellow ones use CMFDynamicViewFTI. Take for example the standard Plone 'Folder' type. If you view this FTI, you will see two fields at the bottom of the 'Properties' tab:

Default view method -- The id of a page template that will be used as the view for new objects by default. This is probably 'folder_listing'.

Available view methods -- This is a list of templates that will be selectable from the 'display' menu. In a standard installation, you will se 'folder_listing', 'folder_tile_view', 'folder_tabular_view' and 'atct_album_view'. Note that the *names* you see in the 'display' menu are taken from the (possibly translated) titles of these page templates, which is defined e.g. in 'folder_listing.pt.metadata'.

To use CMFDynamicViewFTI in RichDocument, we have to do a few things:

1. Declare support for the 'ISelectableBrowserDefault' interface found in CMFDynamicViewFTI. We get this interface and the standard implementation from 'BrowserDefaultMixin', defined in 'CMFDynamicViewFTI/browserdefault.py', by way of 'ATDocument', which already mixes in this class and declares support for the interface.

2. Set 'default_view' and 'suppl_views' on our class to define the default view and any additional views to be available. Note that this can be changed later through 'portal_types'. We do this in 'content/richdocument.py'::

 default_view = 'richdocument_view'
 suppl_views = ('richdocument_view_preview', 'richdocument_view_float')

3. Write these page templates! In RichDocument, we have 'skins/RichDocument/richdocument_view.pt', the default, as well as 'richdocument_view_preview.pt' and 'richdocument_view_float.pt'.

3. Migrate to CMFDynamicViewFTI by calling 'migrateFTIs()' in 'Install.py'. Note that calling this method will migrate the FTIs for *all* the types defined in the product. This is not normally a problem, so long as all types mix in 'BrowserDefaultMixin' (all the ATContentTypes classes do, obviously), because CMFDynamicViewFTI is a direct extension of the standard CMF FTI class.::

 migrateFTIs(self, product=PROJECTNAME)
