Context's support for multiple layouts, each with a distinct set of regions, is key to its flexibility and power in providing diverse page designs. But since this functionality depends on layouts being provided by the current theme, it faces two key limitations: 1., relatively few themes (yet) support layouts, 2. even if layouts are more broadly introduced, each theme may provide a distinct set of layouts with different regions, meaning that features built on context will still have difficulty relying on layouts.

Enabling modules to provide layouts could address these limitations. But what would a module-supplied layout consist of? Our best existing model would of course be Panels. But unlike Panels, with Context we need to support content added to the main content area as well as content written to layout regions.

Possible approach:

  • Modules declare their layouts using the same array format currently used by themes, but in hook_context_layouts().
  • Patch context_layouts_reaction_block.inc to recognize and handle module-supplied layouts alongside theme-supplied ones.
  • If they don't use a template, modules are responsible for rendering of their own layouts, if the layout is set as active.
  • A module-supplied layout is assumed to include the regular $content variable content as passed to theme_page() and to render all its content in the place of the regular $content output.
  • Context layout reaction configuration includes the option to suppress regular theme regions aside from those in the current layout (as is currently done with theme-supplied layouts).

Sample hook implementation:


/**
 * Implementation of hook_context_layouts().
 */
function example_context_layouts() {
  $layouts = array();
  $layouts['example_2col'] = array(
    'name' => t('Example two columns'),
    'description' => t('A two column layout'),
    'stylesheet' => 'example-2col.css',
    'template' => 'example-2col',
    'regions' => array(
      'example_left',
      'example_right',
    ),
  );
  return $layouts;

}

Or I guess if the module wasn't using a template:


/**
 * Preprocessor for theme('page').
 */
function example_preprocess_page(&$vars) {
  if ($layout = context_layouts_get_active_layout(FALSE)) {
    $vars['content'] = theme('example_layout_' . $layout, $vars['content']);
  }
}

A module-supplied layout isn't as powerful as a theme one, as in most themes it could control only a portion of the page and could produce theme layout issues. But it would make it possible to have a consistent set of regions throughout a feature set.

Feasible? Desirable?

Comments

nedjo’s picture

StatusFileSize
new2.57 KB

Conceptual draft of a patch.

Module would declare a 'theme_hook', in its layout array.

nedjo’s picture

Title: Enable module-supplied layouts » Support Panels-style layouts
Status: Active » Needs review
StatusFileSize
new8.42 KB

If we're supporting non-theme layouts, we should probably use the same format as Panels does--no use reinventing here what's already well designed.

Attached patch adds support for Panels-style layouts. No dependency on Panels--loads layout plugins with ctools whether Panels is present or not (though to test enabling Panels provides some layouts to work with).

To demo:
* Enable Panels and Context Layouts.
* Set Garland as the default theme.
* Configure a context with a Blocks reaction. For Layouts options, you should see Default (the Garland regions) and all available Panels layouts. Select one of the Panels layouts and add blocks to its regions. Save.
* You should see the content you added displaying in Panels layout below the Content region.

TODO: figure out how to integrate content assigned to the main $content variable into the Panels layout. Possible approach:
* Introduce a $layout['content_region'] parameter, e.g., 'middle'.
* Alter core Panels layouts to set this parameter.
* If set, prepend $content to this region before theming. Otherwise, do as the patch currently does (append full panels layout to $content).

nedjo’s picture

StatusFileSize
new10.42 KB

Adding in the main $content variable approach outlined in #2. If a layout has a 'content_region' set, that is used. If not but it has a 'middle' or 'top' region, that is set as the content_region. Makes panels-style layouts behave very much the same as existing theme-supplied layouts.

Can be tested with any theme or module that supplies panels layouts.

nedjo’s picture

Opened a related issue on Panels: #892538: Consider pulling layouts into ctools.

nedjo’s picture

Issue tags: +Debut enabler

Tagging.

owen barton’s picture

Subscribe

davidburns’s picture

wasn't there supposed to be a subscribe link for individual issues?

subscribe +1

itserich’s picture

subscribe

nedjo’s picture

Version: 6.x-3.x-dev » 7.x-3.x-dev

I converted this into a freestanding D7 module, in my sandbox for now: http://drupal.org/sandbox/nedjo/1337258.

I've written it so that it will use Panels-supplied layouts if Panels is enabled but, if not, will supply its own layouts (and recognize other module- and theme-supplied panels layouts).