View source
<?php
$plugin = array(
'title' => t('Flexible'),
'category' => t('Builders'),
'icon' => 'flexible.png',
'theme' => 'panels_flexible',
'admin theme' => 'panels_flexible_admin',
'css' => 'flexible.css',
'admin css' => 'flexible-admin.css',
'settings form' => 'panels_flexible_settings_form',
'settings submit' => 'panels_flexible_settings_submit',
'settings validate' => 'panels_flexible_settings_validate',
'panels function' => 'panels_flexible_panels',
'hook menu' => 'panels_flexible_menu',
'builder' => TRUE,
'builder tab title' => 'Add flexible layout',
'get child' => 'panels_flexible_get_sublayout',
'get children' => 'panels_flexible_get_sublayouts',
'ajax' => array(
'settings' => 'panels_ajax_flexible_edit_settings',
'add' => 'panels_ajax_flexible_edit_add',
'remove' => 'panels_ajax_flexible_edit_remove',
'resize' => 'panels_ajax_flexible_edit_resize',
'reuse' => 'panels_ajax_flexible_edit_reuse',
),
);
function panels_flexible_merge_plugin($plugin, $layout) {
$plugin['name'] = 'flexible:' . $layout->name;
$plugin['category'] = !empty($layout->category) ? check_plain($layout->category) : t('Miscellaneous');
$plugin['title'] = check_plain($layout->admin_title);
$plugin['description'] = check_plain($layout->admin_description);
$plugin['layout'] = $layout;
$plugin['builder'] = FALSE;
$plugin['builder tab title'] = NULL;
return $plugin;
}
function panels_flexible_get_sublayout($plugin, $layout_name, $sublayout_name) {
ctools_include('export');
$item = ctools_export_crud_load('panels_layout', $sublayout_name);
if ($item) {
return panels_flexible_merge_plugin($plugin, $item);
}
}
function panels_flexible_get_sublayouts($plugin, $layout_name) {
$layouts[$layout_name] = $plugin;
ctools_include('export');
$items = ctools_export_load_object('panels_layout', 'conditions', array(
'plugin' => 'flexible',
));
foreach ($items as $name => $item) {
$layouts['flexible:' . $name] = panels_flexible_merge_plugin($plugin, $item);
}
return $layouts;
}
function panels_flexible_convert_settings(&$settings, &$layout) {
if (!empty($settings['layout'])) {
$layout = panels_get_layout('flexible:' . $settings['layout']);
}
if (!empty($layout['layout'])) {
$settings = $layout['layout']->settings;
if ($settings) {
return $settings;
}
}
if (empty($settings)) {
$settings = array(
'items' => array(
'canvas' => array(
'type' => 'row',
'contains' => 'column',
'children' => array(
'main',
),
'parent' => NULL,
),
'main' => array(
'type' => 'column',
'width' => 100,
'width_type' => '%',
'children' => array(
'main-row',
),
'parent' => 'canvas',
),
'main-row' => array(
'type' => 'row',
'contains' => 'region',
'children' => array(
'center',
),
'parent' => 'main',
),
'center' => array(
'type' => 'region',
'title' => t('Center'),
'width' => 100,
'width_type' => '%',
'parent' => 'main-row',
),
),
);
}
else {
if (!isset($settings['items'])) {
$old = $settings;
$settings = array();
$settings['items']['canvas'] = array(
'type' => 'row',
'contains' => 'column',
'children' => array(),
'parent' => NULL,
);
if (!empty($old['sidebars']['left'])) {
$settings['items']['canvas']['children'][] = 'sidebar-left';
$settings['items']['sidebar-left'] = array(
'type' => 'column',
'width' => $old['sidebars']['left_width'],
'width_type' => $old['sidebars']['width_type'],
'children' => array(
'sidebar-left-row',
),
'parent' => 'canvas',
);
$settings['items']['sidebar-left-row'] = array(
'type' => 'row',
'contains' => 'region',
'children' => array(
'sidebar_left',
),
'parent' => 'sidebar-left',
);
$settings['items']['sidebar_left'] = array(
'type' => 'region',
'title' => t('Left sidebar'),
'width' => 100,
'width_type' => '%',
'parent' => 'sidebar-left-row',
);
}
$settings['items']['canvas']['children'][] = 'main';
if (!empty($old['sidebars']['right'])) {
$settings['items']['canvas']['children'][] = 'sidebar-right';
$settings['items']['sidebar-right'] = array(
'type' => 'column',
'width' => $old['sidebars']['right_width'],
'width_type' => $old['sidebars']['width_type'],
'children' => array(
'sidebar-right-row',
),
'parent' => 'canvas',
);
$settings['items']['sidebar-right-row'] = array(
'type' => 'row',
'contains' => 'region',
'children' => array(
'sidebar_right',
),
'parent' => 'sidebar-right',
);
$settings['items']['sidebar_right'] = array(
'type' => 'region',
'title' => t('Right sidebar'),
'width' => 100,
'width_type' => '%',
'parent' => 'sidebar-right-row',
);
}
$settings['items']['main'] = array(
'type' => 'column',
'width' => 100,
'width_type' => '%',
'children' => array(),
'parent' => 'canvas',
);
for ($row = 1; $row <= intval($old['rows']); $row++) {
$settings['items']["row_{$row}"] = array(
'type' => 'row',
'contains' => 'region',
'children' => array(),
'parent' => 'main',
);
$settings['items']['main']['children'][] = "row_{$row}";
for ($col = 1; $col <= intval($old["row_{$row}"]['columns']); $col++) {
$settings['items']["row_{$row}_{$col}"] = array(
'type' => 'region',
'width' => $old["row_{$row}"]["width_{$col}"],
'width_type' => '%',
'parent' => "row_{$row}",
);
$settings['items']["row_{$row}"]['children'][] = "row_{$row}_{$col}";
if (!empty($old["row_{$row}"]['names'][$col - 1])) {
$settings['items']["row_{$row}_{$col}"]['title'] = $old["row_{$row}"]['names'][$col - 1];
}
else {
$settings['items']["row_{$row}_{$col}"]['title'] = t("Row @row, Column @col", array(
'@row' => $row,
'@col' => $col,
));
}
}
}
}
else {
if (isset($settings['canvas'])) {
$settings['items']['canvas'] = array(
'type' => 'row',
'contains' => 'column',
'children' => $settings['canvas'],
'parent' => NULL,
);
unset($settings['canvas']);
}
}
}
}
function panels_flexible_panels($display, $settings, $layout) {
$items = array();
panels_flexible_convert_settings($settings, $layout);
foreach ($settings['items'] as $id => $item) {
if ($item['type'] == 'region') {
$items[$id] = $item['title'];
}
}
return $items;
}
function panels_flexible_create_renderer($admin, $id, $content, $settings, &$display, $layout, $handler) {
$renderer = new stdClass();
$renderer->settings = $settings;
$renderer->content = $content;
$renderer->css_id = $id;
$renderer->did =& $display->did;
if ($admin) {
$renderer->scale_base = 99.0;
}
else {
$renderer->scale_base = !empty($settings['items']['canvas']['no_scale']) ? 100.0 : 99.0;
}
$renderer->id_str = $id ? 'id="' . $id . '"' : '';
$renderer->admin = $admin;
$renderer->handler = $handler;
$renderer->name = !empty($layout['layout']) ? $layout['layout']->name : $display->did;
$renderer->base_class = $renderer->name;
$renderer->item_class['column'] = 'panels-flexible-column';
$renderer->item_class['row'] = 'panels-flexible-row';
$renderer->item_class['region'] = 'panels-flexible-region';
$renderer->base['canvas'] = 'panels-flexible-' . $renderer->base_class;
if (!$admin) {
if (!empty($settings['items']['canvas']['class'])) {
$renderer->base_class = $settings['items']['canvas']['class'];
$renderer->base['canvas'] = $renderer->base_class;
}
if (!empty($settings['items']['canvas']['column_class'])) {
$renderer->item_class['column'] = $settings['items']['canvas']['column_class'];
}
if (!empty($settings['items']['canvas']['row_class'])) {
$renderer->item_class['row'] = $settings['items']['canvas']['row_class'];
}
if (!empty($settings['items']['canvas']['region_class'])) {
$renderer->item_class['region'] = $settings['items']['canvas']['region_class'];
}
}
$renderer->column_separation = !empty($settings['items']['canvas']['column_separation']) ? $settings['items']['canvas']['column_separation'] : '0.5em';
$renderer->region_separation = !empty($settings['items']['canvas']['region_separation']) ? $settings['items']['canvas']['region_separation'] : '0.5em';
$renderer->row_separation = !empty($settings['items']['canvas']['row_separation']) ? $settings['items']['canvas']['row_separation'] : '0.5em';
$renderer->base['column'] = $renderer->item_class['column'] . '-' . $renderer->base_class;
$renderer->base['row'] = $renderer->item_class['row'] . '-' . $renderer->base_class;
$renderer->base['region'] = $renderer->item_class['region'] . '-' . $renderer->base_class;
if ($renderer->name != 'new') {
$renderer->css_cache_name = 'flexiblev2:' . $renderer->name;
if ($admin) {
ctools_include('css');
ctools_css_clear($renderer->css_cache_name);
}
}
return $renderer;
}
function theme_panels_flexible($id, $content, $settings, $display, $layout, $handler) {
panels_flexible_convert_settings($settings, $layout);
$renderer = panels_flexible_create_renderer(FALSE, $id, $content, $settings, $display, $layout, $handler);
$css = panels_flexible_render_css($renderer);
if (!empty($renderer->css_cache_name) && empty($display->editing_layout)) {
ctools_include('css');
$filename = ctools_css_retrieve($renderer->css_cache_name);
if (!$filename) {
$filename = ctools_css_store($renderer->css_cache_name, $css, FALSE);
}
if ($handler) {
$handler
->add_css($filename, 'module', 'all', FALSE);
}
else {
ctools_css_add_css($filename, 'module', 'all', FALSE);
}
}
else {
drupal_set_html_head("<style type=\"text/css\">\n{$css}</style>\n");
}
$display->add_css = $css;
$output = "<div class=\"panel-flexible " . $renderer->base['canvas'] . " clear-block\" {$renderer->id_str}>\n";
$output .= "<div class=\"panel-flexible-inside " . $renderer->base['canvas'] . "-inside\">\n";
$output .= panels_flexible_render_items($renderer, $settings['items']['canvas']['children'], $renderer->base['canvas']);
$output .= "</div>\n</div>\n";
return $output;
}
function theme_panels_flexible_admin($id, $content, $settings, $display, $layout, $handler) {
if (!empty($layout['layout'])) {
return theme_panels_flexible($id, $content, $settings, $display, $layout, $handler);
}
panels_flexible_convert_settings($settings, $layout);
$renderer = panels_flexible_create_renderer(TRUE, $id, $content, $settings, $display, $layout, $handler);
$css = panels_flexible_render_css($renderer);
drupal_set_html_head("<style type=\"text/css\">\n{$css}</style>\n");
if (empty($display->editing_layout)) {
$output = '<input type="submit" id="panels-flexible-toggle-layout" value ="' . t('Show layout designer') . '">';
if (user_access('administer panels layouts')) {
$output .= '<input type="hidden" class="panels-flexible-reuse-layout-url" value="' . url($handler
->get_url('layout', 'reuse'), array(
'absolute' => TRUE,
)) . '">';
$output .= '<input type="submit" id="panels-flexible-reuse-layout" class="ctools-use-modal" value ="' . t('Reuse layout') . '">';
}
$output .= "<div class=\"panel-flexible " . $renderer->base['canvas'] . " clear-block panel-flexible-admin panel-flexible-no-edit-layout\" {$renderer->id_str}>\n";
}
else {
$output = "<div class=\"panel-flexible " . $renderer->base['canvas'] . " clear-block panel-flexible-admin panel-flexible-edit-layout\" {$renderer->id_str}>\n";
}
$output .= "<div class=\"panel-flexible-inside " . $renderer->base['canvas'] . "-inside \">\n";
$content = panels_flexible_render_items($renderer, $settings['items']['canvas']['children'], $renderer->base['row'] . '-canvas');
$output .= panels_flexible_render_item($renderer, $settings['items']['canvas'], $content, 'canvas', 0, 0, TRUE);
$output .= "</div>\n</div>\n";
drupal_add_js($layout['path'] . '/flexible-admin.js');
drupal_add_js(array(
'flexible' => array(
'resize' => url($handler
->get_url('layout', 'resize'), array(
'absolute' => TRUE,
)),
),
), 'setting');
return $output;
}
function panels_flexible_render_items($renderer, $list, $owner_id) {
$output = '';
$groups = array(
'left' => '',
'middle' => '',
'right' => '',
);
$max = count($list) - 1;
$prev = NULL;
foreach ($list as $position => $id) {
$item = $renderer->settings['items'][$id];
$location = isset($renderer->positions[$id]) ? $renderer->positions[$id] : 'middle';
if ($renderer->admin && $item['type'] != 'row' && $prev) {
$groups[$location] .= panels_flexible_render_splitter($renderer, $prev, $id);
}
switch ($item['type']) {
case 'column':
$content = panels_flexible_render_items($renderer, $item['children'], $renderer->base['column'] . '-' . $id);
$groups[$location] .= panels_flexible_render_item($renderer, $item, $content, $id, $position, $max);
break;
case 'row':
$content = panels_flexible_render_items($renderer, $item['children'], $renderer->base['row'] . '-' . $id);
$groups[$location] .= panels_flexible_render_item($renderer, $item, $content, $id, $position, $max, TRUE);
break;
case 'region':
$content = isset($renderer->content[$id]) ? $renderer->content[$id] : " ";
$groups[$location] .= panels_flexible_render_item($renderer, $item, $content, $id, $position, $max);
break;
}
if (!empty($renderer->admin) && $max == $position && $location == 'left') {
$groups[$location] .= panels_flexible_render_splitter($renderer, $id, NULL);
}
$prev = $id;
}
$group_count = count(array_filter($groups));
foreach ($groups as $position => $content) {
if (!empty($content) || $renderer->admin) {
if ($group_count > 1 || $renderer->admin) {
$output .= '<div class="' . $owner_id . '-' . $position . '">' . $content . '</div>';
}
else {
$output .= $content;
}
}
}
return $output;
}
function panels_flexible_render_item($renderer, $item, $content, $id, $position, $max, $clear = FALSE) {
if (empty($renderer->admin) && $item['type'] == 'row' && $max == 0) {
$fixed = FALSE;
foreach ($item['children'] as $id) {
if ($renderer->settings['items'][$id]['width_type'] != '%') {
$fixed = TRUE;
break;
}
}
if (!$fixed) {
return $content;
}
}
if (empty($renderer->admin) && $item['type'] == 'column' && $max == 0 && $item['width_type'] == '%') {
return $content;
}
$base = $renderer->item_class[$item['type']];
$output = '<div class="' . $base . ' ' . $renderer->base[$item['type']] . '-' . $id;
if ($position == 0) {
$output .= ' ' . $base . '-first';
}
if ($position == $max) {
$output .= ' ' . $base . '-last';
}
if ($clear) {
$output .= ' clear-block';
}
if (isset($item['class'])) {
$output .= ' ' . check_plain($item['class']);
}
$output .= '">' . "\n";
if (!empty($renderer->admin)) {
$output .= panels_flexible_render_item_links($renderer, $id, $item);
}
$output .= ' <div class="inside ' . $base . '-inside ' . $base . '-' . $renderer->base_class . '-' . $id . '-inside';
if ($position == 0) {
$output .= ' ' . $base . '-inside-first';
}
if ($position == $max) {
$output .= ' ' . $base . '-inside-last';
}
if ($clear) {
$output .= ' clear-block';
}
$output .= "\">\n";
$output .= $content;
$output .= ' </div>' . "\n";
$output .= '</div>' . "\n";
return $output;
}
function panels_flexible_render_splitter($renderer, $left_id, $right_id) {
$left = $renderer->settings['items'][$left_id];
$left_class = $renderer->base[$left['type']] . '-' . $left_id;
if ($right_id) {
$right = $renderer->settings['items'][$right_id];
$right_class = $renderer->base[$left['type']] . '-' . $right_id;
}
else {
$right = $left;
$right_class = $left_class;
}
$output = '<div class="panels-flexible-splitter flexible-splitter-for-' . $left_class . '">';
$output .= '<span class="panels-flexible-splitter-left">';
$output .= '.' . $left_class;
$output .= '</span>';
$output .= '<span class="panels-flexible-splitter-left-id">';
$output .= $left_id;
$output .= '</span>';
$output .= '<span class="panels-flexible-splitter-left-width ' . $left_class . '-width">';
$output .= $left['width'];
$output .= '</span>';
$output .= '<span class="panels-flexible-splitter-left-scale">';
$output .= isset($renderer->scale[$left_id]) ? $renderer->scale[$left_id] : 1;
$output .= '</span>';
$output .= '<span class="panels-flexible-splitter-left-width-type">';
$output .= $left['width_type'];
$output .= '</span>';
$output .= '<span class="panels-flexible-splitter-right">';
$output .= '.' . $right_class;
$output .= '</span>';
$output .= '<span class="panels-flexible-splitter-right-id">';
$output .= $right_id;
$output .= '</span>';
$output .= '<span class="panels-flexible-splitter-right-width ' . $right_class . '-width">';
$output .= $right['width'];
$output .= '</span>';
$output .= '<span class="panels-flexible-splitter-right-scale">';
$output .= isset($renderer->scale[$right_id]) ? $renderer->scale[$right_id] : 1;
$output .= '</span>';
$output .= '<span class="panels-flexible-splitter-right-width-type">';
$output .= $right_id ? $right['width_type'] : '%';
$output .= '</span>';
$output .= '</div>';
return $output;
}
function panels_flexible_render_item_links($renderer, $id, $item) {
$links = array();
$remove = '';
$add = '';
if ($item['type'] == 'column') {
$title = t('Column');
$settings = t('Column settings');
if (empty($item['children'])) {
$remove = t('Remove column');
$add = t('Add row');
}
else {
$add = t('Add row to top');
$add2 = t('Add row to bottom');
}
}
else {
if ($item['type'] == 'row') {
if ($id == 'canvas') {
$title = t('Canvas');
$settings = t('Canvas settings');
}
else {
$title = t('Row');
$settings = t('Row settings');
}
if (empty($item['children'])) {
if ($id != 'canvas') {
$remove = t('Remove row');
}
$add = $item['contains'] == 'region' ? t('Add region') : t('Add column');
}
else {
$add = $item['contains'] == 'region' ? t('Add region to left') : t('Add column to left');
$add2 = $item['contains'] == 'region' ? t('Add region to right') : t('Add column to right');
}
}
else {
if ($item['type'] == 'region') {
$title = t('Region');
$settings = t('Region settings');
$remove = t('Remove region');
}
}
}
if (!empty($settings)) {
$links[] = array(
'title' => $settings,
'href' => $renderer->handler
->get_url('layout', 'settings', $id),
'attributes' => array(
'class' => 'ctools-use-modal',
),
);
}
if ($add) {
$links[] = array(
'title' => $add,
'href' => $renderer->handler
->get_url('layout', 'add', $id),
'attributes' => array(
'class' => 'ctools-use-modal',
),
);
}
if (isset($add2)) {
$links[] = array(
'title' => $add2,
'href' => $renderer->handler
->get_url('layout', 'add', $id, 'right'),
'attributes' => array(
'class' => 'ctools-use-modal',
),
);
}
if ($remove) {
$links[] = array(
'title' => $remove,
'href' => $renderer->handler
->get_url('layout', 'remove', $id),
'attributes' => array(
'class' => 'ctools-use-ajax',
),
);
}
return theme('ctools_dropdown', $title, $links, FALSE, 'flexible-layout-only flexible-links flexible-title flexible-links-' . $id);
}
function panels_flexible_render_css($renderer) {
if ($renderer->admin) {
$parent_class = '.' . $renderer->base['row'] . '-canvas';
}
else {
$parent_class = '.' . $renderer->base['canvas'];
}
return panels_flexible_render_css_group($renderer, $renderer->settings['items']['canvas']['children'], $parent_class, 'column', 'canvas');
}
function panels_flexible_render_css_group($renderer, $list, $owner_id, $type, $id) {
$css = array();
$css['.' . $renderer->item_class['region']] = array(
'padding' => '0',
);
$css['.' . $renderer->item_class['region'] . '-inside'] = array(
'padding-right' => $renderer->region_separation,
'padding-left' => $renderer->region_separation,
);
$css['.' . $renderer->item_class['region'] . '-inside-first'] = array(
'padding-left' => '0',
);
$css['.' . $renderer->item_class['region'] . '-inside-last'] = array(
'padding-right' => '0',
);
$css['.' . $renderer->item_class['column']] = array(
'padding' => '0',
);
$css['.' . $renderer->item_class['column'] . '-inside'] = array(
'padding-right' => $renderer->column_separation,
'padding-left' => $renderer->column_separation,
);
$css['.' . $renderer->item_class['column'] . '-inside-first'] = array(
'padding-left' => '0',
);
$css['.' . $renderer->item_class['column'] . '-inside-last'] = array(
'padding-right' => '0',
);
$css['.' . $renderer->item_class['row']] = array(
'padding' => '0 0 ' . $renderer->row_separation . ' 0',
'margin' => '0',
);
$css['.' . $renderer->item_class['row'] . '-last'] = array(
'padding-bottom' => '0',
);
panels_flexible_get_css_group($css, $renderer, $list, $owner_id, $type, $id);
ctools_include('css');
return ctools_css_assemble($css);
}
function panels_flexible_get_css_group(&$css, $renderer, $list, $owner_id, $type, $item_id) {
if ($type != 'row') {
$left = $middle = $right = array();
$left_total = $right_total = $middle_total = 0;
$current = 'left';
foreach ($list as $id) {
if ($renderer->settings['items'][$id]['width_type'] == 'px') {
if ($current == 'left') {
$left[] = $id;
$renderer->positions[$id] = 'left';
$left_total += $renderer->settings['items'][$id]['width'];
}
else {
$current = 'right';
$right[] = $id;
$renderer->positions[$id] = 'right';
$right_total += $renderer->settings['items'][$id]['width'];
}
}
else {
if ($current != 'right') {
$current = 'middle';
$middle[] = $id;
$renderer->positions[$id] = 'middle';
$middle_total += $renderer->settings['items'][$id]['width'];
}
}
}
foreach ($left as $id) {
$class = "." . $renderer->base[$type] . "-{$id}";
$css[$class] = array(
'position' => 'relative',
'float' => 'left',
'background-color' => 'transparent',
'width' => $renderer->settings['items'][$id]['width'] . "px",
);
}
$right_pixels = 0;
foreach ($right as $id) {
$class = "." . $renderer->base[$type] . "-{$id}";
$css[$class] = array(
'float' => 'left',
'width' => $renderer->settings['items'][$id]['width'] . "px",
);
}
$max = count($middle) - 1;
if ($middle_total) {
$scale = $renderer->scale_base / $middle_total;
foreach ($middle as $position => $id) {
$class = "." . $renderer->base[$type] . "-{$id}";
$css[$class] = array(
'float' => 'left',
'width' => number_format($renderer->settings['items'][$id]['width'] * $scale, 4, '.', '') . "%",
);
$renderer->scale[$id] = $scale;
}
}
if ($left_total) {
$css["{$owner_id}-inside"]['padding-left'] = '0px';
if ($renderer->admin || count($middle)) {
$css["{$owner_id}-middle"]['margin-left'] = $left_total . 'px';
$css["* html {$owner_id}-left"]['left'] = $left_total . "px";
$css[".panel-flexible-admin {$owner_id}-inside"]['padding-left'] = '0px';
}
else {
$css["{$owner_id}-inside"]['margin-left'] = '-' . $left_total . 'px';
$css["{$owner_id}-inside"]['padding-left'] = $left_total . 'px';
$css["* html {$owner_id}-inside"]['left'] = $left_total . "px";
}
}
if ($right_total) {
$css["{$owner_id}-middle"]['margin-right'] = $right_total . 'px';
}
$css["{$owner_id}-inside"]['padding-right'] = '0px';
}
if ($item_id == 'canvas') {
$item = $renderer->settings['items'][$item_id];
if (!empty($item['fixed_width']) && intval($item['fixed_width'])) {
$css['.' . $renderer->base['canvas']]['width'] = intval($item['fixed_width']) . 'px';
}
else {
$css['.' . $renderer->base['canvas']]['width'] = 'auto';
}
}
foreach ($list as $id) {
$item = $renderer->settings['items'][$id];
if (empty($item['children'])) {
continue;
}
if ($type == 'column') {
$child_type = 'row';
}
else {
$child_type = isset($item['contains']) ? $item['contains'] : 'region';
}
$class = "." . $renderer->base[$type] . "-{$id}";
panels_flexible_get_css_group($css, $renderer, $item['children'], $class, $child_type, $id);
}
}
function panels_ajax_flexible_edit_settings($handler, $id) {
$settings =& $handler->display->layout_settings;
panels_flexible_convert_settings($settings, $handler->plugins['layout']);
if (empty($settings['items'][$id])) {
ctools_modal_render(t('Error'), t('Invalid item id.'));
}
$item =& $settings['items'][$id];
$siblings = array();
if ($id != 'canvas') {
$siblings = $settings['items'][$item['parent']]['children'];
}
switch ($item['type']) {
case 'column':
$title = t('Configure column');
break;
case 'row':
if ($id == 'canvas') {
$title = t('Configure canvas');
}
else {
$title = t('Configure row');
}
break;
case 'region':
$title = t('Configure region');
break;
}
$form_state = array(
'display' => &$handler->display,
'item' => &$item,
'id' => $id,
'siblings' => $siblings,
'settings' => &$settings,
'ajax' => TRUE,
'title' => $title,
'op' => 'edit',
);
$output = ctools_modal_form_wrapper('panels_flexible_config_item_form', $form_state);
if (empty($output)) {
panels_edit_cache_set($handler->cache);
$css_id = isset($handler->display->css_id) ? $handler->display->css_id : '';
$renderer = panels_flexible_create_renderer(TRUE, $css_id, array(), $settings, $handler->display, $handler->plugins['layout'], $handler);
$output = array();
$class = $renderer->base[$item['type']] . '-' . $id;
if ($item['type'] == 'region') {
$output[] = ctools_ajax_command_replace(".{$class} h2.label", '<h2 class="label">' . check_plain($item['title']) . '</h2>');
}
$output[] = ctools_ajax_command_replace('.flexible-links-' . $id, panels_flexible_render_item_links($renderer, $id, $item));
if ($id == 'canvas') {
$css = array(
'.' . $renderer->item_class['column'] . '-inside' => array(
'padding-left' => $renderer->column_separation,
'padding-right' => $renderer->column_separation,
),
'.' . $renderer->item_class['region'] . '-inside' => array(
'padding-left' => $renderer->region_separation,
'padding-right' => $renderer->region_separation,
),
'.' . $renderer->item_class['row'] => array(
'padding-bottom' => $renderer->row_separation,
),
);
if (!empty($item['fixed_width']) && intval($item['fixed_width'])) {
$css['.' . $renderer->base['canvas']] = array(
'width' => intval($item['fixed_width']) . 'px',
);
}
else {
$css['.' . $renderer->base['canvas']] = array(
'width' => 'auto',
);
}
foreach ($css as $selector => $data) {
$output[] = ctools_ajax_command_css($selector, $data);
}
}
$output[] = ctools_modal_command_dismiss();
}
$handler->commands = $output;
}
function panels_flexible_config_item_form(&$form_state) {
$display =& $form_state['display'];
$item =& $form_state['item'];
$siblings =& $form_state['siblings'];
$settings =& $form_state['settings'];
$id =& $form_state['id'];
if ($item['type'] == 'region') {
$form['title'] = array(
'#title' => t('Region title'),
'#type' => 'textfield',
'#default_value' => $item['title'],
'#required' => TRUE,
);
}
if ($id == 'canvas') {
$form['class'] = array(
'#title' => t('Canvas class'),
'#type' => 'textfield',
'#default_value' => isset($item['class']) ? $item['class'] : '',
'#description' => t('This class will the primary class for this layout. It will also be appended to all column, row and region_classes to ensure that layouts within layouts will not inherit CSS from each other. If left blank, the name of the layout or ID of the display will be used.'),
);
$form['column_class'] = array(
'#title' => t('Column class'),
'#type' => 'textfield',
'#default_value' => isset($item['column_class']) ? $item['column_class'] : '',
'#description' => t('This class will be applied to all columns of the layout. If left blank this will be panels-flexible-column.'),
);
$form['row_class'] = array(
'#title' => t('Row class'),
'#type' => 'textfield',
'#default_value' => isset($item['row_class']) ? $item['row_class'] : '',
'#description' => t('This class will be applied to all rows of the layout. If left blank this will be panels-flexible-row.'),
);
$form['region_class'] = array(
'#title' => t('Region class'),
'#type' => 'textfield',
'#default_value' => isset($item['region_class']) ? $item['region_class'] : '',
'#description' => t('This class will be applied to all regions of the layout. If left blank this will be panels-flexible-region.'),
);
$form['no_scale'] = array(
'#type' => 'checkbox',
'#title' => t('Scale fluid widths for IE6'),
'#description' => t('IE6 does not do well with 100% widths. If checked, width will be scaled to 99% to compensate.'),
'#default_value' => empty($item['no_scale']),
);
$form['fixed_width'] = array(
'#type' => 'textfield',
'#title' => t('Fixed width'),
'#description' => t('If a value is entered, the layout canvas will be fixed to the given pixel width.'),
'#default_value' => isset($item['fixed_width']) ? $item['fixed_width'] : '',
);
$form['column_separation'] = array(
'#type' => 'textfield',
'#title' => t('Column separation'),
'#description' => t('How much padding to put on columns that are that are next to other columns. Note that this is put on both columns so the real amount is doubled.'),
'#default_value' => isset($item['column_separation']) ? $item['column_separation'] : '0.5em',
);
$form['region_separation'] = array(
'#type' => 'textfield',
'#title' => t('Region separation'),
'#description' => t('How much padding to put on regions that are that are next to other regions. Note that this is put on both regions so the real amount is doubled.'),
'#default_value' => isset($item['region_separation']) ? $item['region_separation'] : '0.5em',
);
$form['row_separation'] = array(
'#type' => 'textfield',
'#title' => t('Row separation'),
'#description' => t('How much padding to put on beneath rows to separate them from each other. Because this is placed only on the bottom, not hte top, this is NOT doubled like column/region separation.'),
'#default_value' => isset($item['row_separation']) ? $item['row_separation'] : '0.5em',
);
}
else {
$form['class'] = array(
'#title' => t('CSS class'),
'#type' => 'textfield',
'#default_value' => isset($item['class']) ? $item['class'] : '',
'#description' => t('Enter a CSS class that will be used. This can be used to apply automatic styling from your theme, for example.'),
);
if ($item['type'] != 'row') {
$left = $right = FALSE;
$current = 'left';
foreach ($siblings as $sibling) {
if ($sibling == $id) {
$current = 'right';
}
else {
if ($settings['items'][$sibling]['width_type'] == '%') {
${$current} = TRUE;
}
}
}
$form['width_type'] = array(
'#type' => 'select',
'#title' => t('Width'),
'#default_value' => $item['width_type'],
'#options' => array(
'%' => t('Fluid'),
'px' => t('Fixed'),
),
'#disabled' => TRUE,
);
}
else {
$form['contains'] = array(
'#type' => 'select',
'#title' => t('Contains'),
'#default_value' => $item['contains'],
'#options' => array(
'region' => t('Regions'),
'column' => t('Columns'),
),
);
if (!empty($item['children'])) {
$form['contains']['#disabled'] = TRUE;
$form['contains']['#value'] = $item['contains'];
$form['contains']['#description'] = t('You must remove contained items to change the row container type.');
}
}
}
$form['save'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
function panels_flexible_config_item_form_submit(&$form, &$form_state) {
$item =& $form_state['item'];
if ($item['type'] == 'region') {
$item['title'] = $form_state['values']['title'];
}
$item['class'] = $form_state['values']['class'];
if ($form_state['id'] == 'canvas') {
$item['column_class'] = $form_state['values']['column_class'];
$item['row_class'] = $form_state['values']['row_class'];
$item['region_class'] = $form_state['values']['region_class'];
$item['no_scale'] = !$form_state['values']['no_scale'];
$item['fixed_width'] = $form_state['values']['fixed_width'];
$item['column_separation'] = $form_state['values']['column_separation'];
$item['region_separation'] = $form_state['values']['region_separation'];
$item['row_separation'] = $form_state['values']['row_separation'];
}
else {
if ($item['type'] != 'row') {
$item['width_type'] = $form_state['values']['width_type'];
}
else {
$item['contains'] = $form_state['values']['contains'];
}
}
}
function panels_ajax_flexible_edit_add($handler, $id, $location = 'left') {
ctools_include('modal');
ctools_include('ajax');
$settings =& $handler->display->layout_settings;
panels_flexible_convert_settings($settings, $handler->plugins['layout']);
if (empty($settings['items'][$id])) {
ctools_modal_render(t('Error'), t('Invalid item id.'));
}
$parent =& $settings['items'][$id];
switch ($parent['type']) {
case 'column':
$title = t('Add row');
$item = array(
'type' => 'row',
'contains' => 'region',
'children' => array(),
'parent' => $id,
);
break;
case 'row':
switch ($parent['contains']) {
case 'region':
$title = $location == 'left' ? t('Add region to left') : t('Add region to right');
$item = array(
'type' => 'region',
'title' => '',
'width' => 100,
'width_type' => '%',
'parent' => $id,
);
break;
case 'column':
$title = $location == 'left' ? t('Add column to left') : t('Add column to right');
$item = array(
'type' => 'column',
'width' => 100,
'width_type' => '%',
'parent' => $id,
'children' => array(),
);
break;
}
break;
case 'region':
break;
}
$form_state = array(
'display' => &$handler->display,
'parent' => &$parent,
'item' => &$item,
'id' => $id,
'settings' => &$settings,
'ajax' => TRUE,
'title' => $title,
'location' => $location,
);
$output = ctools_modal_form_wrapper('panels_flexible_add_item_form', $form_state);
if (empty($output)) {
panels_edit_cache_set($handler->cache);
$output = array();
$css_id = isset($handler->display->css_id) ? $handler->display->css_id : '';
$renderer = panels_flexible_create_renderer(TRUE, $css_id, array(), $settings, $handler->display, $handler->plugins['layout'], $handler);
$content = '';
if ($item['type'] == 'region') {
$handler->plugins['layout']['panels'][$form_state['key']] = $item['title'];
$content = $handler
->render_region($form_state['key'], array());
$content .= '<input type="hidden" name="panel[pane][' . $form_state['key'] . ']" id="edit-panel-pane-' . $form_state['key'] . '" value="" />';
}
else {
foreach (array(
'left',
'middle',
'right',
) as $position) {
if (!empty($content) || $renderer->admin) {
$content .= '<div class="' . $renderer->base[$item['type']] . '-' . $form_state['key'] . '-' . $position . '"></div>';
}
}
}
$parent_class = $renderer->base[$parent['type']] . '-' . $id;
$item_output = panels_flexible_render_item($renderer, $item, $content, $form_state['key'], 0, 0, $item['type'] == 'row');
$css = array();
panels_flexible_get_css_group($css, $renderer, $parent['children'], '.' . $parent_class, $item['type'], $id);
$position = isset($renderer->positions[$form_state['key']]) ? $renderer->positions[$form_state['key']] : 'middle';
switch ($position) {
case 'left':
if ($location == 'left') {
$item_output .= panels_flexible_render_splitter($renderer, $form_state['key'], $form_state['sibling']);
$output[] = ctools_ajax_command_prepend('#panels-dnd-main .' . $parent_class . '-left', $item_output);
}
else {
if ($location == 'right') {
$output[] = ctools_ajax_command_remove('panels-flexible-splitter-for-' . $renderer->base[$item['type']] . '-' . $form_state['key']);
$item_output = panels_flexible_render_splitter($renderer, $form_state['sibling'], $form_state['key']) . $item_output;
$item_output .= panels_flexible_render_splitter($renderer, $form_state['key'], NULL);
$output[] = ctools_ajax_command_append('#panels-dnd-main .' . $parent_class . '-left', $item_output);
}
}
break;
case 'right':
if (!empty($form_state['sibling'])) {
$item_output = panels_flexible_render_splitter($renderer, $form_state['sibling'], $form_state['key']) . $item_output;
}
$output[] = ctools_ajax_command_append('#panels-dnd-main .' . $parent_class . '-right', $item_output);
break;
case 'middle':
if ($location == 'left') {
if (!empty($form_state['sibling'])) {
$item_output .= panels_flexible_render_splitter($renderer, $form_state['key'], $form_state['sibling']);
}
$output[] = ctools_ajax_command_prepend('#panels-dnd-main .' . $parent_class . '-middle', $item_output);
}
else {
if (!empty($form_state['sibling'])) {
$item_output = panels_flexible_render_splitter($renderer, $form_state['sibling'], $form_state['key']) . $item_output;
}
$output[] = ctools_ajax_command_append('#panels-dnd-main .' . $parent_class . '-middle', $item_output);
}
break;
}
$output[] = array(
'command' => 'flexible_fix_height',
);
if (!empty($form_state['sibling'])) {
$sibling_width = '#panels-dnd-main .' . $renderer->base[$item['type']] . '-' . $form_state['sibling'] . '-width';
$output[] = ctools_ajax_command_html($sibling_width, $settings['items'][$form_state['sibling']]['width']);
}
foreach ($css as $selector => $data) {
$output[] = ctools_ajax_command_css($selector, $data);
}
$output[] = ctools_ajax_command_replace('.flexible-links-' . $id, panels_flexible_render_item_links($renderer, $id, $parent));
$output[] = array(
'command' => 'flexible_fix_firstlast',
'selector' => '.' . $parent_class . '-inside',
'base' => 'panels-flexible-' . $item['type'],
);
$output[] = ctools_modal_command_dismiss();
}
$handler->commands = $output;
}
function panels_flexible_add_item_form(&$form_state) {
$display =& $form_state['display'];
$item =& $form_state['item'];
$parent =& $form_state['parent'];
$settings =& $form_state['settings'];
$location =& $form_state['location'];
$id =& $form_state['id'];
if ($item['type'] == 'region') {
$form['title'] = array(
'#title' => t('Region title'),
'#type' => 'textfield',
'#default_value' => $item['title'],
'#required' => TRUE,
);
}
$form['class'] = array(
'#title' => t('CSS Class'),
'#type' => 'textfield',
'#default_value' => isset($item['class']) ? $item['class'] : '',
'#description' => t('Enter a CSS class that will be used. This can be used to apply automatic styling from your theme, for example.'),
);
if ($item['type'] != 'row') {
$restrict = FALSE;
if (!empty($parent['children'])) {
if ($location == 'left') {
$sibling = reset($parent['children']);
}
else {
$sibling = end($parent['children']);
}
if ($settings['items'][$sibling]['width_type'] == 'px') {
$restrict = TRUE;
$item['width_type'] = 'px';
}
}
$form['width_type'] = array(
'#type' => 'select',
'#title' => t('Width'),
'#default_value' => $item['width_type'],
'#options' => array(
'%' => t('Fluid'),
'px' => t('Fixed'),
),
'#disabled' => $restrict,
);
if ($restrict) {
$form['width_type']['#value'] = $item['width_type'];
$form['width_type']['#description'] = t('Items cannot be set to fluid if there are fixed items already on that side.');
}
}
else {
$form['contains'] = array(
'#type' => 'select',
'#title' => t('Contains'),
'#default_value' => $item['contains'],
'#options' => array(
'region' => t('Regions'),
'column' => t('Columns'),
),
);
}
$form['save'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
function panels_flexible_add_item_form_submit(&$form, &$form_state) {
$item =& $form_state['item'];
$parent =& $form_state['parent'];
$location =& $form_state['location'];
$settings =& $form_state['settings'];
$item['class'] = $form_state['values']['class'];
if ($item['type'] == 'region') {
$item['title'] = $form_state['values']['title'];
}
if ($item['type'] != 'row') {
$item['width_type'] = $form_state['values']['width_type'];
}
else {
$item['contains'] = $form_state['values']['contains'];
}
if ($item['type'] == 'region') {
$key = preg_replace("/[^a-z0-9]/", '_', drupal_strtolower($item['title']));
while (isset($settings['items'][$key])) {
$key .= '_';
}
$form_state['key'] = $key;
}
else {
$form_state['key'] = $key = max(array_keys($settings['items'])) + 1;
}
$form_state['sibling'] = NULL;
if ($item['type'] != 'row' && !empty($parent['children'])) {
if ($location == 'left') {
$form_state['sibling'] = reset($parent['children']);
}
else {
$form_state['sibling'] = end($parent['children']);
}
if ($form_state['sibling'] && $settings['items'][$form_state['sibling']]['width_type'] == $item['width_type']) {
$width = $settings['items'][$form_state['sibling']]['width'] / 2;
$settings['items'][$form_state['sibling']]['width'] = $width;
$item['width'] = $width;
}
}
$settings['items'][$key] = $item;
if ($location == 'left') {
array_unshift($parent['children'], $key);
}
else {
$parent['children'][] = $key;
}
}
function panels_ajax_flexible_edit_remove($handler, $id) {
$settings =& $handler->display->layout_settings;
panels_flexible_convert_settings($settings, $handler->plugins['layout']);
if (empty($settings['items'][$id])) {
ctools_ajax_render_error(t('Invalid item id.'));
}
$item =& $settings['items'][$id];
$css_id = isset($handler->display->css_id) ? $handler->display->css_id : '';
$renderer = panels_flexible_create_renderer(TRUE, $css_id, array(), $settings, $handler->display, $handler->plugins['layout'], $handler);
$siblings =& $settings['items'][$item['parent']]['children'];
$parent_class = '.' . $renderer->base[$settings['items'][$item['parent']]['type']] . '-' . $item['parent'];
$offset = array_search($id, $siblings);
if ($item['type'] != 'row') {
if (isset($siblings[$offset + 1])) {
$next = $siblings[$offset + 1];
}
if (isset($siblings[$offset - 1])) {
$prev = $siblings[$offset - 1];
}
if ($item['width_type'] == '%') {
if (isset($next) && $settings['items'][$next]['width_type'] == '%') {
$settings['items'][$next]['width'] += $item['width'];
}
else {
if (isset($prev) && $settings['items'][$prev]['width_type'] == '%') {
$settings['items'][$prev]['width'] += $item['width'];
}
}
}
}
array_splice($siblings, $offset, 1);
unset($settings['items'][$id]);
panels_edit_cache_set($handler->cache);
$class = $renderer->base[$item['type']] . '-' . $id;
$output = array();
$output[] = ctools_ajax_command_remove('#panels-dnd-main .' . $class);
if (!empty($siblings)) {
$css = array();
panels_flexible_get_css_group($css, $renderer, $siblings, $parent_class, $item['type'], $item['parent']);
foreach ($css as $selector => $data) {
$output[] = ctools_ajax_command_css($selector, $data);
}
}
if (!empty($prev)) {
$output[] = ctools_ajax_command_remove('.flexible-splitter-for-' . $renderer->base[$item['type']] . '-' . $prev);
}
$output[] = ctools_ajax_command_remove('.flexible-splitter-for-' . $renderer->base[$item['type']] . '-' . $id);
if (!empty($prev) && !empty($next)) {
$splitter = panels_flexible_render_splitter($renderer, $prev, $next);
$prev_class = '#panels-dnd-main .' . $renderer->base[$item['type']] . '-' . $prev;
$output[] = ctools_ajax_command_after($prev_class, $splitter);
$output[] = array(
'command' => 'flexible_fix_height',
);
}
$output[] = ctools_ajax_command_replace('.flexible-links-' . $item['parent'], panels_flexible_render_item_links($renderer, $item['parent'], $settings['items'][$item['parent']]));
$output[] = array(
'command' => 'flexible_fix_firstlast',
'selector' => $parent_class . '-inside',
'base' => 'panels-flexible-' . $item['type'],
);
$handler->commands = $output;
}
function panels_ajax_flexible_edit_resize($handler) {
ctools_include('ajax');
$settings =& $handler->display->layout_settings;
panels_flexible_convert_settings($settings, $handler->plugins['layout']);
$settings['items'][$_POST['left']]['width'] = $_POST['left_width'];
if (!empty($_POST['right']) && $_POST['right'] != $_POST['left']) {
$settings['items'][$_POST['right']]['width'] = $_POST['right_width'];
}
panels_edit_cache_set($handler->cache);
$handler->commands = array(
'ok',
);
}
function panels_ajax_flexible_edit_reuse($handler) {
$settings =& $handler->display->layout_settings;
panels_flexible_convert_settings($settings, $handler->plugins['layout']);
$form_state = array(
'display' => &$handler->display,
'settings' => &$settings,
'ajax' => TRUE,
'title' => t('Save this layout for reuse'),
);
$output = ctools_modal_form_wrapper('panels_flexible_reuse_form', $form_state);
if (empty($output)) {
ctools_include('export');
$layout = ctools_export_crud_new('panels_layout');
$layout->plugin = 'flexible';
$layout->name = $form_state['values']['name'];
$layout->admin_title = $form_state['values']['admin_title'];
$layout->admin_description = $form_state['values']['admin_description'];
$layout->category = $form_state['values']['category'];
$layout->settings = $handler->display->layout_settings;
ctools_export_crud_save('panels_layout', $layout);
if (empty($form_state['values']['keep'])) {
$handler->display->layout = 'flexible:' . $layout->name;
$handler->display->layout_settings = array();
panels_edit_cache_set($handler->cache);
}
$output[] = ctools_modal_command_dismiss();
}
$handler->commands = $output;
}
function panels_flexible_reuse_form(&$form_state) {
$form['markup'] = array(
'#prefix' => '<div class="description">',
'#suffix' => '</div>',
'#value' => t('If you save this layout for reuse it will appear in the list of reusable layouts at admin/build/panels/layouts, and you will need to go there to edit it. This layout will then become an option for all future panels you make.'),
);
$form['admin_title'] = array(
'#type' => 'textfield',
'#title' => t('Administrative title'),
'#description' => t('This will appear in the administrative interface to easily identify it.'),
);
$form['name'] = array(
'#type' => 'textfield',
'#title' => t('Machine name'),
'#description' => t('The machine readable name of this layout. It must be unique, and it must contain only alphanumeric characters and underscores. Once created, you will not be able to change this value!'),
);
$form['category'] = array(
'#type' => 'textfield',
'#title' => t('Category'),
'#description' => t('What category this layout should appear in. If left blank the category will be "Miscellaneous".'),
);
$form['admin_description'] = array(
'#type' => 'textarea',
'#title' => t('Administrative description'),
'#description' => t('A description of what this layout is, does or is for, for administrative use.'),
);
$form['keep'] = array(
'#type' => 'checkbox',
'#title' => t('Keep current panel layout flexible'),
'#description' => t('If checked, this panel will continue to use a generic flexible layout and will not use the saved layout. Use this option if you wish to clone this layout.'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
function panels_flexible_reuse_form_validate(&$form, &$form_state) {
if (empty($form_state['values']['name'])) {
form_error($form['name'], t('You must choose a machine name.'));
}
ctools_include('export');
$test = ctools_export_crud_load('panels_layout', $form_state['values']['name']);
if ($test) {
form_error($form['name'], t('That name is used by another layout: @layout', array(
'@layout' => $test->admin_title,
)));
}
if (preg_match('/[^a-zA-Z0-9_]/', $form_state['values']['name'])) {
form_error($form['name'], t('Name must be alphanumeric or underscores only.'));
}
}