I’ve been working these months in a Google Summer of Code project entitled Core tiles development. One thing I wanted to do is to write some documentation about how the whole Deco/Blocks/Tiles system works together – the reason is that there are a lot of packages and moving pieces involved and it’s easy to get lost trying to understand what does what and in which order. I won’t try to explain in detail how does each package do its work (read each package documentation if you’re interested) but to introduce the different packages involved.
In short, Deco is a page composition system based on semantic HTML and a grid system. Instead of using custom XML namespaces and a templating language (like METAL), Deco uses plain (strategic) HTML.
To add this feature to a Dexterity content-type you just have to add the plone.app.layoutbehavior Dexterity behavior to it. This behavior adds two fields to the content-type: layout, to select the site layout you want to use, and content. This last field will contain all the tile-related HTML markup, and is populated by default with two field tiles: title and description. The Dexterity type with the cited behavior we’re currently using is named Page and lives into plone.app.page.
If the Deco UI package, plone.app.deco, is installed, it will detect the presence of the content field and activate. The Deco UI allows you to insert, drag-and-drop, edit and delete tiles inside the content field of a type.
To position the tiles in the screen, the Deco UI makes use of the so-called Deco Grid System, a bunch of carefully crafted CSS classes that, when applied to div elements, position them in the page with the appropiate dimensions.
Tiles are little more than browser views with associated configuration data, and their base classes live in plone.tiles. We have transient tiles, which store the configuration data in a querystring in the tile HTML, like:
and persistent tiles, for config data not encodeable into querystrings (e.g. a large file), which store the data in the ZODB as annotations in the content object. Note the expected ‘@@’ for browser views — when this URL is accessed, it will return an HTML page with headers and a body, like:
<html> <head> <link rel="stylesheet" type="text/css" href="names.css" /> </head> <body> <p class="aName">Hello Israel!</p> </body> </html>
The plone.app.tiles (notice the “app” namespace) package registers the helper views @@add-tile, @@edit-tile and @@delete-tile to do exactly what their names say, the two first ones using a form generated from the tile data schema via plone.autoform.
So how are tiles actually rendered into a page? The answer resides in plone.app.blocks. This package is in charge of loading the page layout (remember the “layout” field added by plone.app.layoutbehavior?), merging in the contents of the page and “expanding” the tiles, merging the head of the tile into the head of the resulting page and putting its body where the placeholder for the tile was, as detailed in the documentation.
Finally, the basic tiles to be inserted, including image, video, attachment, navigation tree and searchbox among others, live in plone.app.standardtiles.