diff --git a/core/modules/display/display.module b/core/modules/display/display.module
index 5362711..549a2e5 100644
--- a/core/modules/display/display.module
+++ b/core/modules/display/display.module
@@ -20,7 +20,7 @@ function display_menu() {
'file' => 'display.admin.inc',
);
$items['admin/structure/layouts/manage/%display'] = array(
- 'title' => 'View layout',
+ 'title' => 'Edit layout',
'page callback' => 'display_page_edit',
'page arguments' => array(4),
'access callback' => 'user_access',
@@ -81,3 +81,10 @@ function display_entity_info_alter(&$entity_info) {
$entity_info['display']['list_path'] = 'admin/structure/layouts';
$entity_info['display']['entity_keys']['label'] = 'label';
}
+
+/**
+ * Ajax callback for block placement display switching.
+ */
+function display_ajax_block_placement_callback($form, &$form_state) {
+ return $form['blocks'];
+}
diff --git a/core/modules/display/lib/Drupal/display/DisplayFormController.php b/core/modules/display/lib/Drupal/display/DisplayFormController.php
index 2fe67f4..ef5e056 100644
--- a/core/modules/display/lib/Drupal/display/DisplayFormController.php
+++ b/core/modules/display/lib/Drupal/display/DisplayFormController.php
@@ -20,23 +20,75 @@ class DisplayFormController extends EntityFormController {
* Overrides Drupal\Core\Entity\EntityFormController::form().
*/
public function form(array $form, array &$form_state, EntityInterface $display) {
- // Get list of layouts and expose that for display layout selection.
+ // Get list of layouts to be exposed for display layout selection.
$layouts = drupal_container()->get('plugin.manager.layout')->getDefinitions();
$layout_options = array();
foreach ($layouts as $key => $layout) {
$layout_options[$key] = $layout['title'];
}
+ $layout_keys = array_keys($layout_options);
+
+ // Add default values to form_state['values'].
+ if (!isset($form_state['values'])) {
+ $form_state['values'] = array();
+ }
+ $form_state['values'] += array(
+ 'layout' => isset($display->layout) ? $display->layout : reset($layout_keys),
+ );
+
$form['layout'] = array(
'#type' => 'select',
'#title' => t('Layout'),
- '#default_value' => isset($display->layout) ? $display->layout : '',
+ '#default_value' => $form_state['values']['layout'],
'#options' => $layout_options,
+ '#ajax' => array(
+ 'callback' => 'display_ajax_block_placement_callback',
+ 'wrapper' => 'display-blocks',
+ 'method' => 'replace',
+ 'effect' => 'fade',
+ ),
+ );
+
+ // To support the Ajax interaction, remap the display to the newly selected
+ // layout. This will reorganize the blocks as appropriate.
+ $layout = layout_manager()->createInstance($form_state['values']['layout'], array());
+ $display->remapToLayout($layout);
+
+ // Add block editing interface wrapper for Ajax operation.
+ $form['blocks'] = array(
+ '#prefix' => '
',
+ '#suffix' => '
',
+ 'demonstration' => $this->layoutDemonstration($display),
);
return parent::form($form, $form_state, $display);
}
/**
+ * Produces a render array demonstration form of the display.
+ */
+ private function layoutDemonstration(EntityInterface $display) {
+
+ // Render the layout in an admin context with region demonstrations.
+ $layout = layout_manager()->createInstance($display->layout, array());
+ $regions = $layout->getRegions();
+ foreach ($regions as $region => $info) {
+ $region_text = '' . check_plain($info['label']) . '
';
+ $region_text .= '
';
+ $regions[$region] = $region_text;
+ }
+ $build['demonstration'] = array(
+ '#type' => 'markup',
+ '#markup' => $layout->renderLayout(TRUE, $regions),
+ );
+ $build['#attached']['css'][] = drupal_get_path('module', 'display') . '/display.admin.css';
+ $build['#attached']['js'][] = drupal_get_path('module', 'display') . '/display.admin.js';
+ $build['#attached']['library'][] = array('system', 'jquery.ui.sortable');
+ return $build;
+ }
+
+ /**
* Overrides Drupal\Core\Entity\EntityFormController::actions().
*/
protected function actions(array $form, array &$form_state) {
diff --git a/core/modules/display/display.admin.css b/core/modules/display/display.admin.css
new file mode 100644
index 0000000..3fb706d
--- /dev/null
+++ b/core/modules/display/display.admin.css
@@ -0,0 +1,305 @@
+z#display-blocks {
+ background-color:#fff;
+ -moz-box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1);
+ -webkit-box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1);
+ box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1);
+}
+
+z#display-blocks .layout-display {
+ border: 1px solid #ddd;
+ padding: 27px;
+}
+
+/**
+ * Begions.
+ */
+
+#display-blocks .layout-region .region-wrapper {
+ clear:both;
+ margin-top: 5px;
+ padding: 5px 15px 15px 15px;
+ background-color:rgb(255,255,255);
+ border-color:rgb(204,204,204);
+ border-width:1px;
+ border-style:solid;
+ -moz-box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1);
+ -webkit-box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1);
+ box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1);
+}
+
+#display-blocks .region_information {
+ clear:both;
+ display: block;
+ width: 100%;
+ text-align:right;
+ padding-bottom: 3px;
+ margin:0;
+ overflow: hidden;
+}
+
+#display-blocks .region_label {
+ font-size:11px;
+ text-transform: uppercase;
+ letter-spacing:.1em;
+ margin-right: -.1em;
+ color: #666;
+}
+
+#display-blocks .region_table {
+ clear:both;
+ display: table;
+ width: 100%;
+ table-layout:fixed;
+}
+
+/**
+ * Blocks.
+ */
+
+#display-blocks .region_blocks {
+ display: table-row;
+}
+
+#display-blocks .block {
+ clear:both;
+ display: table-cell;
+ padding-right:15px;
+ height: 60px;
+ overflow: hidden;
+}
+
+#display-blocks .master_block {
+ position: relative;
+ display: inline-block;
+ width: 100%;
+ height:100%;
+ background-image:-moz-linear-gradient(rgb(102,149,168) 0%,rgb(92,133,150) 99%,rgb(92,133,150) 100%);
+ background-image:-webkit-gradient(linear,color-stop(0, rgb(102,149,168)),color-stop(0.99, rgb(92,133,150)),color-stop(1, rgb(92,133,150)));
+ background-image:-webkit-linear-gradient(rgb(102,149,168) 0%,rgb(92,133,150) 99%,rgb(92,133,150) 100%);
+ background-image:linear-gradient(rgb(102,149,168) 0%,rgb(92,133,150) 99%,rgb(92,133,150) 100%);
+}
+
+z#display-blocks .layout_block {
+ position: relative;
+ display: inline-block;
+ width: 100%;
+ height:100%;
+ background-image:-moz-linear-gradient(rgb(123,194,170) 0%,rgb(114,179,156) 99%,rgb(114,179,156) 100%);
+ background-image:-webkit-gradient(linear,color-stop(0, rgb(123,194,170)),color-stop(0.99, rgb(114,179,156)),color-stop(1, rgb(114,179,156)));
+ background-image:-webkit-linear-gradient(rgb(123,194,170) 0%,rgb(114,179,156) 99%,rgb(114,179,156) 100%);
+ background-image:linear-gradient(rgb(123,194,170) 0%,rgb(114,179,156) 99%,rgb(114,179,156) 100%);
+}
+
+z#display-blocks .page_block {
+ position: relative;
+ display: inline-block;
+ width: 100%;
+ height:100%;
+ background-image:-moz-linear-gradient(rgb(137,211,124) 0%,rgb(128,198,117) 99%,rgb(128,198,117) 100%);
+ background-image:-webkit-gradient(linear,color-stop(0, rgb(137,211,124)),color-stop(0.99, rgb(128,198,117)),color-stop(1, rgb(128,198,117)));
+ background-image:-webkit-linear-gradient(rgb(137,211,124) 0%,rgb(128,198,117) 99%,rgb(128,198,117) 100%);
+ background-image:linear-gradient(rgb(137,211,124) 0%,rgb(128,198,117) 99%,rgb(128,198,117) 100%);
+}
+
+#display-blocks .add_block {
+ display: table-cell;
+ border: 1px solid #ddd;
+ width: 60px !important;
+ height: 60px;
+ background-image:-moz-linear-gradient(rgb(254,254,254) 0%,rgb(225,225,225) 100%);
+ background-image:-webkit-gradient(linear,color-stop(0, rgb(254,254,254)),color-stop(1, rgb(225,225,225)));
+ background-image:-webkit-linear-gradient(rgb(254,254,254) 0%,rgb(225,225,225) 100%);
+ background-image:linear-gradient(rgb(254,254,254) 0%,rgb(225,225,225) 100%);
+}
+
+#display-blocks .add_block:hover {
+ border: 1px solid #ccc;
+ -moz-box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1);
+ -webkit-box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1);
+ box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1);
+}
+
+#display-blocks .add_block_press {
+ border: 1px solid #c5c5c5;
+ background-image:-moz-linear-gradient(rgb(245,245,245) 0%,rgb(221,221,221) 100%);
+ background-image:-webkit-gradient(linear,color-stop(0, rgb(245,245,245)),color-stop(1, rgb(221,221,221)));
+ background-image:-webkit-linear-gradient(rgb(245,245,245) 0%,rgb(221,221,221) 100%);
+ background-image:linear-gradient(rgb(245,245,245) 0%,rgb(221,221,221) 100%);
+}
+
+#display-blocks .plus_icon {
+ display: inline-block;
+ width: 100%;
+ height: 100%;
+ background-image:url(plus.png);
+ background-position:center;
+ background-repeat:no-repeat;
+}
+
+z#display-blocks .rowspan {
+ width: 100%;
+ position: relative;
+}
+
+z#display-blocks .column-left {
+ position:relative;
+ float: left;
+ width: 69.7%;
+ margin-bottom: 5px;
+}
+
+z#display-blocks .column-right {
+ float: right;
+ width: 30%;
+ margin-bottom: 5px;
+}
+
+/**
+ * Block information.
+ */
+
+#display-blocks .block_information {
+ position: relative;
+ float: left;
+}
+
+#display-blocks .block_type_indicator {
+ position: absolute;
+ left:0;
+ top:0;
+ width: 22px;
+ height: 22px;
+ border-right: 1px solid #fff;
+ border-bottom: 1px solid #fff;
+ text-align: center;
+ vertical-align:middle;
+ line-height: 200%;
+ font-size:11px;
+ font-weight:bold;
+}
+
+#display-blocks .block_label {
+ position: absolute;
+ left: 27px;
+ top:2px;
+ font-size:14px;
+ font-weight:bold;
+ color:rgb(255,255,255);
+ text-align:left;
+ margin-left:3px;
+}
+
+z#display-blocks .pb_text {
+ color: #555;
+}
+
+z#display-blocks .lb_text {
+ color: #555;
+}
+
+#display-blocks .mb_text {
+ color: #fff;
+}
+
+/**
+ * Block operations.
+ */
+
+#display-blocks .mb_block_operations {
+ position: absolute;
+ opacity:0;
+ left: 0;
+ top: 23px;
+ width: 100%;
+ height: 100%;
+ text-align: center;
+ background-color: transparent;
+ -webkit-transition: all 0.3s;
+ -webkit-transition-property: all;
+ -webkit-transition-duration: 0.3s;
+ -webkit-transition-delay: initial;
+}
+
+#display-blocks .mb_block_operations:hover {
+ opacity:1;
+}
+
+z#display-blocks .lb_block_operations {
+ position: absolute;
+ opacity:0;
+ left: 0;
+ top: 23px;
+ width: 100%;
+ height: 100%;
+ text-align: center;
+ background-color: transparent;
+ -webkit-transition: all 0.3s;
+ -webkit-transition-property: all;
+ -webkit-transition-duration: 0.3s;
+ -webkit-transition-delay: initial;
+}
+
+z#display-blocks .lb_block_operations:hover {
+ opacity:1;
+}
+
+z#display-blocks .pb_block_operations {
+ position: absolute;
+ opacity:0;
+ left: 0;
+ top: 23px;
+ width: 100%;
+ height: 100%;
+ text-align: center;
+ background-color: transparent;
+ -webkit-transition: all 0.3s;
+ -webkit-transition-property: all;
+ -webkit-transition-duration: 0.3s;
+ -webkit-transition-delay: initial;
+}
+
+z#display-blocks .pb_block_operations:hover {
+ opacity:1;
+}
+
+z#display-blocks .drag {
+ display:inline-block;
+ width: 25px;
+ height: 20px;
+ background-position:center;
+ background-repeat:no-repeat;
+}
+
+#display-blocks .gear {
+ display:inline-block;
+ width:25px;
+ height:20px;
+ background-position:center;
+ background-repeat:no-repeat;
+}
+
+#display-blocks .mb_gear {
+ background-image:url(gear_fff.png);
+}
+
+z#display-blocks .mb_drag {
+ background-image:url(drag_fff.png);
+}
+
+z#display-blocks .pb_gear {
+ background-image:url(gear_555.png);
+}
+
+z#display-blocks .pb_drag {
+ background-image:url(drag_555.png);
+}
+
+z#display-blocks .lb_gear {
+ background-image:url(gear_555.png);
+}
+
+z#display-blocks .lb_drag {
+ background-image:url(drag_555.png);
+}
+
+
diff --git a/core/modules/display/display.admin.js b/core/modules/display/display.admin.js
new file mode 100644
index 0000000..8298e6c
--- /dev/null
+++ b/core/modules/display/display.admin.js
@@ -0,0 +1,32 @@
+(function ($, window) {
+
+"use strict";
+
+/**
+ * Add new blocks to a display.
+ */
+Drupal.behaviors.displayAddBlock = {
+ attach: function () {
+ $('.region_table .add_block').click(function () {
+ var chars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
+ var randomString = '';
+ for (var i=0; i < 8; i++) {
+ var rnum = Math.floor(Math.random() * chars.length);
+ randomString += chars.substring(rnum,rnum+1);
+ }
+
+ var block = 'M' + randomString + ' block
';
+ $(this).parent().prepend(block);
+ });
+
+ // Apply drag and drop behavior.
+ $('.region_blocks').sortable({
+ items: '.block',
+ connectWith: '.connectedSortable',
+ cursor: 'move',
+ });
+ $('.region_blocks').disableSelection();
+ }
+};
+
+})(jQuery, window);
diff --git a/core/modules/display/gear_fff.png b/core/modules/display/gear_fff.png
new file mode 100644
index 0000000..dfd4aae
diff --git a/core/modules/display/plus.png b/core/modules/display/plus.png
new file mode 100644
index 0000000..b5544c1