diff --git a/core/includes/entity.inc b/core/includes/entity.inc
index 743cc4af0c697b661b49a73bb3103a794154b7ee..9994406009a79837516a172f956c86a8de96e316 100644
--- a/core/includes/entity.inc
+++ b/core/includes/entity.inc
@@ -105,6 +105,44 @@ function entity_invoke_bundle_hook($hook, $entity_type, $bundle, $bundle_new = N
   module_invoke_all('entity_bundle_' . $hook, $entity_type, $bundle, $bundle_new);
 }
 
+/**
+ * Returns the entity form mode info.
+ *
+ * @param string|null $entity_type
+ *   The entity type whose form mode info should be returned, or NULL for all
+ *   form mode info. Defaults to NULL.
+ *
+ * @return array
+ *   The form mode info for a specific entity type, or all entity types.
+ */
+function entity_get_form_modes($entity_type = NULL) {
+  $form_modes = &drupal_static(__FUNCTION__);
+  if (!$form_modes) {
+    $langcode = language(Language::TYPE_INTERFACE)->langcode;
+    if ($cache = cache()->get("entity_form_mode_info:$langcode")) {
+      $form_modes = $cache->data;
+    }
+    else {
+      $form_modes = array();
+      foreach (entity_load_multiple('form_mode') as $form_mode) {
+        list($form_mode_entity_type, $form_mode_name) = explode('.', $form_mode->id(), 2);
+        $form_modes[$form_mode_entity_type][$form_mode_name] = (array) $form_mode;
+      }
+      drupal_alter('entity_form_mode_info', $form_modes);
+      cache()->set("entity_form_mode_info:$langcode", $form_modes, CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE));
+    }
+  }
+
+  if (empty($entity_type)) {
+    return $form_modes;
+  }
+  elseif (isset($form_modes[$entity_type])) {
+    return $form_modes[$entity_type];
+  }
+
+  return array();
+}
+
 /**
  * Returns the entity view mode info.
  *
@@ -791,9 +829,13 @@ function entity_get_render_form_display(EntityInterface $entity, $form_mode) {
   $entity_type = $entity->entityType();
   $bundle = $entity->bundle();
 
-  // @todo Form modes don't have custom settings yet, so just return the display
-  // for the form mode that was requested.
-  $form_display = entity_get_form_display($entity_type, $bundle, $form_mode);
+  // Determine the form display to use for rendering this entity form. Depending
+  // on the configuration of the form mode for this bundle, this will be either
+  // the form display associated to the form mode, or the 'default' display.
+  $form_mode_settings = field_form_mode_settings($entity_type, $bundle);
+  $render_form_mode = !empty($form_mode_settings[$form_mode]['status']) ? $form_mode : 'default';
+
+  $form_display = entity_get_form_display($entity_type, $bundle, $render_form_mode);
   $form_display->originalMode = $form_mode;
 
   return $form_display;
diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php
index d34d3f001d88ce650fd4ca9c8952df1a2dbdc02e..1100fa8e3793396231d4f186682244189eeedcc9 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormController.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormController.php
@@ -129,15 +129,13 @@ protected function init(array &$form_state) {
     $form_state['controller'] = $this;
     $this->prepareEntity();
 
-    // @todo Allow the usage of different form modes by exposing a hook and the
-    // UI for them.
-    $form_display = entity_get_render_form_display($this->entity, 'default');
+    $form_display = entity_get_render_form_display($this->entity, $this->getOperation());
 
     // Let modules alter the form display.
     $form_display_context = array(
       'entity_type' => $this->entity->entityType(),
       'bundle' => $this->entity->bundle(),
-      'form_mode' => 'default',
+      'form_mode' => $this->getOperation(),
     );
     \Drupal::moduleHandler()->alter('entity_form_display', $form_display, $form_display_context);
 
@@ -158,12 +156,8 @@ public function form(array $form, array &$form_state) {
       field_attach_form($entity, $form, $form_state, $this->getFormLangcode($form_state));
     }
 
-    // Assign the weights configured in the form display.
-    foreach ($this->getFormDisplay($form_state)->getComponents() as $name => $options) {
-      if (isset($form[$name])) {
-        $form[$name]['#weight'] = $options['weight'];
-      }
-    }
+    // Add a process callback so we can assign weights and hide extra fields.
+    $form['#process'][] = array($this, 'processForm');
 
     if (!isset($form['langcode'])) {
       // If the form did not specify otherwise, default to keeping the existing
@@ -177,6 +171,30 @@ public function form(array $form, array &$form_state) {
     return $form;
   }
 
+  /**
+   * Process callback: assigns weights and hides extra fields.
+   *
+   * @see \Drupal\Core\Entity\EntityFormController::form()
+   */
+  public function processForm($element, $form_state, $form) {
+    // Assign the weights configured in the form display.
+    foreach ($this->getFormDisplay($form_state)->getComponents() as $name => $options) {
+      if (isset($element[$name])) {
+        $element[$name]['#weight'] = $options['weight'];
+      }
+    }
+
+    // Hide extra fields.
+    $extra_fields = field_info_extra_fields($this->entity->entityType(), $this->entity->bundle(), 'form');
+    foreach ($extra_fields as $extra_field => $info) {
+      if (!$this->getFormDisplay($form_state)->getComponent($extra_field)) {
+        $element[$extra_field]['#access'] = FALSE;
+      }
+    }
+
+    return $element;
+  }
+
   /**
    * Returns the action form element for the current entity form.
    */
diff --git a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php
index f44b41726e4c415a8d7dcf31a89d150a55cea169..111511e65e924256363ae4e7c4dca72cf545182d 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php
@@ -31,12 +31,8 @@ public function form(array $form, array &$form_state) {
       field_attach_form($entity, $form, $form_state, $this->getFormLangcode($form_state));
     }
 
-    // Assign the weights configured in the form display.
-    foreach ($this->getFormDisplay($form_state)->getComponents() as $name => $options) {
-      if (isset($form[$name])) {
-        $form[$name]['#weight'] = $options['weight'];
-      }
-    }
+    // Add a process callback so we can assign weights and hide extra fields.
+    $form['#process'][] = array($this, 'processForm');
 
     return $form;
   }
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListController.php
index eab2bcd31d42f0fe14f7d5e24e88529702bbabec..346cdff5e88ee91000a130515e44cc7618230637 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListController.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListController.php
@@ -28,11 +28,17 @@ public function getOperations(EntityInterface $entity) {
         'options' => $uri['options'],
         'weight' => 15,
       );
+      $operations['manage-form-display'] = array(
+        'title' => t('Manage form display'),
+        'href' => $uri['path'] . '/form-display',
+        'options' => $uri['options'],
+        'weight' => 20,
+      );
       $operations['manage-display'] = array(
         'title' => t('Manage display'),
         'href' => $uri['path'] . '/display',
         'options' => $uri['options'],
-        'weight' => 20,
+        'weight' => 25,
       );
     }
     return $operations;
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index a7e43cb1e03bcca30e05293f5e47f7907f0b00cd..43b962e6a5cadb0c68770190ab6519615f8c7dd3 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -257,8 +257,10 @@ function comment_menu_alter(&$items) {
   // See comment_entity_bundle_info().
   $items['admin/structure/types/manage/{bundle}/comment/fields']['title'] = 'Comment fields';
   $items['admin/structure/types/manage/{bundle}/comment/fields']['weight'] = 3;
+  $items['admin/structure/types/manage/{bundle}/comment/form-display']['title'] = 'Comment form display';
+  $items['admin/structure/types/manage/{bundle}/comment/form-display']['weight'] = 4;
   $items['admin/structure/types/manage/{bundle}/comment/display']['title'] = 'Comment display';
-  $items['admin/structure/types/manage/{bundle}/comment/display']['weight'] = 4;
+  $items['admin/structure/types/manage/{bundle}/comment/display']['weight'] = 5;
 }
 
 /**
diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module
index 64d97b20429fa49df12970c3d94a903a8cdf27fa..5d26c83b55a82261d0d753f20b6ba6a496cc4eab 100644
--- a/core/modules/contact/contact.module
+++ b/core/modules/contact/contact.module
@@ -314,16 +314,16 @@ function contact_mail($key, &$message, $params) {
  *
  * Add the enable personal contact form to an individual user's account page.
  *
- * @see user_profile_form()
+ * @see \Drupal\user\ProfileFormController::form()
  */
-function contact_form_user_profile_form_alter(&$form, &$form_state) {
+function contact_form_user_form_alter(&$form, &$form_state) {
   $form['contact'] = array(
     '#type' => 'details',
     '#title' => t('Contact settings'),
     '#weight' => 5,
   );
   $account = $form_state['controller']->getEntity();
-  $account_data = Drupal::service('user.data')->get('contact', $account->id(), 'enabled');
+  $account_data = !user_is_anonymous() ? Drupal::service('user.data')->get('contact', $account->id(), 'enabled') : NULL;
   $form['contact']['contact'] = array(
     '#type' => 'checkbox',
     '#title' => t('Personal contact form'),
diff --git a/core/modules/contact/lib/Drupal/contact/CategoryListController.php b/core/modules/contact/lib/Drupal/contact/CategoryListController.php
index db3f829c723c73cd9725876a6347a0d7842a18ca..820010f807189df6bf17433b47a6aa2d9df158cd 100644
--- a/core/modules/contact/lib/Drupal/contact/CategoryListController.php
+++ b/core/modules/contact/lib/Drupal/contact/CategoryListController.php
@@ -27,11 +27,17 @@ public function getOperations(EntityInterface $entity) {
         'options' => $uri['options'],
         'weight' => 11,
       );
+      $operations['manage-form-display'] = array(
+        'title' => t('Manage form display'),
+        'href' => $uri['path'] . '/form-display',
+        'options' => $uri['options'],
+        'weight' => 12,
+      );
       $operations['manage-display'] = array(
         'title' => t('Manage display'),
         'href' => $uri['path'] . '/display',
         'options' => $uri['options'],
-        'weight' => 12,
+        'weight' => 13,
       );
     }
     return $operations;
diff --git a/core/modules/contact/lib/Drupal/contact/Tests/ContactSitewideTest.php b/core/modules/contact/lib/Drupal/contact/Tests/ContactSitewideTest.php
index 24ba989385a1da89b9f82e39204382aeef14a106..a62d0a6aab1757d08e398cf3936b86c8115ae24f 100644
--- a/core/modules/contact/lib/Drupal/contact/Tests/ContactSitewideTest.php
+++ b/core/modules/contact/lib/Drupal/contact/Tests/ContactSitewideTest.php
@@ -237,7 +237,6 @@ function testSiteWideContact() {
       'fields[_add_new_field][label]' => $field_label = $this->randomName(),
       'fields[_add_new_field][field_name]' => Unicode::strtolower($this->randomName()),
       'fields[_add_new_field][type]' => 'text',
-      'fields[_add_new_field][widget_type]' => 'text_textfield',
     );
     $field_name = 'field_' . $edit['fields[_add_new_field][field_name]'];
     $this->drupalPost(NULL, $edit, t('Save'));
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php
index 610f6fd34481c7a4bc5a976afdcdc6f558af6224..267f691e94661894d5f991de7fdd9663f3c29a53 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php
@@ -188,4 +188,19 @@ function settingsForm(array $form, array &$form_state) {
     return $element;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+
+    $summary[] = t('Date part order: !order', array('!order' => $this->getSetting('date_order')));
+    if ($this->getFieldSetting('datetime_type') == 'datetime') {
+      $summary[] = t('Time type: !time_type', array('!time_type' => $this->getSetting('time_type')));
+    }
+    $summary[] = t('Time increments: !increment', array('!increment' => $this->getSetting('increment')));
+
+    return $summary;
+  }
+
 }
diff --git a/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php b/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php
index cecc67694fa1129a123239085b27c729834ca187..8930ace43c9b2afc1a29175dd626bd0cf7387c4c 100644
--- a/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php
+++ b/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php
@@ -68,7 +68,7 @@ public function generate(EntityInterface $entity, FieldInstance $instance, $lang
     }
 
     // Early-return if no editor is available.
-    $formatter_id = entity_get_render_display($entity, $view_mode)->getFormatter($instance['field_name'])->getPluginId();
+    $formatter_id = entity_get_render_display($entity, $view_mode)->getRenderer($instance['field_name'])->getPluginId();
     $items = $entity->getTranslation($langcode, FALSE)->get($field_name)->getValue();
     $editor_id = $this->editorSelector->getEditor($formatter_id, $instance, $items);
     if (!isset($editor_id)) {
diff --git a/core/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php b/core/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php
index 9cd6a99626f938220d42d00eb24d7046b08062d0..0e514520c75d048ed3a3cdb19a1c9988f75dafa8 100644
--- a/core/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php
+++ b/core/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php
@@ -41,6 +41,23 @@ public function settingsForm(array $form, array &$form_state) {
     return $element;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+
+    $placeholder = $this->getSetting('placeholder');
+    if (!empty($placeholder)) {
+      $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder));
+    }
+    else {
+      $summary[] = t('No placeholder');
+    }
+
+    return $summary;
+  }
+
   /**
    * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement().
    */
diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php
index 0a7ff40b8e4a6a908bb7afd659dbae00112c6295..99008e202c7e6d951d74a3d12ced4634665a0f84 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php
@@ -163,7 +163,7 @@ public function createCopy($mode) {
   public function getComponents() {
     $result = array();
     foreach ($this->content as $name => $options) {
-      if (!isset($options['visible']) || $options['visible'] === TRUE) {
+      if (!isset($options['visible']) || $options['visible'] == TRUE) {
         unset($options['visible']);
         $result[$name] = $options;
       }
diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayBaseInterface.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayBaseInterface.php
index 42a68c079c98f07b6060de7dcb18c1ce1854ef53..06647e76e618777664256d64e0acfb42421ab8bb 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityDisplayBaseInterface.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayBaseInterface.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\entity\Plugin\Core\Entity\EntityDisplayBaseInterface.
+ * Contains \Drupal\entity\EntityDisplayBaseInterface.
  */
 
 namespace Drupal\entity;
@@ -81,4 +81,15 @@ public function removeComponent($name);
    */
   public function getHighestWeight();
 
+  /**
+   * Returns the renderer plugin for a field (e.g. widget, formatter).
+   *
+   * @param string $field_name
+   *   The field name.
+   *
+   * @return \Drupal\field\Plugin\PluginSettingsInterface|null
+   *   A widget or formatter plugin or NULL if the field does not exist.
+   */
+  public function getRenderer($field_name);
+
 }
diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayInterface.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayInterface.php
index ef8a7cb6ed347beeff403e02e390a040d3ea40cd..08d49c0d856ba9d575c27c38eeafc381be23cf35 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityDisplayInterface.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayInterface.php
@@ -14,16 +14,4 @@
  */
 interface EntityDisplayInterface extends EntityDisplayBaseInterface {
 
-  /**
-   * Returns the Formatter plugin for a field.
-   *
-   * @param string $field_name
-   *   The field name.
-   *
-   * @return \Drupal\field\Plugin\Type\Formatter\FormatterInterface
-   *   If the field is not hidden, the Formatter plugin to use for rendering
-   *   it.
-   */
-  public function getFormatter($field_name);
-
 }
diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php
new file mode 100644
index 0000000000000000000000000000000000000000..4fe2c125663b06e2a35275da9079c0605bf0edcb
--- /dev/null
+++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\entity\EntityDisplayModeBase.
+ */
+
+namespace Drupal\entity;
+
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+
+/**
+ * Base class for config entity types that hold settings for form and view modes.
+ */
+abstract class EntityDisplayModeBase extends ConfigEntityBase {
+
+  /**
+   * The ID of the form or view mode.
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * The UUID of the form or view mode.
+   *
+   * @var string
+   */
+  public $uuid;
+
+  /**
+   * The human-readable name of the form or view mode.
+   *
+   * @var string
+   */
+  public $label;
+
+  /**
+   * The entity type this form or view mode is used for.
+   *
+   * This is not to be confused with EntityViewMode::entityType which is
+   * inherited from Entity::entityType.
+   *
+   * @var string
+   */
+  public $targetEntityType;
+
+  /**
+   * Whether or not this form or view mode has custom settings by default.
+   *
+   * If FALSE, entities displayed in this mode will reuse the 'default' display
+   * settings by default (e.g. right after the module exposing the form or view
+   * mode is enabled), but administrators can later use the Field UI to apply
+   * custom display settings specific to the form or view mode.
+   *
+   * @var bool
+   */
+  public $status = FALSE;
+
+}
diff --git a/core/modules/entity/lib/Drupal/entity/EntityViewModeStorageController.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeStorageController.php
similarity index 65%
rename from core/modules/entity/lib/Drupal/entity/EntityViewModeStorageController.php
rename to core/modules/entity/lib/Drupal/entity/EntityDisplayModeStorageController.php
index 495f0c9c796e13eecbd44e74b8cf627388029bf3..cca791ec5a4418a527661276e7fdb26d8f6a6c79 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityViewModeStorageController.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeStorageController.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\entity\EntityViewModeStorageController.
+ * Contains \Drupal\entity\EntityDisplayModeStorageController.
  */
 
 namespace Drupal\entity;
@@ -11,9 +11,9 @@
 use Drupal\Core\Entity\EntityInterface;
 
 /**
- * Defines the storage controller class for entity view modes.
+ * Defines the storage controller class for entity form and view modes.
  */
-class EntityViewModeStorageController extends ConfigStorageController {
+class EntityDisplayModeStorageController extends ConfigStorageController {
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/entity/lib/Drupal/entity/EntityFormDisplayInterface.php b/core/modules/entity/lib/Drupal/entity/EntityFormDisplayInterface.php
index dce1f683934cdf5b66e08f47be28803f95c1795a..7f6e61a32aba34d77f045e9018d98f726c655013 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityFormDisplayInterface.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityFormDisplayInterface.php
@@ -14,15 +14,4 @@
  */
 interface EntityFormDisplayInterface extends EntityDisplayBaseInterface {
 
-  /**
-   * Returns the Widget plugin for a field.
-   *
-   * @param string $field_name
-   *   The field name.
-   *
-   * @return \Drupal\field\Plugin\Type\Widget\WidgetInterface|null
-   *   A Widget plugin or NULL if the field does not exist.
-   */
-  public function getWidget($field_name);
-
 }
diff --git a/core/modules/entity/lib/Drupal/entity/EntityFormModeInterface.php b/core/modules/entity/lib/Drupal/entity/EntityFormModeInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..9a0a199251c5b3621ce30a94d0777ffdc1149b7c
--- /dev/null
+++ b/core/modules/entity/lib/Drupal/entity/EntityFormModeInterface.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\entity\EntityFormModeInterface.
+ */
+
+namespace Drupal\entity;
+
+use Drupal\Core\Config\Entity\ConfigEntityInterface;
+
+/**
+ * Provides an interface defining an entity form mode entity type.
+ */
+interface EntityFormModeInterface extends ConfigEntityInterface {
+
+}
diff --git a/core/modules/entity/lib/Drupal/entity/EntityViewModeInterface.php b/core/modules/entity/lib/Drupal/entity/EntityViewModeInterface.php
index 718479ff771d1eced7448fb914d7a883cd84eb7d..f43c2df77c9d8fe0db6351ed1a677ac5119ffa00 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityViewModeInterface.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityViewModeInterface.php
@@ -10,7 +10,7 @@
 use Drupal\Core\Config\Entity\ConfigEntityInterface;
 
 /**
- * Provides an interface defining an entity view mode entity.
+ * Provides an interface defining an entity view mode entity type.
  */
 interface EntityViewModeInterface extends ConfigEntityInterface {
 
diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php
index f8c3f5b5cec4619ec0f0c6f21b2b6c228f9e260f..78963bc42fa904de88b8ad9bd13baf4c39d85b67 100644
--- a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php
+++ b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php
@@ -45,7 +45,7 @@ public function __construct(array $values, $entity_type) {
   /**
    * {@inheritdoc}
    */
-  public function getFormatter($field_name) {
+  public function getRenderer($field_name) {
     if (isset($this->plugins[$field_name])) {
       return $this->plugins[$field_name];
     }
diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php
index 8c7298635ddd0aed7153510f2c4383c0d32ff1e6..9a3f0a63d09a022169ec1a2bdc861a456fa2a034 100644
--- a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php
+++ b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php
@@ -45,7 +45,7 @@ public function __construct(array $values, $entity_type) {
   /**
    * {@inheritdoc}
    */
-  public function getWidget($field_name) {
+  public function getRenderer($field_name) {
     if (isset($this->plugins[$field_name])) {
       return $this->plugins[$field_name];
     }
diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormMode.php b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormMode.php
new file mode 100644
index 0000000000000000000000000000000000000000..c539d5e8181bb7fc91dd544554102e12e42a9d96
--- /dev/null
+++ b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormMode.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\entity\Plugin\Core\Entity\EntityFormMode.
+ */
+
+namespace Drupal\entity\Plugin\Core\Entity;
+
+use Drupal\Core\Entity\Annotation\EntityType;
+use Drupal\Core\Annotation\Translation;
+use Drupal\entity\EntityDisplayModeBase;
+use Drupal\entity\EntityFormModeInterface;
+
+/**
+ * Defines the form mode configuration entity class.
+ *
+ * Form modes allow entity forms to be displayed differently depending on the
+ * context. For instance, the user entity form can be displayed with a set of
+ * fields on the 'profile' page (user edit page) and with a different set of
+ * fields (or settings) on the user registration page. Modules taking part in
+ * the display of the entity form (notably the Field API) can adjust their
+ * behavior depending on the requested form mode. An additional 'default' form
+ * mode is available for all entity types. For each available form mode,
+ * administrators can configure whether it should use its own set of field
+ * display settings, or just replicate the settings of the 'default' form mode,
+ * thus reducing the amount of form display configurations to keep track of.
+ *
+ * @see entity_get_form_modes()
+ * @see hook_entity_form_mode_info_alter()
+ *
+ * @EntityType(
+ *   id = "form_mode",
+ *   label = @Translation("Form mode"),
+ *   module = "entity",
+ *   controllers = {
+ *     "storage" = "Drupal\entity\EntityDisplayModeStorageController"
+ *   },
+ *   config_prefix = "entity.form_mode",
+ *   entity_keys = {
+ *     "id" = "id",
+ *     "label" = "label",
+ *     "uuid" = "uuid"
+ *   }
+ * )
+ */
+class EntityFormMode extends EntityDisplayModeBase implements EntityFormModeInterface {
+
+}
diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityViewMode.php b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityViewMode.php
index c2c54dd916b3b90b028aec385f77be732e9f9687..b0d1efef3b41034a1ca99c75db984c20842f7c96 100644
--- a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityViewMode.php
+++ b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityViewMode.php
@@ -7,9 +7,9 @@
 
 namespace Drupal\entity\Plugin\Core\Entity;
 
-use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\Core\Entity\Annotation\EntityType;
 use Drupal\Core\Annotation\Translation;
+use Drupal\entity\EntityDisplayModeBase;
 use Drupal\entity\EntityViewModeInterface;
 
 /**
@@ -35,7 +35,7 @@
  *   label = @Translation("View mode"),
  *   module = "entity",
  *   controllers = {
- *     "storage" = "Drupal\entity\EntityViewModeStorageController"
+ *     "storage" = "Drupal\entity\EntityDisplayModeStorageController"
  *   },
  *   config_prefix = "entity.view_mode",
  *   entity_keys = {
@@ -45,50 +45,6 @@
  *   }
  * )
  */
-class EntityViewMode extends ConfigEntityBase implements EntityViewModeInterface {
-
-  /**
-   * The ID of the view mode.
-   *
-   * @var string
-   */
-  public $id;
-
-  /**
-   * The UUID of the view mode.
-   *
-   * @var string
-   */
-  public $uuid;
-
-  /**
-   * The human-readable name of the view mode.
-   *
-   * @var string
-   */
-  public $label;
-
-  /**
-   * The entity type this view mode is used for.
-   *
-   * This is not to be confused with EntityViewMode::entityType which is
-   * inherited from Entity::entityType and equals 'view_mode' for any view mode
-   * entity.
-   *
-   * @var string
-   */
-  public $targetEntityType;
-
-  /**
-   * Whether or not this view mode has custom settings by default.
-   *
-   * If FALSE, entities displayed in this view mode will reuse the 'default'
-   * display settings by default (e.g. right after the module exposing the view
-   * mode is enabled), but administrators can later use the Field UI to apply
-   * custom display settings specific to the view mode.
-   *
-   * @var bool
-   */
-  public $status = FALSE;
+class EntityViewMode extends EntityDisplayModeBase implements EntityViewModeInterface {
 
 }
diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php
index a29e967852e8b7549c2103459338ad3adb784a34..4337abdc327741b9048d8c79f1e6c3f8700b9b67 100644
--- a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php
+++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php
@@ -167,7 +167,7 @@ public function testFieldComponent() {
     $this->assertEqual($display->getComponent($field_name), $expected);
 
     // Check that the getFormatter() method returns the correct formatter plugin.
-    $formatter = $display->getFormatter($field_name);
+    $formatter = $display->getRenderer($field_name);
     $this->assertEqual($formatter->getPluginId(), $default_formatter);
     $this->assertEqual($formatter->getSettings(), $default_settings);
 
@@ -175,14 +175,14 @@ public function testFieldComponent() {
     // arbitrary property and reading it back.
     $random_value = $this->randomString();
     $formatter->randomValue = $random_value;
-    $formatter = $display->getFormatter($field_name);
+    $formatter = $display->getRenderer($field_name);
     $this->assertEqual($formatter->randomValue, $random_value);
 
     // Check that changing the definition creates a new formatter.
     $display->setComponent($field_name, array(
       'type' => 'field_test_multiple',
     ));
-    $formatter = $display->getFormatter($field_name);
+    $formatter = $display->getRenderer($field_name);
     $this->assertEqual($formatter->getPluginId(), 'field_test_multiple');
     $this->assertFalse(isset($formatter->randomValue));
 
@@ -194,7 +194,7 @@ public function testFieldComponent() {
     ));
     $options = $display->getComponent($field_name);
     $this->assertEqual($options['type'], 'unknown_formatter');
-    $formatter = $display->getFormatter($field_name);
+    $formatter = $display->getRenderer($field_name);
     $this->assertEqual($formatter->getPluginId(), $default_formatter);
   }
 
diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php
index e7cb19dc91d6acb727eec2d255e409ac72a5141e..a74c96699a7f162a14ac9e483ec45e11c81bd564 100644
--- a/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php
+++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php
@@ -88,7 +88,7 @@ public function testFieldComponent() {
     $this->assertEqual($form_display->getComponent($field_name), $expected);
 
     // Check that the getWidget() method returns the correct widget plugin.
-    $widget = $form_display->getWidget($field_name);
+    $widget = $form_display->getRenderer($field_name);
     $this->assertEqual($widget->getPluginId(), $default_widget);
     $this->assertEqual($widget->getSettings(), $default_settings);
 
@@ -96,14 +96,14 @@ public function testFieldComponent() {
     // arbitrary property and reading it back.
     $random_value = $this->randomString();
     $widget->randomValue = $random_value;
-    $widget = $form_display->getWidget($field_name);
+    $widget = $form_display->getRenderer($field_name);
     $this->assertEqual($widget->randomValue, $random_value);
 
     // Check that changing the definition creates a new widget.
     $form_display->setComponent($field_name, array(
       'type' => 'field_test_multiple',
     ));
-    $widget = $form_display->getWidget($field_name);
+    $widget = $form_display->getRenderer($field_name);
     $this->assertEqual($widget->getPluginId(), 'test_field_widget');
     $this->assertFalse(isset($widget->randomValue));
 
@@ -115,7 +115,7 @@ public function testFieldComponent() {
     ));
     $options = $form_display->getComponent($field_name);
     $this->assertEqual($options['type'], 'unknown_widget');
-    $widget = $form_display->getWidget($field_name);
+    $widget = $form_display->getRenderer($field_name);
     $this->assertEqual($widget->getPluginId(), $default_widget);
   }
 
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php
index da70748e43f856fed8f04ceb826f7e91e80be9c7..fd044dd8f78508a9703bb3b0020f0085f23b7def 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php
@@ -38,16 +38,32 @@ public function settingsForm(array $form, array &$form_state) {
       '#min' => 1,
       '#required' => TRUE,
     );
-
     $element['placeholder'] = array(
       '#type' => 'textfield',
       '#title' => t('Placeholder'),
       '#default_value' => $this->getSetting('placeholder'),
       '#description' => t('Text that will be shown inside the field until a value is entered. This hint is usually a sample value or a brief description of the expected format.'),
     );
+    return $element;
+  }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+
+    $summary[] = t('Autocomplete matching: @match_operator', array('@match_operator' => $this->getSetting('match_operator')));
+    $summary[] = t('Textfield size: !size', array('!size' => $this->getSetting('size')));
+    $placeholder = $this->getSetting('placeholder');
+    if (!empty($placeholder)) {
+      $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder));
+    }
+    else {
+      $summary[] = t('No placeholder');
+    }
 
-    return $element;
+    return $summary;
   }
 
   /**
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php
index 463a34765cb627f9347fd7d128521b58bbb93ef1..db74267c1c930bbb23295adb563e6ececc608e1b 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php
@@ -70,7 +70,6 @@ public function testFieldAdminHandler() {
       'fields[_add_new_field][label]' => 'Test label',
       'fields[_add_new_field][field_name]' => 'test',
       'fields[_add_new_field][type]' => 'entity_reference',
-      'fields[_add_new_field][widget_type]' => 'entity_reference_autocomplete',
     ), t('Save'));
 
     // Node should be selected by default.
diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php
index 1f4b2201813473446fc3b66ceeb70273ac44b3c7..02fd7046f5baa354f416ef5cc32eac5b73179ae8 100644
--- a/core/modules/field/field.api.php
+++ b/core/modules/field/field.api.php
@@ -32,8 +32,8 @@
  *   - label: The human readable name of the element.
  *   - description: A short description of the element contents.
  *   - weight: The default weight of the element.
- *   - visible: (optional) The default visibility of the element.  Only for
- *    'display' context. Defaults to TRUE.
+ *   - visible: (optional) The default visibility of the element. Defaults to
+ *     TRUE.
  *   - edit: (optional) String containing markup (normally a link) used as the
  *     element's 'edit' operation in the administration interface. Only for
  *     'form' context.
diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc
index 8ac39d7da0250b4b5f9b2e9f840fba4408824c92..ff28636a521cfe1915f9e1c2ba8a433df36b79c8 100644
--- a/core/modules/field/field.attach.inc
+++ b/core/modules/field/field.attach.inc
@@ -402,7 +402,7 @@ function _field_invoke_get_instances($entity_type, $bundle, $options) {
  */
 function _field_invoke_widget_target($form_display) {
   return function ($instance) use ($form_display) {
-    return $form_display->getWidget($instance['field_name']);
+    return $form_display->getRenderer($instance['field_name']);
   };
 }
 
@@ -1048,7 +1048,7 @@ function field_attach_prepare_view($entity_type, array $entities, array $display
   // the entity display.
   $target_function = function ($instance) use ($displays) {
     if (isset($displays[$instance['bundle']])) {
-      return $displays[$instance['bundle']]->getFormatter($instance['field_name']);
+      return $displays[$instance['bundle']]->getRenderer($instance['field_name']);
     }
   };
   $null = NULL;
@@ -1093,7 +1093,7 @@ function field_attach_view(EntityInterface $entity, EntityDisplay $display, $lan
   // For each instance, call the view() method on the formatter object handed
   // by the entity display.
   $target_function = function ($instance) use ($display) {
-    return $display->getFormatter($instance['field_name']);
+    return $display->getRenderer($instance['field_name']);
   };
   $null = NULL;
   $output = field_invoke_method('view', $target_function, $entity, $null, $null, $options);
diff --git a/core/modules/field/field.info.inc b/core/modules/field/field.info.inc
index 2a16bc111146167bf0f484e6a1e3db030f31e79f..932f6b2bb0253c5b5496c3e57927c5f7d6b146b5 100644
--- a/core/modules/field/field.info.inc
+++ b/core/modules/field/field.info.inc
@@ -31,6 +31,7 @@
  */
 function field_info_cache_clear() {
   drupal_static_reset('field_view_mode_settings');
+  drupal_static_reset('field_form_mode_settings');
   drupal_static_reset('field_available_languages');
 
   // @todo: Remove this when field_attach_*_bundle() bundle management
diff --git a/core/modules/field/field.install b/core/modules/field/field.install
index 7cfa1f6889949622f771d975e62914f2b467aa84..b4251699eff9c50920d44fc925b07e54206d8594 100644
--- a/core/modules/field/field.install
+++ b/core/modules/field/field.install
@@ -378,6 +378,39 @@ function field_update_8004() {
   ));
 }
 
+/**
+ * Removes the 'user_register_form' setting from field instances and populates
+ * the user.user.register form display.
+ */
+function field_update_8005() {
+  $uuid = new Uuid();
+
+  $user_default_form_display = Drupal::config('entity.form_display.user.user.default');
+  $user_register_config_data = array(
+    'id' => 'user.user.register',
+    'uuid' => $uuid->generate(),
+    'targetEntityType' => 'user',
+    'bundle' => 'user',
+    'mode' => 'register',
+    'content' => array(),
+  );
+  foreach (config_get_storage_names_with_prefix('field.instance') as $config_id) {
+    $instance_config = Drupal::config($config_id);
+    if ($instance_config->get('entity_type') == 'user' && $instance_config->get('settings.user_register_form')) {
+      list(, , $field_id) = explode('.', $instance_config->get('id'));
+      $user_register_config_data['content'][$field_id] = $user_default_form_display->get('content.' . $field_id);
+    }
+    $settings = $instance_config->get('settings');
+    unset($settings['user_register_form']);
+    $instance_config->set('settings', $settings)->save();
+  }
+
+  // Save the new 'register' form display.
+  Drupal::config('entity.form_display.user.user.register')
+    ->setData($user_register_config_data)
+    ->save();
+}
+
 /**
  * @} End of "addtogroup updates-7.x-to-8.x".
  * The next series of updates should start at 9000.
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 1694e2e8c2839880b9fe95dc23ccd6213e967784..19bf6ed4b576319fd3fe5734daac56e332828569 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -550,12 +550,48 @@ function field_bundle_settings($entity_type, $bundle, $settings = NULL) {
     $settings = variable_get('field_bundle_settings_' . $entity_type . '__' . $bundle, array());
     $settings += array(
       'view_modes' => array(),
+      'form_modes' => array(),
     );
 
     return $settings;
   }
 }
 
+/**
+ * Returns form mode settings in a given bundle.
+ *
+ * @param string $entity_type
+ *   The type of entity; e.g. 'node' or 'user'.
+ * @param string $bundle
+ *   The bundle name to return form mode settings for.
+ *
+ * @return
+ *   An array keyed by form mode, with the following key/value pairs:
+ *   - status: Boolean specifying whether the form mode uses a dedicated set of
+ *     display options (TRUE), or the 'default' options (FALSE). Defaults to
+ *     FALSE.
+ */
+function field_form_mode_settings($entity_type, $bundle) {
+  $cache = &drupal_static(__FUNCTION__, array());
+
+  if (!isset($cache[$entity_type][$bundle])) {
+    $bundle_settings = field_bundle_settings($entity_type, $bundle);
+    $settings = $bundle_settings['form_modes'];
+    // Include form modes for which nothing has been stored yet, but whose
+    // definition in hook_entity_info_alter() specify they should use custom
+    // settings by default.
+    $form_modes = entity_get_form_modes($entity_type);
+    foreach ($form_modes as $form_mode => $form_mode_info) {
+      if (!isset($settings[$form_mode]['status']) && $form_mode_info['status']) {
+        $settings[$form_mode]['status'] = TRUE;
+      }
+    }
+    $cache[$entity_type][$bundle] = $settings;
+  }
+
+  return $cache[$entity_type][$bundle];
+}
+
 /**
  * Returns view mode settings in a given bundle.
  *
@@ -744,7 +780,7 @@ function field_view_field(EntityInterface $entity, $field_name, $display_options
   // Get the formatter object.
   if (is_string($display_options)) {
     $view_mode = $display_options;
-    $formatter = entity_get_render_display($entity, $view_mode)->getFormatter($field_name);
+    $formatter = entity_get_render_display($entity, $view_mode)->getRenderer($field_name);
   }
   else {
     $view_mode = '_custom';
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
index 7c2e35afece7b5350bb3de1b183b6dd0dfa1a0bc..39deee9179e2273608678539a3d7f2443db87480 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
@@ -160,4 +160,19 @@ public function getOptions($field_type = NULL) {
     return $this->formatterOptions;
   }
 
+  /**
+   * Returns the default settings of a field formatter.
+   *
+   * @param string $type
+   *   A field formatter type name.
+   *
+   * @return array
+   *   The formatter type's default settings, as provided by the plugin
+   *   definition, or an empty array if type or settings are undefined.
+   */
+  public function getDefaultSettings($type) {
+    $info = $this->getDefinition($type);
+    return isset($info['settings']) ? $info['settings'] : array();
+  }
+
 }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
index 7f9017aa25af36d36091e91719fd6d8d5a7d8152..654cbbe1249b198769a6192efa05f66dc9fca55f 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
@@ -392,6 +392,13 @@ public function settingsForm(array $form, array &$form_state) {
     return array();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    return array();
+  }
+
   /**
    * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::errorElement().
    */
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php
index d4a7b8c14cd01624d740a3d10764ea6b87b330dd..fbc939c0cdb18cbfa5b438fa2f3ff373ea7590dd 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php
@@ -38,6 +38,18 @@ interface WidgetInterface extends WidgetBaseInterface {
    */
   public function settingsForm(array $form, array &$form_state);
 
+  /**
+   * Returns a short summary for the current widget settings.
+   *
+   * If an empty result is returned, the widget is assumed to have no
+   * configurable settings, and no UI will be provided to display a settings
+   * form.
+   *
+   * @return array
+   *   A short summary of the widget settings.
+   */
+  public function settingsSummary();
+
   /**
    * Returns the form for a single field widget.
    *
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php
index 6f22fa8dbf64e2cda96a2f15980e12c103b01a4a..b8213caf649ce030fdb798afc1c3ec2df852f5e8 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php
@@ -161,4 +161,19 @@ public function getOptions($field_type = NULL) {
     return $this->widgetOptions;
   }
 
+  /**
+   * Returns the default settings of a field widget.
+   *
+   * @param string $type
+   *   A field widget type name.
+   *
+   * @return array
+   *   The widget type's default settings, as provided by the plugin
+   *   definition, or an empty array if type or settings are undefined.
+   */
+  public function getDefaultSettings($type) {
+    $info = $this->getDefinition($type);
+    return isset($info['settings']) ? $info['settings'] : array();
+  }
+
 }
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
index 0c3521f63bd7b85a3528157ad74d1bd092c3c954..012ee4f3722315bba5b704025d38969fff359bbe 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
@@ -24,10 +24,6 @@ function testFieldInfo() {
     // Test that field_test module's fields, widgets, and formatters show up.
 
     $field_test_info = field_test_field_info();
-    // We need to account for the existence of user_field_info_alter().
-    foreach (array_keys($field_test_info) as $name) {
-      $field_test_info[$name]['instance_settings']['user_register_form'] = FALSE;
-    }
     $info = field_info_field_types();
     foreach ($field_test_info as $t_key => $field_type) {
       foreach ($field_type as $key => $val) {
@@ -165,12 +161,10 @@ function testInstancePrepare() {
     $instance->save();
 
     // Simulate a stored instance definition missing various settings (e.g. a
-    // third-party module adding instance or widget settings has been enabled,
-    // but existing instances do not know the new settings).
+    // third-party module adding instance settings has been enabled, but
+    // existing instances do not know the new settings).
     \Drupal::config('field.instance.' . $instance->id())
       ->set('settings', array())
-      ->set('widget.type', 'unavailable_widget')
-      ->set('widget.settings', array())
       ->save();
     field_info_cache_clear();
 
@@ -284,10 +278,6 @@ function testFieldMap() {
    */
   function testSettingsInfo() {
     $info = field_test_field_info();
-    // We need to account for the existence of user_field_info_alter().
-    foreach (array_keys($info) as $name) {
-      $info[$name]['instance_settings']['user_register_form'] = FALSE;
-    }
     foreach ($info as $type => $data) {
       $this->assertIdentical(field_info_field_settings($type), $data['settings'], format_string("field_info_field_settings returns %type's field settings", array('%type' => $type)));
       $this->assertIdentical(field_info_instance_settings($type), $data['instance_settings'], format_string("field_info_field_settings returns %type's field instance settings", array('%type' => $type)));
diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module
index 5ac9e9d6ca8b91a1481b8763902957060aaf0595..800f4d40feb16f5e2a95ebf66651760f69fe95d2 100644
--- a/core/modules/field/tests/modules/field_test/field_test.module
+++ b/core/modules/field/tests/modules/field_test/field_test.module
@@ -192,6 +192,25 @@ function field_test_query_efq_metadata_test_alter(&$query) {
   $efq_test_metadata = $query->getMetadata('foo');
 }
 
+/**
+ * Implements hook_field_widget_settings_form_alter().
+ */
+function field_test_field_widget_settings_form_alter(&$element, &$form_state, $context) {
+  $element['field_test_widget_settings_form_alter'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Widget settings form alter'),
+    '#default_value' => $context['widget']->getSetting('field_test_widget_settings_form_alter'),
+  );
+}
+
+/**
+ * Implements hook_field_widget_settings_summary_alter().
+ */
+function field_test_field_widget_settings_summary_alter(&$summary, $context) {
+  $summary[] = 'field_test_field_widget_settings_summary_alter';
+  return $summary;
+}
+
 /**
  * Implements hook_field_formatter_settings_form_alter().
  */
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidget.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidget.php
index 21445d42420633fefd7e548ad5feb1c5e9f3a842..c6e850c948778e4646c89207faaf57b4d90ad9ae 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidget.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidget.php
@@ -31,7 +31,7 @@
 class TestFieldWidget extends WidgetBase {
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::settingsForm().
+   * {@inheritdoc}
    */
   public function settingsForm(array $form, array &$form_state) {
     $element['test_widget_setting'] = array(
@@ -45,7 +45,16 @@ public function settingsForm(array $form, array &$form_state) {
   }
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement().
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+    $summary[] = t('@setting: @value', array('@setting' => 'test_widget_setting', '@value' => $this->getSetting('test_widget_setting')));
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
    */
   public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $element += array(
@@ -56,7 +65,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
   }
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::errorElement().
+   * {@inheritdoc}
    */
   public function errorElement(array $element, ConstraintViolationInterface $error, array $form, array &$form_state) {
     return $element['value'];
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php
index d65f14feeb275f5fc19b84a804b8b201ac116cea..1fb1f38020a11ba89223bb27b8930b7e12127f74 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php
@@ -32,21 +32,30 @@
 class TestFieldWidgetMultiple extends WidgetBase {
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::settingsForm().
+   * {@inheritdoc}
    */
   public function settingsForm(array $form, array &$form_state) {
-    $element['test_field_widget_multiple'] = array(
+    $element['test_widget_setting_multiple'] = array(
       '#type' => 'textfield',
       '#title' => t('Field test field widget setting'),
       '#description' => t('A dummy form element to simulate field widget setting.'),
-      '#default_value' => $this->getSetting('test_widget_setting'),
+      '#default_value' => $this->getSetting('test_widget_setting_multiple'),
       '#required' => FALSE,
     );
     return $element;
   }
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement().
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+    $summary[] = t('@setting: @value', array('@setting' => 'test_widget_setting_multiple', '@value' => $this->getSetting('test_widget_setting_multiple')));
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
    */
   public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $values = array();
@@ -62,7 +71,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
   }
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::errorElement().
+   * {@inheritdoc}
    */
   public function errorElement(array $element, ConstraintViolationInterface $error, array $form, array &$form_state) {
     return $element;
diff --git a/core/modules/field_ui/css/field_ui.admin.css b/core/modules/field_ui/css/field_ui.admin.css
index cf59695cee98e900113f54506ae4be83ed558862..0eb5d6b8e33d53cc2f54d015e3ee873e4e3795de 100644
--- a/core/modules/field_ui/css/field_ui.admin.css
+++ b/core/modules/field_ui/css/field_ui.admin.css
@@ -38,31 +38,31 @@
   white-space: nowrap;
 }
 
-/* 'Manage display' overview */
-.field-ui-overview .field-formatter-summary-cell {
+/* 'Manage form display' and 'Manage display' overview */
+.field-ui-overview .field-plugin-summary-cell {
   line-height: 1em;
 }
-.field-ui-overview .field-formatter-summary {
+.field-ui-overview .field-plugin-summary {
   float: left;
   font-size: .9em;
 }
-.field-ui-overview .field-formatter-summary-cell .warning {
+.field-ui-overview .field-plugin-summary-cell .warning {
   display: block;
   float: left;
   margin-right: .5em;
 }
-.field-ui-overview .field-formatter-settings-edit-wrapper {
+.field-ui-overview .field-plugin-settings-edit-wrapper {
   float: right;
 }
-.field-ui-overview .field-formatter-settings-edit {
+.field-ui-overview .field-plugin-settings-edit {
   float: right;
 }
-.field-ui-overview .field-formatter-settings-editing td {
+.field-ui-overview .field-plugin-settings-editing td {
   vertical-align: top;
 }
-.field-ui-overview .field-formatter-settings-editing .field-formatter-type {
+.field-ui-overview .field-plugin-settings-editing .field-plugin-type {
   display: none;
 }
-.field-ui-overview .field-formatter-settings-edit-form .formatter-name{
+.field-ui-overview .field-plugin-settings-edit-form .plugin-name {
   font-weight: bold;
 }
diff --git a/core/modules/field_ui/field_ui.api.php b/core/modules/field_ui/field_ui.api.php
index bece316b209b123683f38a9f60f690f31d4a03ac..7bcfff012000e3595e9caf5fcde08f0445eb17de 100644
--- a/core/modules/field_ui/field_ui.api.php
+++ b/core/modules/field_ui/field_ui.api.php
@@ -38,6 +38,34 @@ function hook_field_formatter_settings_form_alter(&$element, &$form_state, $cont
   }
 }
 
+/**
+ * Alters the widget settings form.
+ *
+ * @param array $element
+ *   Form array.
+ * @param array $form_state
+ *   The form state of the (entire) configuration form.
+ * @param array $context
+ *   An associative array with the following elements:
+ *   - formatter: The formatter object.
+ *   - field: The field structure being configured.
+ *   - instance: The instance structure being configured.
+ *   - form_mode: The form mode being configured.
+ *   - form: The (entire) configuration form array.
+ *
+ * @see \Drupal\field_ui\FormDisplayOverView.
+ */
+function hook_field_widget_settings_form_alter(&$element, &$form_state, $context) {
+  // Add a 'mysetting' checkbox to the settings form for 'foo_field' fields.
+  if ($context['field']['type'] == 'foo_field') {
+    $element['mysetting'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('My setting'),
+      '#default_value' => $context['formatter']->getSetting('mysetting'),
+    );
+  }
+}
+
 /**
  * Alters the field formatter settings summary.
  *
@@ -62,6 +90,30 @@ function hook_field_formatter_settings_summary_alter(&$summary, $context) {
   }
 }
 
+/**
+ * Alters the field widget settings summary.
+ *
+ * @param array $summary
+ *   The summary.
+ * @param array $context
+ *   An associative array with the following elements:
+ *   - widget: The widget object.
+ *   - field: The field structure being configured.
+ *   - instance: The instance structure being configured.
+ *   - form_mode: The form mode being configured.
+ *
+ * @see \Drupal\field_ui\FormDisplayOverView.
+ */
+function hook_field_widget_settings_summary_alter(&$summary, $context) {
+  // Append a message to the summary when an instance of foo_field has
+  // mysetting set to TRUE for the current view mode.
+  if ($context['field']['type'] == 'foo_field') {
+    if ($context['widget']->getSetting('mysetting')) {
+      $summary[] = t('My setting enabled.');
+    }
+  }
+}
+
 /**
  * @} End of "addtogroup field_types".
  */
diff --git a/core/modules/field_ui/field_ui.js b/core/modules/field_ui/field_ui.js
index 3000cd10903aef62f516e5c8bd02359f3b71b821..2955bf9b11f3fe55ab3545b7a7b4df8fce1b3206 100644
--- a/core/modules/field_ui/field_ui.js
+++ b/core/modules/field_ui/field_ui.js
@@ -7,108 +7,6 @@
 
 "use strict";
 
-Drupal.behaviors.fieldUIFieldOverview = {
-  attach: function (context, settings) {
-    $(context).find('table#field-overview').once('field-overview', function () {
-      Drupal.fieldUIFieldOverview.attachUpdateSelects(this, settings);
-    });
-  }
-};
-
-Drupal.fieldUIFieldOverview = {
-  /**
-   * Implements dependent select dropdowns on the 'Manage fields' screen.
-   */
-  attachUpdateSelects: function(table, settings) {
-    var widgetTypes = settings.fieldWidgetTypes;
-    var fields = settings.fields;
-    var $table = $(table);
-
-    // Store the default text of widget selects.
-    $table.find('.widget-type-select').each(function () {
-      this.initialValue = this.options[0].text;
-    });
-
-    // 'Field type' select updates its 'Widget' select.
-    $table.find('.field-type-select').each(function () {
-      var $this = $(this);
-      this.targetSelect = $this.closest('tr').find('.widget-type-select');
-
-      $this.bind('change keyup', function () {
-        var selectedFieldType = this.options[this.selectedIndex].value;
-        var options = (selectedFieldType in widgetTypes ? widgetTypes[selectedFieldType] : []);
-        this.targetSelect.fieldUIPopulateOptions(options);
-      });
-
-      // Trigger change on initial pageload to get the right widget options
-      // when field type comes pre-selected (on failed validation).
-      $this.trigger('change', false);
-    });
-
-    // 'Existing field' select updates its 'Widget' select and 'Label' textfield.
-    $table.find('.field-select').each(function () {
-      var $this = $(this);
-      var $tr = $this.closest('tr');
-      this.targetSelect = $tr.find('.widget-type-select');
-      this.targetTextfield = $tr.find('.label-textfield');
-      this.targetTextfield
-        .data('field_ui_edited', false)
-        .bind('keyup', function (e) {
-          $(this).data('field_ui_edited', $(this).val() !== '');
-        });
-
-      $this.bind('change keyup', function (e, updateText) {
-        updateText = (typeof updateText === 'undefined' ? true : updateText);
-        var selectedField = this.options[this.selectedIndex].value;
-        var selectedFieldType = (selectedField in fields ? fields[selectedField].type : null);
-        var selectedFieldWidget = (selectedField in fields ? fields[selectedField].widget : null);
-        var options = (selectedFieldType && (selectedFieldType in widgetTypes) ? widgetTypes[selectedFieldType] : []);
-        this.targetSelect.fieldUIPopulateOptions(options, selectedFieldWidget);
-
-        // Only overwrite the "Label" input if it has not been manually
-        // changed, or if it is empty.
-        if (updateText && !this.targetTextfield.data('field_ui_edited')) {
-          this.targetTextfield.val(selectedField in fields ? fields[selectedField].label : '');
-        }
-      });
-
-      // Trigger change on initial pageload to get the right widget options
-      // and label when field type comes pre-selected (on failed validation).
-      $this.trigger('change', false);
-    });
-  }
-};
-
-/**
- * Populates options in a select input.
- */
-jQuery.fn.fieldUIPopulateOptions = function (options, selected) {
-  return this.each(function () {
-    var disabled = false;
-    if (options.length === 0) {
-      options = [this.initialValue];
-      disabled = true;
-    }
-
-    // If possible, keep the same widget selected when changing field type.
-    // This is based on textual value, since the internal value might be
-    // different (options_buttons vs. node_reference_buttons).
-    var previousSelectedText = this.options[this.selectedIndex].text;
-
-    var html = '';
-    for (var value in options) {
-      if (options.hasOwnProperty(value)) {
-        // Figure out which value should be selected. The 'selected' param
-        // takes precedence.
-        var is_selected = ((typeof selected !== 'undefined' && value === selected) || (typeof selected === 'undefined' && options[value] === previousSelectedText));
-        html += '<option value="' + value + '"' + (is_selected ? ' selected="selected"' : '') + '>' + options[value] + '</option>';
-      }
-    }
-
-    $(this).html(html).prop('disabled', disabled);
-  });
-};
-
 Drupal.behaviors.fieldUIDisplayOverview = {
   attach: function (context, settings) {
     $(context).find('table#field-display-overview').once('field-display-overview', function() {
@@ -290,9 +188,9 @@ Drupal.fieldUIDisplayOverview.field = function (row, data) {
   this.region = data.region;
   this.tableDrag = data.tableDrag;
 
-  // Attach change listener to the 'formatter type' select.
-  this.$formatSelect = $(row).find('select.field-formatter-type');
-  this.$formatSelect.change(Drupal.fieldUIOverview.onChange);
+  // Attach change listener to the 'plugin type' select.
+  this.$pluginSelect = $(row).find('select.field-plugin-type');
+  this.$pluginSelect.change(Drupal.fieldUIOverview.onChange);
 
   return this;
 };
@@ -302,7 +200,7 @@ Drupal.fieldUIDisplayOverview.field.prototype = {
    * Returns the region corresponding to the current form values of the row.
    */
   getRegion: function () {
-    return (this.$formatSelect.val() === 'hidden') ? 'hidden' : 'content';
+    return (this.$pluginSelect.val() === 'hidden') ? 'hidden' : 'content';
   },
 
   /**
@@ -326,7 +224,7 @@ Drupal.fieldUIDisplayOverview.field.prototype = {
 
     // When triggered by a row drag, the 'format' select needs to be adjusted
     // to the new region.
-    var currentValue = this.$formatSelect.val();
+    var currentValue = this.$pluginSelect.val();
     var value;
     // @TODO Check if this couldn't just be like
     // if (region !== 'hidden') {
@@ -334,7 +232,7 @@ Drupal.fieldUIDisplayOverview.field.prototype = {
       if (currentValue === 'hidden') {
         // Restore the formatter back to the default formatter. Pseudo-fields do
         // not have default formatters, we just return to 'visible' for those.
-        value = (typeof this.defaultFormatter !== 'undefined') ? this.defaultFormatter : this.$formatSelect.find('option').val();
+        value = (typeof this.defaultPlugin !== 'undefined') ? this.defaultPlugin : this.$pluginSelect.find('option').val();
       }
     }
     else {
@@ -342,11 +240,11 @@ Drupal.fieldUIDisplayOverview.field.prototype = {
     }
 
     if (typeof value !== 'undefined') {
-      this.$formatSelect.val(value);
+      this.$pluginSelect.val(value);
     }
 
     var refreshRows = {};
-    refreshRows[this.name] = this.$formatSelect.get(0);
+    refreshRows[this.name] = this.$pluginSelect.get(0);
 
     return refreshRows;
   }
diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module
index 9c695975ef68bfeb7b510a0111bf8d2ddc00b969..2040df277c95a8077839663192208448905a4f9f 100644
--- a/core/modules/field_ui/field_ui.module
+++ b/core/modules/field_ui/field_ui.module
@@ -94,11 +94,6 @@ function field_ui_menu() {
         'type' => MENU_LOCAL_TASK,
         'route_name' => "field_ui.field_edit.$entity_type",
       );
-      $items["$path/fields/%/widget-type"] = array(
-        'title' => 'Widget type',
-        'type' => MENU_LOCAL_TASK,
-        'route_name' => "field_ui.widget_type.$entity_type",
-      );
       $items["$path/fields/%/delete"] = array(
         'title' => 'Delete',
         'type' => MENU_VISIBLE_IN_BREADCRUMB,
@@ -106,26 +101,47 @@ function field_ui_menu() {
         'weight' => 10,
       );
 
+      // 'Manage form display' tab.
+      $items["$path/form-display"] = array(
+        'title' => 'Manage form display',
+        'type' => MENU_LOCAL_TASK,
+        'route_name' => "field_ui.form_display_overview.$entity_type",
+        'weight' => 2,
+      );
+
       // 'Manage display' tab.
       $items["$path/display"] = array(
         'title' => 'Manage display',
         'type' => MENU_LOCAL_TASK,
         'route_name' => "field_ui.display_overview.$entity_type",
-        'weight' => 2,
+        'weight' => 3,
       );
 
-      // View modes secondary tabs.
+      // View and form modes secondary tabs.
       // The same base $path for the menu item (with a placeholder) can be
       // used for all bundles of a given entity type; but depending on
       // administrator settings, each bundle has a different set of view
       // modes available for customisation. So we define menu items for all
       // view modes, and use a route requirement to determine which ones are
       // actually visible for a given bundle.
+      $items["$default_path/form-display/default"] = array(
+        'title' => t('Default'),
+        'type' => MENU_DEFAULT_LOCAL_TASK,
+      );
       $items["$default_path/display/default"] = array(
         'title' => t('Default'),
         'type' => MENU_DEFAULT_LOCAL_TASK,
       );
       $weight = 0;
+      foreach (entity_get_form_modes($entity_type) as $form_mode => $form_mode_info) {
+        $items["$path/form-display/$form_mode"] = array(
+          'title' => $form_mode_info['label'],
+          'type' => MENU_LOCAL_TASK,
+          'weight' => $weight++,
+          'route_name' => "field_ui.form_display_overview.$entity_type.$form_mode",
+        );
+      }
+      $weight = 0;
       foreach (entity_get_view_modes($entity_type) as $view_mode => $view_mode_info) {
         $items["$path/display/$view_mode"] = array(
           'title' => $view_mode_info['label'],
@@ -153,6 +169,9 @@ function field_ui_permission() {
         'title' => t('%entity_label: Administer fields', array('%entity_label' => $entity_info['label'])),
         'restrict access' => TRUE,
       );
+      $permissions['administer ' . $entity_type . ' form display'] = array(
+        'title' => t('%entity_label: Administer form display', array('%entity_label' => $entity_info['label']))
+      );
       $permissions['administer ' . $entity_type . ' display'] = array(
         'title' => t('%entity_label: Administer display', array('%entity_label' => $entity_info['label']))
       );
diff --git a/core/modules/field_ui/field_ui.services.yml b/core/modules/field_ui/field_ui.services.yml
index cfc1214fe1bd26c3a06f16b7222fa493b7787b1e..cec753a3dd50a8f6beae62a663b2f4896af9a00d 100644
--- a/core/modules/field_ui/field_ui.services.yml
+++ b/core/modules/field_ui/field_ui.services.yml
@@ -8,3 +8,7 @@ services:
     class: Drupal\field_ui\Access\ViewModeAccessCheck
     tags:
      - { name: access_check }
+  access_check.field_ui.form_mode:
+    class: Drupal\field_ui\Access\FormModeAccessCheck
+    tags:
+     - { name: access_check }
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Access/FormModeAccessCheck.php b/core/modules/field_ui/lib/Drupal/field_ui/Access/FormModeAccessCheck.php
new file mode 100644
index 0000000000000000000000000000000000000000..dfbefe77797ede95f50e62f02002be5ad03d4ddf
--- /dev/null
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Access/FormModeAccessCheck.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field_ui\Access\FormModeAccessCheck.
+ */
+
+namespace Drupal\field_ui\Access;
+
+use Drupal\Core\Access\AccessCheckInterface;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Allows access to routes to be controlled by an '_access' boolean parameter.
+ */
+class FormModeAccessCheck implements AccessCheckInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function applies(Route $route) {
+    return array_key_exists('_field_ui_form_mode_access', $route->getRequirements());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access(Route $route, Request $request) {
+    if ($entity_type = $request->attributes->get('entity_type')) {
+      $bundle = $request->attributes->get('bundle');
+      $form_mode = $request->attributes->get('mode');
+
+      $form_mode_settings = field_form_mode_settings($entity_type, $bundle);
+      $visibility = ($form_mode == 'default') || !empty($form_mode_settings[$form_mode]['status']);
+      if ($visibility) {
+        $permission = $route->getRequirement('_field_ui_form_mode_access');
+        return user_access($permission);
+      }
+    }
+  }
+
+}
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Access/ViewModeAccessCheck.php b/core/modules/field_ui/lib/Drupal/field_ui/Access/ViewModeAccessCheck.php
index 1ddb8b5922d34f2da702785bc060bb3e6f0d5225..f82ede6895b69457cb4b331acd81bc518179da55 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Access/ViewModeAccessCheck.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Access/ViewModeAccessCheck.php
@@ -29,7 +29,7 @@ public function applies(Route $route) {
   public function access(Route $route, Request $request) {
     if ($entity_type = $request->attributes->get('entity_type')) {
       $bundle = $request->attributes->get('bundle');
-      $view_mode = $request->attributes->get('view_mode');
+      $view_mode = $request->attributes->get('mode');
 
       $view_mode_settings = field_view_mode_settings($entity_type, $bundle);
       $visibility = ($view_mode == 'default') || !empty($view_mode_settings[$view_mode]['status']);
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
index bb09eab435747176209b54403c5ca778fb9d552d..841c056463e61924d118ea03bb80fb5c4f409369 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
@@ -7,36 +7,16 @@
 
 namespace Drupal\field_ui;
 
-use Drupal\field_ui\OverviewBase;
-use Drupal\Core\Entity\EntityManager;
-use Drupal\field\Plugin\Type\Formatter\FormatterPluginManager;
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Controller\ControllerInterface;
+use Drupal\entity\EntityDisplayBaseInterface;
+use Drupal\field\FieldInstanceInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Field UI display overview form.
  */
-class DisplayOverview extends OverviewBase {
-
-  /**
-   * The formatter plugin manager.
-   *
-   * @var \Drupal\field\Plugin\Type\Formatter\FormatterPluginManager
-   */
-  protected $formatterManager;
-
-  /**
-   * Constructs a new DisplayOverview.
-   *
-   * @param \Drupal\Core\Entity\EntityManager $entity_manager
-   *   The entity manager.
-   * @param \Drupal\field\Plugin\Type\Formatter\FormatterPluginManager $formatter_manager
-   *   The formatter plugin manager.
-   */
-  public function __construct(EntityManager $entity_manager, FormatterPluginManager $formatter_manager) {
-    parent::__construct($entity_manager);
-
-    $this->formatterManager = $formatter_manager;
-  }
+class DisplayOverview extends DisplayOverviewBase implements ControllerInterface {
 
   /**
    * {@inheritdoc}
@@ -49,584 +29,188 @@ public static function create(ContainerInterface $container) {
   }
 
   /**
-   * Implements Drupal\field_ui\OverviewBase::getRegions().
-   */
-  public function getRegions() {
-    return array(
-      'content' => array(
-        'title' => t('Content'),
-        'invisible' => TRUE,
-        'message' => t('No field is displayed.')
-      ),
-      'hidden' => array(
-        'title' => t('Disabled'),
-        'message' => t('No field is hidden.')
-      ),
-    );
-  }
-
-  /**
-   * Implements \Drupal\Core\Form\FormInterface::getFormID().
+   * {@inheritdoc}
    */
   public function getFormID() {
     return 'field_ui_display_overview_form';
   }
 
   /**
-   * Implements \Drupal\Core\Form\FormInterface::buildForm().
+   * {@inheritdoc}
    */
-  public function buildForm(array $form, array &$form_state, $entity_type = NULL, $bundle = NULL, $view_mode = NULL) {
-    parent::buildForm($form, $form_state, $entity_type, $bundle);
-
-    $this->mode = (isset($view_mode) ? $view_mode : 'default');
-    // Gather type information.
-    $instances = field_info_instances($this->entity_type, $this->bundle);
-    $field_types = field_info_field_types();
-    $extra_fields = field_info_extra_fields($this->entity_type, $this->bundle, 'display');
-    $entity_display = entity_get_display($this->entity_type, $this->bundle, $this->mode);
-
-    $form_state += array(
-      'formatter_settings_edit' => NULL,
-    );
-
-    $form += array(
-      '#entity_type' => $this->entity_type,
-      '#bundle' => $this->bundle,
-      '#view_mode' => $this->mode,
-      '#fields' => array_keys($instances),
-      '#extra' => array_keys($extra_fields),
-    );
-
-    if (empty($instances) && empty($extra_fields)) {
-      drupal_set_message(t('There are no fields yet added. You can add new fields on the <a href="@link">Manage fields</a> page.', array('@link' => url($this->adminPath . '/fields'))), 'warning');
-      return $form;
-    }
-
-    $table = array(
-      '#type' => 'field_ui_table',
-      '#pre_render' => array(array($this, 'tablePreRender')),
-      '#tree' => TRUE,
-      '#header' => array(
-        t('Field'),
-        t('Weight'),
-        t('Parent'),
-        t('Label'),
-        array('data' => t('Format'), 'colspan' => 3),
+  protected function buildFieldRow($field_id, FieldInstanceInterface $instance, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) {
+    $field_row = parent::buildFieldRow($field_id, $instance, $entity_display, $form, $form_state);
+    $display_options = $entity_display->getComponent($field_id);
+
+    // Insert the label column.
+    $label = array(
+      'label' => array(
+        '#type' => 'select',
+        '#title' => t('Label display for @title', array('@title' => $instance['label'])),
+        '#title_display' => 'invisible',
+        '#options' => $this->getFieldLabelOptions(),
+        '#default_value' => $display_options ? $display_options['label'] : 'above',
       ),
-      '#regions' => $this->getRegions(),
-      '#parent_options' => drupal_map_assoc(array_keys($this->getRegions())),
-      '#attributes' => array(
-        'class' => array('field-ui-overview'),
-        'id' => 'field-display-overview',
-      ),
-      // Add Ajax wrapper.
-      '#prefix' => '<div id="field-display-overview-wrapper">',
-      '#suffix' => '</div>',
-    );
-
-    $field_label_options = array(
-      'above' => t('Above'),
-      'inline' => t('Inline'),
-      'hidden' => '<' . t('Hidden') . '>',
     );
-    $extra_visibility_options = array(
-      'visible' => t('Visible'),
-      'hidden' => t('Hidden'),
-    );
-
-    // Field rows.
-    foreach ($instances as $name => $instance) {
-      $field = field_info_field($name);
-      $display_options = $entity_display->getComponent($name);
-
-      $table[$name] = array(
-        '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
-        '#row_type' => 'field',
-        '#region_callback' => array($this, 'getRowRegion'),
-        '#js_settings' => array(
-          'rowHandler' => 'field',
-          'defaultFormatter' => $field_types[$field['type']]['default_formatter'],
-        ),
-        'human_name' => array(
-          '#markup' => check_plain($instance['label']),
-        ),
-        'weight' => array(
-          '#type' => 'textfield',
-          '#title' => t('Weight for @title', array('@title' => $instance['label'])),
-          '#title_display' => 'invisible',
-          '#default_value' => $display_options ? $display_options['weight'] : '0',
-          '#size' => 3,
-          '#attributes' => array('class' => array('field-weight')),
-        ),
-        'parent_wrapper' => array(
-          'parent' => array(
-            '#type' => 'select',
-            '#title' => t('Label display for @title', array('@title' => $instance['label'])),
-            '#title_display' => 'invisible',
-            '#options' => $table['#parent_options'],
-            '#empty_value' => '',
-            '#attributes' => array('class' => array('field-parent')),
-            '#parents' => array('fields', $name, 'parent'),
-          ),
-          'hidden_name' => array(
-            '#type' => 'hidden',
-            '#default_value' => $name,
-            '#attributes' => array('class' => array('field-name')),
-          ),
-        ),
-        'label' => array(
-          '#type' => 'select',
-          '#title' => t('Label display for @title', array('@title' => $instance['label'])),
-          '#title_display' => 'invisible',
-          '#options' => $field_label_options,
-          '#default_value' => $display_options ? $display_options['label'] : 'above',
-        ),
-      );
-
-      $formatter_options = $this->formatterManager->getOptions($field['type']);
-      $formatter_options['hidden'] = '<' . t('Hidden') . '>';
-      $table[$name]['format'] = array(
-        'type' => array(
-          '#type' => 'select',
-          '#title' => t('Formatter for @title', array('@title' => $instance['label'])),
-          '#title_display' => 'invisible',
-          '#options' => $formatter_options,
-          '#default_value' => $display_options ? $display_options['type'] : 'hidden',
-          '#parents' => array('fields', $name, 'type'),
-          '#attributes' => array('class' => array('field-formatter-type')),
-        ),
-        'settings_edit_form' => array(),
-      );
-
-      // Check the currently selected formatter, and merge persisted values for
-      // formatter settings.
-      if (isset($form_state['values']['fields'][$name]['type'])) {
-        $display_options['type'] = $form_state['values']['fields'][$name]['type'];
-      }
-      if (isset($form_state['formatter_settings'][$name])) {
-        $display_options['settings'] = $form_state['formatter_settings'][$name];
-      }
-
-      // Get the corresponding formatter object.
-      if ($display_options && $display_options['type'] != 'hidden') {
-        $formatter = $this->formatterManager->getInstance(array(
-          'field_definition' => $instance,
-          'view_mode' => $this->mode,
-          'configuration' => $display_options
-        ));
-      }
-      else {
-        $formatter = NULL;
-      }
 
-      // Base button element for the various formatter settings actions.
-      $base_button = array(
-        '#submit' => array(array($this, 'multistepSubmit')),
-        '#ajax' => array(
-          'callback' => array($this, 'multistepAjax'),
-          'wrapper' => 'field-display-overview-wrapper',
-          'effect' => 'fade',
-        ),
-        '#field_name' => $name,
-      );
+    $label_position = array_search('plugin', array_keys($field_row));
+    $field_row = array_slice($field_row, 0, $label_position, TRUE) + $label + array_slice($field_row, $label_position, count($field_row) - 1, TRUE);
 
-      if ($form_state['formatter_settings_edit'] == $name) {
-        // We are currently editing this field's formatter settings. Display the
-        // settings form and submit buttons.
-        $table[$name]['format']['settings_edit_form'] = array();
-
-        if ($formatter) {
-          $formatter_type_info = $formatter->getPluginDefinition();
-
-          // Generate the settings form and allow other modules to alter it.
-          $settings_form = $formatter->settingsForm($form, $form_state);
-          $context = array(
-            'formatter' => $formatter,
-            'field' => $field,
-            'instance' => $instance,
-            'view_mode' => $this->mode,
-            'form' => $form,
-          );
-          drupal_alter('field_formatter_settings_form', $settings_form, $form_state, $context);
-
-          if ($settings_form) {
-            $table[$name]['format']['#cell_attributes'] = array('colspan' => 3);
-            $table[$name]['format']['settings_edit_form'] = array(
-              '#type' => 'container',
-              '#attributes' => array('class' => array('field-formatter-settings-edit-form')),
-              '#parents' => array('fields', $name, 'settings_edit_form'),
-              'label' => array(
-                '#markup' => t('Format settings:') . ' <span class="formatter-name">' . $formatter_type_info['label'] . '</span>',
-              ),
-              'settings' => $settings_form,
-              'actions' => array(
-                '#type' => 'actions',
-                'save_settings' => $base_button + array(
-                  '#type' => 'submit',
-                  '#name' => $name . '_formatter_settings_update',
-                  '#value' => t('Update'),
-                  '#op' => 'update',
-                ),
-                'cancel_settings' => $base_button + array(
-                  '#type' => 'submit',
-                  '#name' => $name . '_formatter_settings_cancel',
-                  '#value' => t('Cancel'),
-                  '#op' => 'cancel',
-                  // Do not check errors for the 'Cancel' button, but make sure we
-                  // get the value of the 'formatter type' select.
-                  '#limit_validation_errors' => array(array('fields', $name, 'type')),
-                ),
-              ),
-            );
-            $table[$name]['#attributes']['class'][] = 'field-formatter-settings-editing';
-          }
-        }
-      }
-      else {
-        $table[$name]['settings_summary'] = array();
-        $table[$name]['settings_edit'] = array();
-
-        if ($formatter) {
-          // Display a summary of the current formatter settings, and (if the
-          // summary is not empty) a button to edit them.
-          $summary = $formatter->settingsSummary();
-
-          // Allow other modules to alter the summary.
-          $context = array(
-            'formatter' => $formatter,
-            'field' => $field,
-            'instance' => $instance,
-            'view_mode' => $this->mode,
-          );
-          drupal_alter('field_formatter_settings_summary', $summary, $context);
-
-          if (!empty($summary)) {
-            $table[$name]['settings_summary'] = array(
-              '#markup' => '<div class="field-formatter-summary">' . implode('<br />', $summary) . '</div>',
-              '#cell_attributes' => array('class' => array('field-formatter-summary-cell')),
-            );
-            $table[$name]['settings_edit'] = $base_button + array(
-              '#type' => 'image_button',
-              '#name' => $name . '_formatter_settings_edit',
-              '#src' => 'core/misc/configure-dark.png',
-              '#attributes' => array('class' => array('field-formatter-settings-edit'), 'alt' => t('Edit')),
-              '#op' => 'edit',
-              // Do not check errors for the 'Edit' button, but make sure we get
-              // the value of the 'formatter type' select.
-              '#limit_validation_errors' => array(array('fields', $name, 'type')),
-              '#prefix' => '<div class="field-formatter-settings-edit-wrapper">',
-              '#suffix' => '</div>',
-            );
-          }
-        }
-      }
+    // Update the (invisible) title of the 'plugin' column.
+    $field_row['plugin']['#title'] = t('Formatter for @title', array('@title' => $instance['label']));
+    if (!empty($field_row['plugin']['settings_edit_form'])) {
+      $plugin_type_info = $entity_display->getRenderer($field_id)->getPluginDefinition();
+      $field_row['plugin']['settings_edit_form']['label']['#markup'] = t('Format settings:') . ' <span class="plugin-name">' . $plugin_type_info['label'] . '</span>';
     }
 
-    // Non-field elements.
-    foreach ($extra_fields as $name => $extra_field) {
-      $display_options = $entity_display->getComponent($name);
-
-      $table[$name] = array(
-        '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
-        '#row_type' => 'extra_field',
-        '#region_callback' => array($this, 'getRowRegion'),
-        '#js_settings' => array('rowHandler' => 'field'),
-        'human_name' => array(
-          '#markup' => check_plain($extra_field['label']),
-        ),
-        'weight' => array(
-          '#type' => 'textfield',
-          '#title' => t('Weight for @title', array('@title' => $extra_field['label'])),
-          '#title_display' => 'invisible',
-          '#default_value' => $display_options ? $display_options['weight'] : 0,
-          '#size' => 3,
-          '#attributes' => array('class' => array('field-weight')),
-        ),
-        'parent_wrapper' => array(
-          'parent' => array(
-            '#type' => 'select',
-            '#title' => t('Parents for @title', array('@title' => $extra_field['label'])),
-            '#title_display' => 'invisible',
-            '#options' => $table['#parent_options'],
-            '#empty_value' => '',
-            '#attributes' => array('class' => array('field-parent')),
-            '#parents' => array('fields', $name, 'parent'),
-          ),
-          'hidden_name' => array(
-            '#type' => 'hidden',
-            '#default_value' => $name,
-            '#attributes' => array('class' => array('field-name')),
-          ),
-        ),
-        'empty_cell' => array(
-          '#markup' => '&nbsp;',
-        ),
-        'format' => array(
-          'type' => array(
-            '#type' => 'select',
-            '#title' => t('Visibility for @title', array('@title' => $extra_field['label'])),
-            '#title_display' => 'invisible',
-            '#options' => $extra_visibility_options,
-            '#default_value' => $display_options ? 'visible' : 'hidden',
-            '#parents' => array('fields', $name, 'type'),
-            '#attributes' => array('class' => array('field-formatter-type')),
-          ),
-        ),
-        'settings_summary' => array(),
-        'settings_edit' => array(),
-      );
-    }
-
-    $form['fields'] = $table;
-
-    // Custom display settings.
-    if ($this->mode == 'default') {
-      $view_modes = entity_get_view_modes($this->entity_type);
-      // Only show the settings if there is more than one view mode.
-      if (count($view_modes) > 1) {
-        $form['modes'] = array(
-          '#type' => 'details',
-          '#title' => t('Custom display settings'),
-          '#collapsed' => TRUE,
-        );
-        // Collect options and default values for the 'Custom display settings'
-        // checkboxes.
-        $options = array();
-        $default = array();
-        $view_mode_settings = field_view_mode_settings($this->entity_type, $this->bundle);
-        foreach ($view_modes as $view_mode_name => $view_mode_info) {
-          $options[$view_mode_name] = $view_mode_info['label'];
-          if (!empty($view_mode_settings[$view_mode_name]['status'])) {
-            $default[] = $view_mode_name;
-          }
-        }
-        $form['modes']['view_modes_custom'] = array(
-          '#type' => 'checkboxes',
-          '#title' => t('Use custom display settings for the following view modes'),
-          '#options' => $options,
-          '#default_value' => $default,
-        );
-      }
-    }
+    return $field_row;
+  }
 
-    // In overviews involving nested rows from contributed modules (i.e
-    // field_group), the 'format type' selects can trigger a series of changes
-    // in child rows. The #ajax behavior is therefore not attached directly to
-    // the selects, but triggered by the client-side script through a hidden
-    // #ajax 'Refresh' button. A hidden 'refresh_rows' input tracks the name of
-    // affected rows.
-    $form['refresh_rows'] = array('#type' => 'hidden');
-    $form['refresh'] = array(
-      '#type' => 'submit',
-      '#value' => t('Refresh'),
-      '#op' => 'refresh_table',
-      '#submit' => array(array($this, 'multistepSubmit')),
-      '#ajax' => array(
-        'callback' => array($this, 'multistepAjax'),
-        'wrapper' => 'field-display-overview-wrapper',
-        'effect' => 'fade',
-        // The button stays hidden, so we hide the Ajax spinner too. Ad-hoc
-        // spinners will be added manually by the client-side script.
-        'progress' => 'none',
-      ),
-      '#attributes' => array('class' => array('visually-hidden'))
+  /**
+   * {@inheritdoc}
+   */
+  protected function buildExtraFieldRow($field_id, $extra_field, $entity_display) {
+    $extra_field_row = parent::buildExtraFieldRow($field_id, $extra_field, $entity_display);
+
+    // Insert an empty placeholder for the label column.
+    $label = array(
+      'empty_cell' => array(
+        '#markup' => '&nbsp;'
+      )
     );
+    $label_position = array_search('plugin', array_keys($extra_field_row));
+    $extra_field_row = array_slice($extra_field_row, 0, $label_position, TRUE) + $label + array_slice($extra_field_row, $label_position, count($extra_field_row) - 1, TRUE);
 
-    $form['actions'] = array('#type' => 'actions');
-    $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save'));
-
-    $form['#attached']['library'][] = array('field_ui', 'drupal.field_ui');
-
-    // Add tabledrag behavior.
-    $form['#attached']['drupal_add_tabledrag'][] = array('field-display-overview', 'order', 'sibling', 'field-weight');
-    $form['#attached']['drupal_add_tabledrag'][] = array('field-display-overview', 'match', 'parent', 'field-parent', 'field-parent', 'field-name');
-
-    return $form;
+    return $extra_field_row;
   }
 
   /**
-   * Overrides \Drupal\field_ui\OverviewBase::submitForm().
+   * {@inheritdoc}
    */
-  public function submitForm(array &$form, array &$form_state) {
-    $form_values = $form_state['values'];
-    $display = entity_get_display($this->entity_type, $this->bundle, $this->mode);
-
-    // Collect data for 'regular' fields.
-    foreach ($form['#fields'] as $field_name) {
-      // Retrieve the stored instance settings to merge with the incoming
-      // values.
-      $values = $form_values['fields'][$field_name];
-
-      if ($values['type'] == 'hidden') {
-        $display->removeComponent($field_name);
-      }
-      else {
-        // Get formatter settings. They lie either directly in submitted form
-        // values (if the whole form was submitted while some formatter
-        // settings were being edited), or have been persisted in $form_state.
-        $settings = array();
-        if (isset($values['settings_edit_form']['settings'])) {
-          $settings = $values['settings_edit_form']['settings'];
-        }
-        elseif (isset($form_state['formatter_settings'][$field_name])) {
-          $settings = $form_state['formatter_settings'][$field_name];
-        }
-        elseif ($current_options = $display->getComponent($field_name)) {
-          $settings = $current_options['settings'];
-        }
-
-        // Only save settings actually used by the selected formatter.
-        $default_settings = field_info_formatter_settings($values['type']);
-        $settings = array_intersect_key($settings, $default_settings);
-
-        $display->setComponent($field_name, array(
-          'label' => $values['label'],
-          'type' => $values['type'],
-          'weight' => $values['weight'],
-          'settings' => $settings,
-        ));
-      }
-    }
-
-    // Collect data for 'extra' fields.
-    foreach ($form['#extra'] as $name) {
-      if ($form_values['fields'][$name]['type'] == 'hidden') {
-        $display->removeComponent($name);
-      }
-      else {
-        $display->setComponent($name, array(
-          'weight' => $form_values['fields'][$name]['weight'],
-        ));
-      }
-    }
-
-    // Save the display.
-    $display->save();
-
-    // Handle the 'view modes' checkboxes if present.
-    if ($this->mode == 'default' && !empty($form_values['view_modes_custom'])) {
-      $entity_info = entity_get_info($this->entity_type);
-      $view_modes = entity_get_view_modes($this->entity_type);
-      $bundle_settings = field_bundle_settings($this->entity_type, $this->bundle);
-      $view_mode_settings = field_view_mode_settings($this->entity_type, $this->bundle);
-
-      foreach ($form_values['view_modes_custom'] as $view_mode => $value) {
-        if (!empty($value) && empty($view_mode_settings[$view_mode]['status'])) {
-          // If no display exists for the newly enabled view mode, initialize
-          // it with those from the 'default' view mode, which were used so
-          // far.
-          if (!entity_load('entity_display', $this->entity_type . '.' . $this->bundle . '.' . $view_mode)) {
-            $display = entity_get_display($this->entity_type, $this->bundle, 'default')->createCopy($view_mode);
-            $display->save();
-          }
+  protected function getEntityDisplay($mode) {
+    return entity_get_display($this->entity_type, $this->bundle, $mode);
+  }
 
-          $view_mode_label = $view_modes[$view_mode]['label'];
-          $path = $this->entityManager->getAdminPath($this->entity_type, $this->bundle) . "/display/$view_mode";
-          drupal_set_message(t('The %view_mode mode now uses custom display settings. You might want to <a href="@url">configure them</a>.', array('%view_mode' => $view_mode_label, '@url' => url($path))));
-        }
-        $bundle_settings['view_modes'][$view_mode]['status'] = !empty($value);
-      }
+  /**
+   * {@inheritdoc}
+   */
+  protected function getExtraFields() {
+    return field_info_extra_fields($this->entity_type, $this->bundle, 'display');
+  }
 
-      // Save updated bundle settings.
-      field_bundle_settings($this->entity_type, $this->bundle, $bundle_settings);
+  /**
+   * {@inheritdoc}
+   */
+  protected function getPlugin($instance, $configuration) {
+    $plugin = NULL;
+
+    if ($configuration && $configuration['type'] != 'hidden') {
+      $plugin = $this->pluginManager->getInstance(array(
+        'field_definition' => $instance,
+        'view_mode' => $this->mode,
+        'configuration' => $configuration
+      ));
     }
 
-    drupal_set_message(t('Your settings have been saved.'));
+    return $plugin;
   }
 
   /**
-   * Form submission handler for multistep buttons.
+   * {@inheritdoc}
    */
-  public function multistepSubmit($form, &$form_state) {
-    $trigger = $form_state['triggering_element'];
-    $op = $trigger['#op'];
-
-    switch ($op) {
-      case 'edit':
-        // Store the field whose settings are currently being edited.
-        $field_name = $trigger['#field_name'];
-        $form_state['formatter_settings_edit'] = $field_name;
-        break;
-
-      case 'update':
-        // Store the saved settings, and set the field back to 'non edit' mode.
-        $field_name = $trigger['#field_name'];
-        $values = $form_state['values']['fields'][$field_name]['settings_edit_form']['settings'];
-        $form_state['formatter_settings'][$field_name] = $values;
-        unset($form_state['formatter_settings_edit']);
-        break;
-
-      case 'cancel':
-        // Set the field back to 'non edit' mode.
-        unset($form_state['formatter_settings_edit']);
-        break;
+  protected function getPluginOptions($field_type) {
+    return parent::getPluginOptions($field_type) + array('hidden' => '- ' . t('Hidden') . ' -');
+  }
 
-      case 'refresh_table':
-        // If the currently edited field is one of the rows to be refreshed, set
-        // it back to 'non edit' mode.
-        $updated_rows = explode(' ', $form_state['values']['refresh_rows']);
-        if (isset($form_state['formatter_settings_edit']) && in_array($form_state['formatter_settings_edit'], $updated_rows)) {
-          unset($form_state['formatter_settings_edit']);
-        }
-        break;
-    }
+  /**
+   * {@inheritdoc}
+   */
+  protected function getDefaultPlugin($field_type) {
+    return $this->fieldTypes[$field_type]['default_formatter'];
+  }
 
-    $form_state['rebuild'] = TRUE;
+  /**
+   * {@inheritdoc}
+   */
+  protected function getDisplayModes() {
+    return entity_get_view_modes($this->entity_type);
   }
 
   /**
-   * Ajax handler for multistep buttons.
+   * {@inheritdoc}
    */
-  public function multistepAjax($form, &$form_state) {
-    $trigger = $form_state['triggering_element'];
-    $op = $trigger['#op'];
+  protected function getDisplayModeSettings() {
+    return field_view_mode_settings($this->entity_type, $this->bundle);
+  }
 
-    // Pick the elements that need to receive the ajax-new-content effect.
-    switch ($op) {
-      case 'edit':
-        $updated_rows = array($trigger['#field_name']);
-        $updated_columns = array('format');
-        break;
+  /**
+   * {@inheritdoc}
+   */
+  protected function saveDisplayModeSettings($display_mode_settings) {
+    $bundle_settings = field_bundle_settings($this->entity_type, $this->bundle);
+    $bundle_settings['view_modes'] = NestedArray::mergeDeep($bundle_settings['view_modes'], $display_mode_settings);
+    field_bundle_settings($this->entity_type, $this->bundle, $bundle_settings);
+  }
 
-      case 'update':
-      case 'cancel':
-        $updated_rows = array($trigger['#field_name']);
-        $updated_columns = array('format', 'settings_summary', 'settings_edit');
-        break;
+  /**
+   * {@inheritdoc
+   */
+  protected function getTableHeader() {
+    return array(
+      t('Field'),
+      t('Weight'),
+      t('Parent'),
+      t('Label'),
+      array('data' => t('Format'), 'colspan' => 3),
+    );
+  }
 
-      case 'refresh_table':
-        $updated_rows = array_values(explode(' ', $form_state['values']['refresh_rows']));
-        $updated_columns = array('settings_summary', 'settings_edit');
-        break;
-    }
+  /**
+   * {@inheritdoc}
+   */
+  protected function getOverviewPath($mode) {
+    return $this->entityManager->getAdminPath($this->entity_type, $this->bundle) . "/display/$mode";
+  }
 
-    foreach ($updated_rows as $name) {
-      foreach ($updated_columns as $key) {
-        $element = &$form['fields'][$name][$key];
-        $element['#prefix'] = '<div class="ajax-new-content">' . (isset($element['#prefix']) ? $element['#prefix'] : '');
-        $element['#suffix'] = (isset($element['#suffix']) ? $element['#suffix'] : '') . '</div>';
-      }
-    }
+  /**
+   * Returns an array of visibility options for field labels.
+   *
+   * @return array
+   *   An array of visibility options.
+   */
+  protected function getFieldLabelOptions() {
+    return array(
+      'above' => t('Above'),
+      'inline' => t('Inline'),
+      'hidden' => '- ' . t('Hidden') . ' -',
+    );
+  }
 
-    // Return the whole table.
-    return $form['fields'];
+  /**
+   * {@inheritdoc}
+   */
+  protected function alterSettingsForm(array &$settings_form, $plugin, FieldInstanceInterface $instance, array $form, array &$form_state) {
+    $context = array(
+      'formatter' => $plugin,
+      'field' => $instance->getField(),
+      'instance' => $instance,
+      'view_mode' => $this->mode,
+      'form' => $form,
+    );
+    drupal_alter('field_formatter_settings_form', $settings_form, $form_state, $context);
   }
 
   /**
-   * Returns the region to which a row in the display overview belongs.
-   *
-   * @param array $row
-   *   The row element.
-   *
-   * @return string|null
-   *   The region name this row belongs to.
+   * {@inheritdoc}
    */
-  public function getRowRegion($row) {
-    switch ($row['#row_type']) {
-      case 'field':
-      case 'extra_field':
-        return ($row['format']['type']['#value'] == 'hidden' ? 'hidden' : 'content');
-    }
+  protected function alterSettingsSummary(array &$summary, $plugin, FieldInstanceInterface $instance) {
+    $context = array(
+      'formatter' => $plugin,
+      'field' => $instance->getField(),
+      'instance' => $instance,
+      'view_mode' => $this->mode,
+    );
+    drupal_alter('field_formatter_settings_summary', $summary, $context);
   }
 
 }
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php
new file mode 100644
index 0000000000000000000000000000000000000000..5a45c21f77cdf4a4bc912c0df236cf69c77e03d4
--- /dev/null
+++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php
@@ -0,0 +1,760 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field_ui\DisplayOverviewBase.
+ */
+
+namespace Drupal\field_ui;
+
+use Drupal\Component\Plugin\PluginManagerBase;
+use Drupal\Core\Entity\EntityManager;
+use Drupal\entity\EntityDisplayBaseInterface;
+use Drupal\field\FieldInstanceInterface;
+use Drupal\field_ui\OverviewBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Field UI display overview base class.
+ */
+abstract class DisplayOverviewBase extends OverviewBase {
+
+  /**
+   * The widget or formatter plugin manager.
+   *
+   * @var \Drupal\Component\Plugin\PluginManagerBase
+   */
+  protected $pluginManager;
+
+  /**
+   * A list of field types.
+   *
+   * @var array
+   */
+  protected $fieldTypes;
+
+  /**
+   * Constructs a new DisplayOverviewBase.
+   *
+   * @param \Drupal\Core\Entity\EntityManager $entity_manager
+   *   The entity manager.
+   * @param \Drupal\Component\Plugin\PluginManagerBase $plugin_manager
+   *   The widget or formatter plugin manager.
+   */
+  public function __construct(EntityManager $entity_manager, PluginManagerBase $plugin_manager) {
+    parent::__construct($entity_manager);
+
+    $this->pluginManager = $plugin_manager;
+    $this->fieldTypes = field_info_field_types();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRegions() {
+    return array(
+      'content' => array(
+        'title' => t('Content'),
+        'invisible' => TRUE,
+        'message' => t('No field is displayed.')
+      ),
+      'hidden' => array(
+        'title' => t('Disabled'),
+        'message' => t('No field is hidden.')
+      ),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, array &$form_state, $entity_type = NULL, $bundle = NULL, $mode = NULL) {
+    parent::buildForm($form, $form_state, $entity_type, $bundle);
+
+    $this->mode = (isset($mode) ? $mode : 'default');
+
+    // Gather type information.
+    $instances = field_info_instances($this->entity_type, $this->bundle);
+    $extra_fields = $this->getExtraFields();
+    $entity_display = $this->getEntityDisplay($this->mode);
+
+    $form_state += array(
+      'plugin_settings_edit' => NULL,
+    );
+
+    $form += array(
+      '#entity_type' => $this->entity_type,
+      '#bundle' => $this->bundle,
+      '#mode' => $this->mode,
+      '#fields' => array_keys($instances),
+      '#extra' => array_keys($extra_fields),
+    );
+
+    if (empty($instances) && empty($extra_fields)) {
+      drupal_set_message(t('There are no fields yet added. You can add new fields on the <a href="@link">Manage fields</a> page.', array('@link' => url($this->adminPath . '/fields'))), 'warning');
+      return $form;
+    }
+
+    $table = array(
+      '#type' => 'field_ui_table',
+      '#pre_render' => array(array($this, 'tablePreRender')),
+      '#tree' => TRUE,
+      '#header' => $this->getTableHeader(),
+      '#regions' => $this->getRegions(),
+      '#attributes' => array(
+        'class' => array('field-ui-overview'),
+        'id' => 'field-display-overview',
+      ),
+      // Add Ajax wrapper.
+      '#prefix' => '<div id="field-display-overview-wrapper">',
+      '#suffix' => '</div>',
+    );
+
+    // Field rows.
+    foreach ($instances as $field_id => $instance) {
+      $table[$field_id] = $this->buildFieldRow($field_id, $instance, $entity_display, $form, $form_state);
+    }
+
+    // Non-field elements.
+    foreach ($extra_fields as $field_id => $extra_field) {
+      $table[$field_id] = $this->buildExtraFieldRow($field_id, $extra_field, $entity_display);
+    }
+
+    $form['fields'] = $table;
+
+    // Custom display settings.
+    if ($this->mode == 'default') {
+      // Only show the settings if there is at least one custom display mode.
+      if ($display_modes = $this->getDisplayModes()) {
+        $form['modes'] = array(
+          '#type' => 'details',
+          '#title' => t('Custom display settings'),
+          '#collapsed' => TRUE,
+        );
+        // Collect options and default values for the 'Custom display settings'
+        // checkboxes.
+        $options = array();
+        $default = array();
+        $display_mode_settings = $this->getDisplayModeSettings();
+        foreach ($display_modes as $mode_name => $mode_info) {
+          $options[$mode_name] = $mode_info['label'];
+          if (!empty($display_mode_settings[$mode_name]['status'])) {
+            $default[] = $mode_name;
+          }
+        }
+        $form['modes']['display_modes_custom'] = array(
+          '#type' => 'checkboxes',
+          '#title' => t('Use custom display settings for the following modes'),
+          '#options' => $options,
+          '#default_value' => $default,
+        );
+      }
+    }
+
+    // In overviews involving nested rows from contributed modules (i.e
+    // field_group), the 'plugin type' selects can trigger a series of changes
+    // in child rows. The #ajax behavior is therefore not attached directly to
+    // the selects, but triggered by the client-side script through a hidden
+    // #ajax 'Refresh' button. A hidden 'refresh_rows' input tracks the name of
+    // affected rows.
+    $form['refresh_rows'] = array('#type' => 'hidden');
+    $form['refresh'] = array(
+      '#type' => 'submit',
+      '#value' => t('Refresh'),
+      '#op' => 'refresh_table',
+      '#submit' => array(array($this, 'multistepSubmit')),
+      '#ajax' => array(
+        'callback' => array($this, 'multistepAjax'),
+        'wrapper' => 'field-display-overview-wrapper',
+        'effect' => 'fade',
+        // The button stays hidden, so we hide the Ajax spinner too. Ad-hoc
+        // spinners will be added manually by the client-side script.
+        'progress' => 'none',
+      ),
+      '#attributes' => array('class' => array('visually-hidden'))
+    );
+
+    $form['actions'] = array('#type' => 'actions');
+    $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save'));
+
+    $form['#attached']['library'][] = array('field_ui', 'drupal.field_ui');
+
+    // Add tabledrag behavior.
+    $form['#attached']['drupal_add_tabledrag'][] = array('field-display-overview', 'order', 'sibling', 'field-weight');
+    $form['#attached']['drupal_add_tabledrag'][] = array('field-display-overview', 'match', 'parent', 'field-parent', 'field-parent', 'field-name');
+
+    return $form;
+  }
+
+  /**
+   * Builds the table row structure for a single field.
+   *
+   * @param string $field_id
+   *   The field ID.
+   * @param \Drupal\field\FieldInstanceInterface $instance
+   *   The field instance.
+   * @param \Drupal\entity\EntityDisplayBaseInterface $entity_display
+   *   The entity display.
+   * @param array $form
+   *   An associative array containing the structure of the form.
+   * @param array $form_state
+   *   A reference to a keyed array containing the current state of the form.
+   *
+   * @return array
+   *   A table row array.
+   */
+  protected function buildFieldRow($field_id, FieldInstanceInterface $instance, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) {
+    $field = $instance->getField();
+    $display_options = $entity_display->getComponent($field_id);
+
+    $field_row = array(
+      '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
+      '#row_type' => 'field',
+      '#region_callback' => array($this, 'getRowRegion'),
+      '#js_settings' => array(
+        'rowHandler' => 'field',
+        'defaultPlugin' => $this->getDefaultPlugin($field['type']),
+      ),
+      'human_name' => array(
+        '#markup' => check_plain($instance['label']),
+      ),
+      'weight' => array(
+        '#type' => 'textfield',
+        '#title' => t('Weight for @title', array('@title' => $instance['label'])),
+        '#title_display' => 'invisible',
+        '#default_value' => $display_options ? $display_options['weight'] : '0',
+        '#size' => 3,
+        '#attributes' => array('class' => array('field-weight')),
+      ),
+      'parent_wrapper' => array(
+        'parent' => array(
+          '#type' => 'select',
+          '#title' => t('Label display for @title', array('@title' => $instance['label'])),
+          '#title_display' => 'invisible',
+          '#options' => drupal_map_assoc(array_keys($this->getRegions())),
+          '#empty_value' => '',
+          '#attributes' => array('class' => array('field-parent')),
+          '#parents' => array('fields', $field_id, 'parent'),
+        ),
+        'hidden_name' => array(
+          '#type' => 'hidden',
+          '#default_value' => $field_id,
+          '#attributes' => array('class' => array('field-name')),
+        ),
+      ),
+
+    );
+
+    $field_row['plugin'] = array(
+      'type' => array(
+        '#type' => 'select',
+        '#title' => t('Plugin for @title', array('@title' => $instance['label'])),
+        '#title_display' => 'invisible',
+        '#options' => $this->getPluginOptions($field['type']),
+        '#default_value' => $display_options ? $display_options['type'] : 'hidden',
+        '#parents' => array('fields', $field_id, 'type'),
+        '#attributes' => array('class' => array('field-plugin-type')),
+      ),
+      'settings_edit_form' => array(),
+    );
+
+    // Check the currently selected plugin, and merge persisted values for its
+    // settings.
+    if (isset($form_state['values']['fields'][$field_id]['type'])) {
+      $display_options['type'] = $form_state['values']['fields'][$field_id]['type'];
+    }
+    if (isset($form_state['plugin_settings'][$field_id])) {
+      $display_options['settings'] = $form_state['plugin_settings'][$field_id];
+    }
+
+    // Get the corresponding plugin object.
+    $plugin = $this->getPlugin($instance, $display_options);
+
+    // Base button element for the various plugin settings actions.
+    $base_button = array(
+      '#submit' => array(array($this, 'multistepSubmit')),
+      '#ajax' => array(
+        'callback' => array($this, 'multistepAjax'),
+        'wrapper' => 'field-display-overview-wrapper',
+        'effect' => 'fade',
+      ),
+      '#field_name' => $field_id,
+    );
+
+    if ($form_state['plugin_settings_edit'] == $field_id) {
+      // We are currently editing this field's plugin settings. Display the
+      // settings form and submit buttons.
+      $field_row['plugin']['settings_edit_form'] = array();
+
+      if ($plugin) {
+        // Generate the settings form and allow other modules to alter it.
+        $settings_form = $plugin->settingsForm($form, $form_state);
+        $this->alterSettingsForm($settings_form, $plugin, $instance, $form, $form_state);
+
+        if ($settings_form) {
+          $field_row['plugin']['#cell_attributes'] = array('colspan' => 3);
+          $field_row['plugin']['settings_edit_form'] = array(
+            '#type' => 'container',
+            '#attributes' => array('class' => array('field-plugin-settings-edit-form')),
+            '#parents' => array('fields', $field_id, 'settings_edit_form'),
+            'label' => array(
+              '#markup' => t('Plugin settings'),
+            ),
+            'settings' => $settings_form,
+            'actions' => array(
+              '#type' => 'actions',
+              'save_settings' => $base_button + array(
+                '#type' => 'submit',
+                '#name' => $field_id . '_plugin_settings_update',
+                '#value' => t('Update'),
+                '#op' => 'update',
+              ),
+              'cancel_settings' => $base_button + array(
+                '#type' => 'submit',
+                '#name' => $field_id . '_plugin_settings_cancel',
+                '#value' => t('Cancel'),
+                '#op' => 'cancel',
+                // Do not check errors for the 'Cancel' button, but make sure we
+                // get the value of the 'plugin type' select.
+                '#limit_validation_errors' => array(array('fields', $field_id, 'type')),
+              ),
+            ),
+          );
+          $field_row['#attributes']['class'][] = 'field-plugin-settings-editing';
+        }
+      }
+    }
+    else {
+      $field_row['settings_summary'] = array();
+      $field_row['settings_edit'] = array();
+
+      if ($plugin) {
+        // Display a summary of the current plugin settings, and (if the
+        // summary is not empty) a button to edit them.
+        $summary = $plugin->settingsSummary();
+
+        // Allow other modules to alter the summary.
+        $this->alterSettingsSummary($summary, $plugin, $instance);
+
+        if (!empty($summary)) {
+          $field_row['settings_summary'] = array(
+            '#markup' => '<div class="field-plugin-summary">' . implode('<br />', $summary) . '</div>',
+            '#cell_attributes' => array('class' => array('field-plugin-summary-cell')),
+          );
+          $field_row['settings_edit'] = $base_button + array(
+            '#type' => 'image_button',
+            '#name' => $field_id . '_settings_edit',
+            '#src' => 'core/misc/configure-dark.png',
+            '#attributes' => array('class' => array('field-plugin-settings-edit'), 'alt' => t('Edit')),
+            '#op' => 'edit',
+            // Do not check errors for the 'Edit' button, but make sure we get
+            // the value of the 'plugin type' select.
+            '#limit_validation_errors' => array(array('fields', $field_id, 'type')),
+            '#prefix' => '<div class="field-plugin-settings-edit-wrapper">',
+            '#suffix' => '</div>',
+          );
+        }
+      }
+    }
+
+    return $field_row;
+  }
+
+  /**
+   * Builds the table row structure for a single extra field.
+   *
+   * @param string $field_id
+   *   The field ID.
+   * @param array $extra_field
+   *   The pseudo-field element.
+   * @param \Drupal\entity\EntityDisplayBaseInterface $entity_display
+   *   The entity display.
+   *
+   * @return array
+   *   A table row array.
+   */
+  protected function buildExtraFieldRow($field_id, $extra_field, $entity_display) {
+    $display_options = $entity_display->getComponent($field_id);
+
+    $extra_field_row = array(
+      '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
+      '#row_type' => 'extra_field',
+      '#region_callback' => array($this, 'getRowRegion'),
+      '#js_settings' => array('rowHandler' => 'field'),
+      'human_name' => array(
+        '#markup' => check_plain($extra_field['label']),
+      ),
+      'weight' => array(
+        '#type' => 'textfield',
+        '#title' => t('Weight for @title', array('@title' => $extra_field['label'])),
+        '#title_display' => 'invisible',
+        '#default_value' => $display_options ? $display_options['weight'] : 0,
+        '#size' => 3,
+        '#attributes' => array('class' => array('field-weight')),
+      ),
+      'parent_wrapper' => array(
+        'parent' => array(
+          '#type' => 'select',
+          '#title' => t('Parents for @title', array('@title' => $extra_field['label'])),
+          '#title_display' => 'invisible',
+          '#options' => drupal_map_assoc(array_keys($this->getRegions())),
+          '#empty_value' => '',
+          '#attributes' => array('class' => array('field-parent')),
+          '#parents' => array('fields', $field_id, 'parent'),
+        ),
+        'hidden_name' => array(
+          '#type' => 'hidden',
+          '#default_value' => $field_id,
+          '#attributes' => array('class' => array('field-name')),
+        ),
+      ),
+      'plugin' => array(
+        'type' => array(
+          '#type' => 'select',
+          '#title' => t('Visibility for @title', array('@title' => $extra_field['label'])),
+          '#title_display' => 'invisible',
+          '#options' => $this->getExtraFieldVisibilityOptions(),
+          '#default_value' => $display_options ? 'visible' : 'hidden',
+          '#parents' => array('fields', $field_id, 'type'),
+          '#attributes' => array('class' => array('field-plugin-type')),
+        ),
+      ),
+      'settings_summary' => array(),
+      'settings_edit' => array(),
+    );
+
+    return $extra_field_row;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, array &$form_state) {
+    $form_values = $form_state['values'];
+    $display = $this->getEntityDisplay($this->mode);
+
+    // Collect data for 'regular' fields.
+    foreach ($form['#fields'] as $field_name) {
+      // Retrieve the stored instance settings to merge with the incoming
+      // values.
+      $values = $form_values['fields'][$field_name];
+
+      if ($values['type'] == 'hidden') {
+        $display->removeComponent($field_name);
+      }
+      else {
+        // Get plugin settings. They lie either directly in submitted form
+        // values (if the whole form was submitted while some plugin settings
+        // were being edited), or have been persisted in $form_state.
+        $settings = array();
+        if (isset($values['settings_edit_form']['settings'])) {
+          $settings = $values['settings_edit_form']['settings'];
+        }
+        elseif (isset($form_state['plugin_settings'][$field_name])) {
+          $settings = $form_state['plugin_settings'][$field_name];
+        }
+        elseif ($current_options = $display->getComponent($field_name)) {
+          $settings = $current_options['settings'];
+        }
+
+        // Only save settings actually used by the selected plugin.
+        $default_settings = $this->pluginManager->getDefaultSettings($values['type']);
+        $settings = array_intersect_key($settings, $default_settings);
+
+        // Default component values.
+        $component_values = array(
+          'type' => $values['type'],
+          'weight' => $values['weight'],
+          'settings' => $settings
+        );
+
+        // Only formatters have configurable label visibility.
+        if (isset($values['label'])) {
+          $component_values['label'] = $values['label'];
+        }
+
+        $display->setComponent($field_name, $component_values);
+      }
+    }
+
+    // Collect data for 'extra' fields.
+    foreach ($form['#extra'] as $name) {
+      if ($form_values['fields'][$name]['type'] == 'hidden') {
+        $display->removeComponent($name);
+      }
+      else {
+        $display->setComponent($name, array(
+          'weight' => $form_values['fields'][$name]['weight'],
+        ));
+      }
+    }
+
+    // Save the display.
+    $display->save();
+
+    // Handle the 'view modes' checkboxes if present.
+    if ($this->mode == 'default' && !empty($form_values['display_modes_custom'])) {
+      $display_modes = $this->getDisplayModes();
+      $display_mode_settings = $this->getDisplayModeSettings();
+
+      $display_mode_bundle_settings = array();
+      foreach ($form_values['display_modes_custom'] as $mode => $value) {
+        if (!empty($value) && empty($display_mode_settings[$mode]['status'])) {
+          // If no display exists for the newly enabled view mode, initialize
+          // it with those from the 'default' view mode, which were used so
+          // far.
+          if (!entity_load($this->getEntityDisplay('default')->entityType(), $this->entity_type . '.' . $this->bundle . '.' . $mode)) {
+            $display = $this->getEntityDisplay('default')->createCopy($mode);
+            $display->save();
+          }
+
+          $display_mode_label = $display_modes[$mode]['label'];
+          $path = $this->getOverviewPath($mode);
+          drupal_set_message(t('The %display_mode mode now uses custom display settings. You might want to <a href="@url">configure them</a>.', array('%display_mode' => $display_mode_label, '@url' => url($path))));
+        }
+        $display_mode_bundle_settings[$mode]['status'] = !empty($value);
+      }
+
+      // Save updated bundle settings.
+      $this->saveDisplayModeSettings($display_mode_bundle_settings);
+    }
+
+    drupal_set_message(t('Your settings have been saved.'));
+  }
+
+  /**
+   * Form submission handler for multistep buttons.
+   */
+  public function multistepSubmit($form, &$form_state) {
+    $trigger = $form_state['triggering_element'];
+    $op = $trigger['#op'];
+
+    switch ($op) {
+      case 'edit':
+        // Store the field whose settings are currently being edited.
+        $field_name = $trigger['#field_name'];
+        $form_state['plugin_settings_edit'] = $field_name;
+        break;
+
+      case 'update':
+        // Store the saved settings, and set the field back to 'non edit' mode.
+        $field_name = $trigger['#field_name'];
+        $values = $form_state['values']['fields'][$field_name]['settings_edit_form']['settings'];
+        $form_state['plugin_settings'][$field_name] = $values;
+        unset($form_state['plugin_settings_edit']);
+        break;
+
+      case 'cancel':
+        // Set the field back to 'non edit' mode.
+        unset($form_state['plugin_settings_edit']);
+        break;
+
+      case 'refresh_table':
+        // If the currently edited field is one of the rows to be refreshed, set
+        // it back to 'non edit' mode.
+        $updated_rows = explode(' ', $form_state['values']['refresh_rows']);
+        if (isset($form_state['plugin_settings_edit']) && in_array($form_state['plugin_settings_edit'], $updated_rows)) {
+          unset($form_state['plugin_settings_edit']);
+        }
+        break;
+    }
+
+    $form_state['rebuild'] = TRUE;
+  }
+
+  /**
+   * Ajax handler for multistep buttons.
+   */
+  public function multistepAjax($form, &$form_state) {
+    $trigger = $form_state['triggering_element'];
+    $op = $trigger['#op'];
+
+    // Pick the elements that need to receive the ajax-new-content effect.
+    switch ($op) {
+      case 'edit':
+        $updated_rows = array($trigger['#field_name']);
+        $updated_columns = array('plugin');
+        break;
+
+      case 'update':
+      case 'cancel':
+        $updated_rows = array($trigger['#field_name']);
+        $updated_columns = array('plugin', 'settings_summary', 'settings_edit');
+        break;
+
+      case 'refresh_table':
+        $updated_rows = array_values(explode(' ', $form_state['values']['refresh_rows']));
+        $updated_columns = array('settings_summary', 'settings_edit');
+        break;
+    }
+
+    foreach ($updated_rows as $name) {
+      foreach ($updated_columns as $key) {
+        $element = &$form['fields'][$name][$key];
+        $element['#prefix'] = '<div class="ajax-new-content">' . (isset($element['#prefix']) ? $element['#prefix'] : '');
+        $element['#suffix'] = (isset($element['#suffix']) ? $element['#suffix'] : '') . '</div>';
+      }
+    }
+
+    // Return the whole table.
+    return $form['fields'];
+  }
+
+  /**
+   * Returns the entity display object used by this form.
+   *
+   * @param string $mode
+   *   A view or form mode.
+   *
+   * @return \Drupal\entity\EntityDisplayBaseInterface
+   *   An entity display.
+   */
+  abstract protected function getEntityDisplay($mode);
+
+  /**
+   * Returns the extra fields of the entity type and bundle used by this form.
+   *
+   * @return array
+   *   An array of extra field info, as provided by field_info_extra_fields().
+   */
+  abstract protected function getExtraFields();
+
+  /**
+   * Returns the widget or formatter plugin for a field.
+   *
+   * @param \Drupal\field\FieldInstanceInterface $instance
+   *   The field instance.
+   * @param array $configuration
+   *   The plugin configuration
+   *
+   * @return object
+   *   The corresponding plugin.
+   */
+  abstract protected function getPlugin($instance, $configuration);
+
+  /**
+   * Returns an array of widget or formatter options for a field type.
+   *
+   * @param string $field_type
+   *   The name of the field type.
+   *
+   * @return array
+   *   An array of widget or formatter options.
+   */
+  protected function getPluginOptions($field_type) {
+    return $this->pluginManager->getOptions($field_type);
+  }
+
+  /**
+   * Returns the ID of the default widget or formatter plugin for a field type.
+   *
+   * @param string $field_type
+   *   The field type.
+   *
+   * @return string
+   *   The widget or formatter plugin ID.
+   */
+  abstract protected function getDefaultPlugin($field_type);
+
+  /**
+   * Returns the form or view modes used by this form.
+   *
+   * @return array
+   *   An array of form or view mode info.
+   */
+  abstract protected function getDisplayModes();
+
+  /**
+   * Returns form or view modes settings for the bundle used by this form.
+   *
+   * @return array
+   *   An array of form or view mode settings.
+   */
+  abstract protected function getDisplayModeSettings();
+
+  /**
+   * Saves the updated display mode settings.
+   *
+   * @param array $display_mode_settings
+   *   An array holding updated form or view mode settings.
+   */
+  abstract protected function saveDisplayModeSettings($display_mode_settings);
+
+  /**
+   * Returns the region to which a row in the display overview belongs.
+   *
+   * @param array $row
+   *   The row element.
+   *
+   * @return string|null
+   *   The region name this row belongs to.
+   */
+  public function getRowRegion($row) {
+    switch ($row['#row_type']) {
+      case 'field':
+      case 'extra_field':
+        return ($row['plugin']['type']['#value'] == 'hidden' ? 'hidden' : 'content');
+    }
+  }
+
+  /**
+   * Returns an array of visibility options for extra fields.
+   *
+   * @return array
+   *   An array of visibility options.
+   */
+  protected function getExtraFieldVisibilityOptions() {
+    return array(
+      'visible' => t('Visible'),
+      'hidden' => '- ' . t('Hidden') . ' -',
+    );
+  }
+
+  /**
+   * Returns an array containing the table headers.
+   *
+   * @return array
+   *   The table header.
+   */
+  abstract protected function getTableHeader();
+
+  /**
+   * Returns the path of a specific form or view mode form.
+   *
+   * @param string $mode
+   *   The form or view mode.
+   *
+   * @return string
+   *   An internal path.
+   */
+  abstract protected function getOverviewPath($mode);
+
+  /**
+   * Alters the widget or formatter settings form.
+   *
+   * @param array $settings_form
+   *   The widget or formatter settings form.
+   * @param object $plugin
+   *   The widget or formatter.
+   * @param FieldInstanceInterface $instance
+   *   The field instance.
+   * @param array $form
+   *   The The (entire) configuration form array.
+   * @param array $form_state
+   *   The form state.
+   */
+  abstract protected function alterSettingsForm(array &$settings_form, $plugin, FieldInstanceInterface $instance, array $form, array &$form_state);
+
+  /**
+   * Alters the widget or formatter settings summary.
+   *
+   * @param array $summary
+   *   The widget or formatter settings summary.
+   * @param object $plugin
+   *   The widget or formatter.
+   * @param FieldInstanceInterface $instance
+   *   The field instance.
+   */
+  abstract protected function alterSettingsSummary(array &$summary, $plugin, FieldInstanceInterface $instance);
+
+}
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
index ec602ffe4e83372b0d8aeb2a1aff5030447a92f4..8e7e770fe183792b72eeb0d3ea9494909be64ca8 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
@@ -8,8 +8,6 @@
 namespace Drupal\field_ui;
 
 use Drupal\field_ui\OverviewBase;
-use Drupal\Core\Entity\EntityManager;
-use Drupal\field\Plugin\Type\Widget\WidgetPluginManager;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\field\Plugin\Core\Entity\Field;
 
@@ -18,80 +16,36 @@
  */
 class FieldOverview extends OverviewBase {
 
-  /**
-   * The widget plugin manager.
-   *
-   * @var \Drupal\field\Plugin\Type\Widget\WidgetPluginManager
-   */
-  protected $widgetManager;
-
-  /**
-   * Constructs a new DisplayOverview.
-   *
-   * @param \Drupal\Core\Entity\EntityManager $entity_manager
-   *   The entity manager.
-   * @param \Drupal\field\Plugin\Type\Widget\WidgetPluginManager $widget_manager
-   *   The widget plugin manager.
-   */
-  public function __construct(EntityManager $entity_manager, WidgetPluginManager $widget_manager) {
-    parent::__construct($entity_manager);
-
-    $this->widgetManager = $widget_manager;
-  }
-
   /**
    * {@inheritdoc}
    */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('plugin.manager.entity'),
-      $container->get('plugin.manager.field.widget')
-    );
-  }
-
-  /**
-   * Implements Drupal\field_ui\OverviewBase::getRegions().
-   */
   public function getRegions() {
     return array(
       'content' => array(
         'title' => t('Content'),
         'invisible' => TRUE,
-        'message' => t('No fields are present yet.'),
-      ),
-      'hidden' => array(
-        'title' => t('Hidden'),
-        'invisible' => TRUE,
-        'message' => t('No fields.'),
+        // @todo Bring back this message in https://drupal.org/node/1963340.
+        //'message' => t('No fields are present yet.'),
       ),
     );
   }
 
   /**
-   * Implements \Drupal\Core\Form\FormInterface::getFormID().
+   * {@inheritdoc}
    */
   public function getFormID() {
     return 'field_ui_field_overview_form';
   }
 
   /**
-   * Implements \Drupal\Core\Form\FormInterface::buildForm().
+   * {@inheritdoc}
    */
-  public function buildForm(array $form, array &$form_state, $entity_type = NULL, $bundle = NULL, $form_mode = NULL) {
+  public function buildForm(array $form, array &$form_state, $entity_type = NULL, $bundle = NULL) {
     parent::buildForm($form, $form_state, $entity_type, $bundle);
 
-    $this->mode = (isset($form_mode) ? $form_mode : 'default');
-    // When displaying the form, make sure the list of fields is up-to-date.
-    if (empty($form_state['post'])) {
-      field_info_cache_clear();
-    }
-
     // Gather bundle information.
     $instances = field_info_instances($this->entity_type, $this->bundle);
     $field_types = field_info_field_types();
-    $widget_types = field_info_widget_types();
-    $extra_fields = field_info_extra_fields($this->entity_type, $this->bundle, 'form');
-    $entity_form_display = entity_get_form_display($this->entity_type, $this->bundle, $this->mode);
 
     // Field prefix.
     $field_prefix = config('field_ui.settings')->get('field_prefix');
@@ -100,23 +54,17 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
       '#entity_type' => $this->entity_type,
       '#bundle' => $this->bundle,
       '#fields' => array_keys($instances),
-      '#extra' => array_keys($extra_fields),
     );
 
     $table = array(
       '#type' => 'field_ui_table',
-      '#pre_render' => array(array($this, 'tablePreRender')),
       '#tree' => TRUE,
       '#header' => array(
         t('Label'),
-        t('Weight'),
-        t('Parent'),
         t('Machine name'),
         t('Field type'),
-        t('Widget'),
         t('Operations'),
       ),
-      '#parent_options' => array(),
       '#regions' => $this->getRegions(),
       '#attributes' => array(
         'class' => array('field-ui-overview'),
@@ -127,39 +75,14 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
     // Fields.
     foreach ($instances as $name => $instance) {
       $field = field_info_field($instance['field_name']);
-      $widget_configuration = $entity_form_display->getComponent($instance['field_name']);
       $admin_field_path = $this->adminPath . '/fields/' . $instance->id();
       $table[$name] = array(
-        '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
-        '#row_type' => 'field',
-        '#region_callback' => array($this, 'getRowRegion'),
+        '#attributes' => array(
+          'id' => drupal_html_class($name),
+        ),
         'label' => array(
           '#markup' => check_plain($instance['label']),
         ),
-        'weight' => array(
-          '#type' => 'textfield',
-          '#title' => t('Weight for @title', array('@title' => $instance['label'])),
-          '#title_display' => 'invisible',
-          '#default_value' => $widget_configuration ? $widget_configuration['weight'] : '0',
-          '#size' => 3,
-          '#attributes' => array('class' => array('field-weight')),
-         ),
-        'parent_wrapper' => array(
-          'parent' => array(
-            '#type' => 'select',
-            '#title' => t('Parent for @title', array('@title' => $instance['label'])),
-            '#title_display' => 'invisible',
-            '#options' => $table['#parent_options'],
-            '#empty_value' => '',
-            '#attributes' => array('class' => array('field-parent')),
-            '#parents' => array('fields', $name, 'parent'),
-          ),
-          'hidden_name' => array(
-            '#type' => 'hidden',
-            '#default_value' => $name,
-            '#attributes' => array('class' => array('field-name')),
-          ),
-        ),
         'field_name' => array(
           '#markup' => $instance['field_name'],
         ),
@@ -169,12 +92,6 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
           '#href' => $admin_field_path . '/field',
           '#options' => array('attributes' => array('title' => t('Edit field settings.'))),
         ),
-        'widget_type' => array(
-          '#type' => 'link',
-          '#title' => $widget_configuration ? $widget_types[$widget_configuration['type']]['label'] : $widget_types['hidden']['label'],
-          '#href' => $admin_field_path . '/widget-type',
-          '#options' => array('attributes' => array('title' => t('Change widget type.'))),
-        ),
       );
 
       $links = array();
@@ -183,6 +100,11 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
         'href' => $admin_field_path,
         'attributes' => array('title' => t('Edit instance settings.')),
       );
+      $links['field-settings'] = array(
+        'title' => t('Field settings'),
+        'href' => $admin_field_path . '/field',
+        'attributes' => array('title' => t('Edit field settings.')),
+      );
       $links['delete'] = array(
         'title' => t('Delete'),
         'href' => "$admin_field_path/delete",
@@ -199,79 +121,21 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
       }
     }
 
-    // Non-field elements.
-    foreach ($extra_fields as $name => $extra_field) {
-      $table[$name] = array(
-        '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
-        '#row_type' => 'extra_field',
-        '#region_callback' => array($this, 'getRowRegion'),
-        'label' => array(
-          '#markup' => check_plain($extra_field['label']),
-        ),
-        'weight' => array(
-          '#type' => 'textfield',
-          '#default_value' => $extra_field['weight'],
-          '#size' => 3,
-          '#attributes' => array('class' => array('field-weight')),
-          '#title_display' => 'invisible',
-          '#title' => t('Weight for @title', array('@title' => $extra_field['label'])),
-        ),
-        'parent_wrapper' => array(
-          'parent' => array(
-            '#type' => 'select',
-            '#title' => t('Parent for @title', array('@title' => $extra_field['label'])),
-            '#title_display' => 'invisible',
-            '#options' => $table['#parent_options'],
-            '#empty_value' => '',
-            '#attributes' => array('class' => array('field-parent')),
-            '#parents' => array('fields', $name, 'parent'),
-          ),
-          'hidden_name' => array(
-            '#type' => 'hidden',
-            '#default_value' => $name,
-            '#attributes' => array('class' => array('field-name')),
-          ),
-        ),
-        'field_name' => array(
-          '#markup' => $name,
-        ),
-        'type' => array(
-          '#markup' => isset($extra_field['description']) ? $extra_field['description'] : '',
-          '#cell_attributes' => array('colspan' => 2),
-        ),
-        'operations' => array(
-          '#markup' => '',
-        ),
-      );
-    }
-
-    // Additional row: add new field.
-    $max_weight = $entity_form_display->getHighestWeight();
-
-    // Prepare the widget types to be display as options.
-    $widget_options = $this->widgetManager->getOptions();
-    $widget_type_options = array();
-    foreach ($widget_options as $field_type => $widgets) {
-      $widget_type_options[$field_types[$field_type]['label']] = $widgets;
-    }
-
     // Gather valid field types.
     $field_type_options = array();
     foreach ($field_types as $name => $field_type) {
-      // Skip field types which have no widget types, or should not be added via
-      // user interface.
-      if (isset($widget_options[$name]) && empty($field_type['no_ui'])) {
+      // Skip field types which should not be added via user interface.
+      if (empty($field_type['no_ui'])) {
         $field_type_options[$name] = $field_type['label'];
       }
     }
     asort($field_type_options);
 
-    if ($field_type_options && $widget_type_options) {
+    // Additional row: add new field.
+    if ($field_type_options) {
       $name = '_add_new_field';
       $table[$name] = array(
-        '#attributes' => array('class' => array('draggable', 'tabledrag-leaf', 'add-new')),
-        '#row_type' => 'add_new_field',
-        '#region_callback' => array($this, 'getRowRegion'),
+        '#attributes' => array('class' => array('add-new')),
         'label' => array(
           '#type' => 'textfield',
           '#title' => t('New field label'),
@@ -281,32 +145,6 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
           '#prefix' => '<div class="label-input"><div class="add-new-placeholder">' . t('Add new field') .'</div>',
           '#suffix' => '</div>',
         ),
-        'weight' => array(
-          '#type' => 'textfield',
-          '#default_value' => $max_weight + 1,
-          '#size' => 3,
-          '#title_display' => 'invisible',
-          '#title' => t('Weight for new field'),
-          '#attributes' => array('class' => array('field-weight')),
-          '#prefix' => '<div class="add-new-placeholder">&nbsp;</div>',
-        ),
-        'parent_wrapper' => array(
-          'parent' => array(
-            '#type' => 'select',
-            '#title' => t('Parent for new field'),
-            '#title_display' => 'invisible',
-            '#options' => $table['#parent_options'],
-            '#empty_value' => '',
-            '#attributes' => array('class' => array('field-parent')),
-            '#prefix' => '<div class="add-new-placeholder">&nbsp;</div>',
-            '#parents' => array('fields', $name, 'parent'),
-          ),
-          'hidden_name' => array(
-            '#type' => 'hidden',
-            '#default_value' => $name,
-            '#attributes' => array('class' => array('field-name')),
-          ),
-        ),
         'field_name' => array(
           '#type' => 'machine_name',
           '#title' => t('New field name'),
@@ -336,17 +174,7 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
           '#empty_option' => t('- Select a field type -'),
           '#description' => t('Type of data to store.'),
           '#attributes' => array('class' => array('field-type-select')),
-          '#prefix' => '<div class="add-new-placeholder">&nbsp;</div>',
-        ),
-        'widget_type' => array(
-          '#type' => 'select',
-          '#title' => t('Widget for new field'),
-          '#title_display' => 'invisible',
-          '#options' => $widget_type_options,
-          '#empty_option' => t('- Select a widget -'),
-          '#description' => t('Form element to edit the data.'),
-          '#attributes' => array('class' => array('widget-type-select')),
-          '#cell_attributes' => array('colspan' => 3),
+          '#cell_attributes' => array('colspan' => 2),
           '#prefix' => '<div class="add-new-placeholder">&nbsp;</div>',
         ),
         // Place the 'translatable' property as an explicit value so that
@@ -360,7 +188,7 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
 
     // Additional row: re-use existing field.
     $existing_fields = $this->getExistingFieldOptions();
-    if ($existing_fields && $widget_type_options) {
+    if ($existing_fields) {
       // Build list of options.
       $existing_field_options = array();
       foreach ($existing_fields as $field_name => $info) {
@@ -374,7 +202,7 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
       asort($existing_field_options);
       $name = '_add_existing_field';
       $table[$name] = array(
-        '#attributes' => array('class' => array('draggable', 'tabledrag-leaf', 'add-new')),
+        '#attributes' => array('class' => array('add-new')),
         '#row_type' => 'add_new_field',
         '#region_callback' => array($this, 'getRowRegion'),
         'label' => array(
@@ -387,32 +215,6 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
           '#prefix' => '<div class="label-input"><div class="add-new-placeholder">' . t('Re-use existing field') .'</div>',
           '#suffix' => '</div>',
         ),
-        'weight' => array(
-          '#type' => 'textfield',
-          '#default_value' => $max_weight + 2,
-          '#size' => 3,
-          '#title_display' => 'invisible',
-          '#title' => t('Weight for added field'),
-          '#attributes' => array('class' => array('field-weight')),
-          '#prefix' => '<div class="add-new-placeholder">&nbsp;</div>',
-        ),
-        'parent_wrapper' => array(
-          'parent' => array(
-            '#type' => 'select',
-            '#title' => t('Parent for existing field'),
-            '#title_display' => 'invisible',
-            '#options' => $table['#parent_options'],
-            '#empty_value' => '',
-            '#attributes' => array('class' => array('field-parent')),
-            '#prefix' => '<div class="add-new-placeholder">&nbsp;</div>',
-            '#parents' => array('fields', $name, 'parent'),
-          ),
-          'hidden_name' => array(
-            '#type' => 'hidden',
-            '#default_value' => $name,
-            '#attributes' => array('class' => array('field-name')),
-          ),
-        ),
         'field_name' => array(
           '#type' => 'select',
           '#title' => t('Existing field to share'),
@@ -421,58 +223,29 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
           '#empty_option' => t('- Select an existing field -'),
           '#description' => t('Field to share'),
           '#attributes' => array('class' => array('field-select')),
-          '#cell_attributes' => array('colspan' => 2),
-          '#prefix' => '<div class="add-new-placeholder">&nbsp;</div>',
-        ),
-        'widget_type' => array(
-          '#type' => 'select',
-          '#title' => t('Widget for existing field'),
-          '#title_display' => 'invisible',
-          '#options' => $widget_type_options,
-          '#empty_option' => t('- Select a widget -'),
-          '#description' => t('Form element to edit the data.'),
-          '#attributes' => array('class' => array('widget-type-select')),
           '#cell_attributes' => array('colspan' => 3),
           '#prefix' => '<div class="add-new-placeholder">&nbsp;</div>',
         ),
       );
     }
-    $form['fields'] = $table;
 
-    // Add AJAX wrapper.
-    $form['fields']['#prefix'] = '<div id="field-display-overview-wrapper">';
-    $form['fields']['#suffix'] = '</div>';
+    // We can set the 'rows_order' element, needed by theme_field_ui_table(),
+    // here instead of a #pre_render callback because this form doesn't have the
+    // tabledrag behavior anymore.
+    foreach (element_children($table) as $name) {
+      $table['#regions']['content']['rows_order'][] = $name;
+    }
 
-    // This key is used to store the current updated field.
-    $form_state += array(
-      'formatter_settings_edit' => NULL,
-    );
+    $form['fields'] = $table;
 
     $form['actions'] = array('#type' => 'actions');
     $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save'));
 
-    $form['#attached']['library'][] = array('field_ui', 'drupal.field_ui');
-
-    // Add settings for the update selects behavior.
-    $js_fields = array();
-    foreach ($existing_fields as $field_name => $info) {
-      $js_fields[$field_name] = array('label' => $info['label'], 'type' => $info['type'], 'widget' => $info['widget_type']);
-    }
-
-    $form['#attached']['js'][] = array(
-      'type' => 'setting',
-      'data' => array('fields' => $js_fields, 'fieldWidgetTypes' => $widget_options),
-    );
-
-    // Add tabledrag behavior.
-    $form['#attached']['drupal_add_tabledrag'][] = array('field-overview', 'order', 'sibling', 'field-weight');
-    $form['#attached']['drupal_add_tabledrag'][] = array('field-overview', 'match', 'parent', 'field-parent', 'field-parent', 'field-name');
-
     return $form;
   }
 
   /**
-   * Implements \Drupal\Core\Form\FormInterface::validateForm().
+   * {@inheritdoc}
    */
   public function validateForm(array &$form, array &$form_state) {
     $this->validateAddNew($form, $form_state);
@@ -493,7 +266,7 @@ protected function validateAddNew(array $form, array &$form_state) {
     $field = $form_state['values']['fields']['_add_new_field'];
 
     // Validate if any information was provided in the 'add new field' row.
-    if (array_filter(array($field['label'], $field['field_name'], $field['type'], $field['widget_type']))) {
+    if (array_filter(array($field['label'], $field['field_name'], $field['type']))) {
       // Missing label.
       if (!$field['label']) {
         form_set_error('fields][_add_new_field][label', t('Add new field: you need to provide a label.'));
@@ -516,18 +289,6 @@ protected function validateAddNew(array $form, array &$form_state) {
       if (!$field['type']) {
         form_set_error('fields][_add_new_field][type', t('Add new field: you need to select a field type.'));
       }
-
-      // Missing widget type.
-      if (!$field['widget_type']) {
-        form_set_error('fields][_add_new_field][widget_type', t('Add new field: you need to select a widget.'));
-      }
-      // Wrong widget type.
-      elseif ($field['type']) {
-        $widget_types = $this->widgetManager->getOptions($field['type']);
-        if (!isset($widget_types[$field['widget_type']])) {
-          form_set_error('fields][_add_new_field][widget_type', t('Add new field: invalid widget.'));
-        }
-      }
     }
   }
 
@@ -549,7 +310,7 @@ protected function validateAddExisting(array $form, array &$form_state) {
 
       // Validate if any information was provided in the
       // 're-use existing field' row.
-      if (array_filter(array($field['label'], $field['field_name'], $field['widget_type']))) {
+      if (array_filter(array($field['label'], $field['field_name']))) {
         // Missing label.
         if (!$field['label']) {
           form_set_error('fields][_add_existing_field][label', t('Re-use existing field: you need to provide a label.'));
@@ -559,18 +320,6 @@ protected function validateAddExisting(array $form, array &$form_state) {
         if (!$field['field_name']) {
           form_set_error('fields][_add_existing_field][field_name', t('Re-use existing field: you need to select a field.'));
         }
-
-        // Missing widget type.
-        if (!$field['widget_type']) {
-          form_set_error('fields][_add_existing_field][widget_type', t('Re-use existing field: you need to select a widget.'));
-        }
-        // Wrong widget type.
-        elseif ($field['field_name'] && ($existing_field = field_info_field($field['field_name']))) {
-          $widget_types = $this->widgetManager->getOptions($existing_field['type']);
-          if (!isset($widget_types[$field['widget_type']])) {
-            form_set_error('fields][_add_existing_field][widget_type', t('Re-use existing field: invalid widget.'));
-          }
-        }
       }
     }
   }
@@ -580,26 +329,6 @@ protected function validateAddExisting(array $form, array &$form_state) {
    */
   public function submitForm(array &$form, array &$form_state) {
     $form_values = $form_state['values']['fields'];
-    $entity_form_display = entity_get_form_display($this->entity_type, $this->bundle, $this->mode);
-
-    // Collect data for 'regular' fields.
-    foreach ($form['#fields'] as $field_name) {
-      $options = $entity_form_display->getComponent($field_name);
-      $options['weight'] = $form_values[$field_name]['weight'];
-
-      $entity_form_display->setComponent($field_name, $options);
-    }
-
-    // Collect data for 'extra' fields.
-    foreach ($form['#extra'] as $field_name) {
-      $entity_form_display->setComponent($field_name, array(
-        'weight' => $form_values[$field_name]['weight'],
-      ));
-    }
-
-    // Save the form display.
-    $entity_form_display->save();
-
     $destinations = array();
 
     // Create new field.
@@ -625,12 +354,10 @@ public function submitForm(array &$form, array &$form_state) {
         $new_instance->save();
 
         // Make sure the field is displayed in the 'default' form mode (using
-        // the configured widget and default settings).
+        // default widget and settings). It stays hidden for other form modes
+        // until it is explicitly configured.
         entity_get_form_display($this->entity_type, $this->bundle, 'default')
-          ->setComponent($field['field_name'], array(
-            'type' => $values['widget_type'],
-            'weight' => $values['weight'],
-          ))
+          ->setComponent($field['field_name'])
           ->save();
 
         // Make sure the field is displayed in the 'default' view mode (using
@@ -673,12 +400,10 @@ public function submitForm(array &$form, array &$form_state) {
           $new_instance->save();
 
           // Make sure the field is displayed in the 'default' form mode (using
-          // the configured widget and default settings).
+          // default widget and settings). It stays hidden for other form modes
+          // until it is explicitly configured.
           entity_get_form_display($this->entity_type, $this->bundle, 'default')
-            ->setComponent($field['field_name'], array(
-              'type' => $values['widget_type'],
-              'weight' => $values['weight'],
-            ))
+            ->setComponent($field['field_name'])
             ->save();
 
           // Make sure the field is displayed in the 'default' view mode (using
@@ -712,27 +437,6 @@ public function submitForm(array &$form, array &$form_state) {
     }
   }
 
-  /**
-   * Returns the region to which a row in the display overview belongs.
-   *
-   * @param array $row
-   *   The row element.
-   *
-   * @return string|null
-   *   The region name this row belongs to.
-   */
-  public function getRowRegion($row) {
-    switch ($row['#row_type']) {
-      case 'field':
-      case 'extra_field':
-        return 'content';
-      case 'add_new_field':
-        // If no input in 'label', assume the row has not been dragged out of the
-        // 'add new' section.
-        return (!empty($row['label']['#value']) ? 'content' : 'hidden');
-    }
-  }
-
   /**
    * Returns an array of existing fields to be added to a bundle.
    *
@@ -759,13 +463,11 @@ protected function getExistingFieldOptions() {
               && !field_info_instance($this->entity_type, $field['field_name'], $this->bundle)
               && (empty($field['entity_types']) || in_array($this->entity_type, $field['entity_types']))
               && empty($field_types[$field['type']]['no_ui'])) {
-              $widget = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($instance['field_name']);
               $info[$instance['field_name']] = array(
                 'type' => $field['type'],
                 'type_label' => $field_types[$field['type']]['label'],
                 'field' => $field['field_name'],
                 'label' => $instance['label'],
-                'widget_type' => $widget['type'],
               );
             }
           }
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php
index 16ab117dd6f3e68bebcdec1d2bdeb1aab3e4ad8e..26264ac0e7c686f01707198ceb70817c4ee99f6e 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php
@@ -103,11 +103,6 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['instance']['settings'] = $this->getFieldItem($form['#entity'], $this->instance['field_name'])->instanceSettingsForm($form, $form_state);
     $form['instance']['settings']['#weight'] = 10;
 
-    // Add widget settings for the widget type.
-    $additions = $entity_form_display->getWidget($this->instance->getField()->id)->settingsForm($form, $form_state);
-    $form['instance']['widget']['settings'] = $additions ?: array('#type' => 'value', '#value' => array());
-    $form['instance']['widget']['#weight'] = 20;
-
     // Add handling for default value if not provided by any other module.
     if (field_behaviors_widget('default_value', $this->instance) == FIELD_BEHAVIOR_DEFAULT && empty($this->instance['default_value_function'])) {
       $form['instance']['default_value_widget'] = $this->getDefaultValueWidget($field, $form, $form_state);
@@ -141,7 +136,7 @@ public function validateForm(array &$form, array &$form_state) {
 
       // Extract the 'default value'.
       $items = array();
-      $entity_form_display->getWidget($this->instance->getField()->id)->extractFormValues($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
+      $entity_form_display->getRenderer($this->instance->getField()->id)->extractFormValues($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
 
       // @todo Simplify when all entity types are converted to EntityNG.
       if ($entity instanceof EntityNG) {
@@ -165,7 +160,7 @@ public function validateForm(array &$form, array &$form_state) {
         field_form_set_state($element['#parents'], $field_name, Language::LANGCODE_NOT_SPECIFIED, $form_state, $field_state);
 
         // Assign reported errors to the correct form element.
-        $entity_form_display->getWidget($this->instance->getField()->id)->flagErrors($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
+        $entity_form_display->getRenderer($this->instance->getField()->id)->flagErrors($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
       }
     }
   }
@@ -183,17 +178,11 @@ public function submitForm(array &$form, array &$form_state) {
 
       // Extract field values.
       $items = array();
-      $entity_form_display->getWidget($this->instance->getField()->id)->extractFormValues($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
+      $entity_form_display->getRenderer($this->instance->getField()->id)->extractFormValues($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
 
       $this->instance['default_value'] = $items ? $items : NULL;
     }
 
-    // Handle widget settings.
-    $options = $entity_form_display->getComponent($this->instance->getField()->id);
-    $options['settings'] = $form_state['values']['instance']['widget']['settings'];
-    $entity_form_display->setComponent($this->instance->getField()->id, $options)->save();
-    unset($form_state['values']['instance']['widget']);
-
     // Merge incoming values into the instance.
     foreach ($form_state['values']['instance'] as $key => $value) {
       $this->instance[$key] = $value;
@@ -202,10 +191,6 @@ public function submitForm(array &$form, array &$form_state) {
 
     drupal_set_message(t('Saved %label configuration.', array('%label' => $this->instance->label())));
 
-    if ($this->instance['required'] && empty($this->instance['default_value']) && empty($this->instance['default_value_function']) && $this->instance['widget']['type'] == 'field_hidden') {
-      drupal_set_message(t('Field %label is required and uses the "hidden" widget. You might want to configure a default value.', array('%label' => $this->instance['label'])), 'warning');
-    }
-
     $form_state['redirect'] = $this->getNextDestination();
   }
 
@@ -246,7 +231,9 @@ protected function getDefaultValueWidget($field, array &$form, &$form_state) {
 
     // Adjust the instance definition to use the default widget of this field type
     // instead of the hidden widget.
-    if ($this->instance['widget']['type'] == 'field_hidden') {
+    // @todo Clean this up since we don't have $this->instance['widget'] anymore.
+    //   see https://drupal.org/node/2028759
+    if ($this->instance['widget']['type'] == 'hidden') {
       $field_type = field_info_field_types($field['type']);
       $default_widget = $this->widgetManager->getDefinition($field_type['default_widget']);
 
@@ -263,7 +250,7 @@ protected function getDefaultValueWidget($field, array &$form, &$form_state) {
     if (!empty($this->instance['default_value'])) {
       $items = (array) $this->instance['default_value'];
     }
-    $element += $entity_form_display->getWidget($this->instance->getField()->id)->form($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
+    $element += $entity_form_display->getRenderer($this->instance->getField()->id)->form($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
 
     return $element;
   }
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldWidgetTypeForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldWidgetTypeForm.php
deleted file mode 100644
index 4f449470ad8fd3552b99ad29100229e76ed5b1ef..0000000000000000000000000000000000000000
--- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldWidgetTypeForm.php
+++ /dev/null
@@ -1,99 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\field_ui\Form\FieldWidgetTypeForm.
- */
-
-namespace Drupal\field_ui\Form;
-
-use Drupal\field\FieldInstanceInterface;
-
-/**
- * Provides a form for the widget selection form.
- */
-class FieldWidgetTypeForm extends FieldInstanceFormBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getFormID() {
-    return 'field_ui_widget_type_form';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildForm(array $form, array &$form_state, FieldInstanceInterface $field_instance = NULL) {
-    parent::buildForm($form, $form_state, $field_instance);
-
-    drupal_set_title($this->instance['label']);
-
-    $bundle = $this->instance['bundle'];
-    $entity_type = $this->instance['entity_type'];
-    $field_name = $this->instance['field_name'];
-
-    $entity_form_display = entity_get_form_display($entity_type, $bundle, 'default');
-    $field = $this->instance->getField();
-    $bundles = entity_get_bundles();
-    $bundle_label = $bundles[$entity_type][$bundle]['label'];
-
-    $form = array(
-      '#bundle' => $bundle,
-      '#entity_type' => $entity_type,
-      '#field_name' => $field_name,
-      '#instance' => $this->instance,
-    );
-
-    $form['widget_type'] = array(
-      '#type' => 'select',
-      '#title' => t('Widget type'),
-      '#required' => TRUE,
-      '#options' => $this->widgetManager->getOptions($field['type']),
-      '#default_value' => $entity_form_display->getWidget($field_name)->getPluginId(),
-      '#description' => t('The type of form element you would like to present to the user when creating this field in the %type type.', array('%type' => $bundle_label)),
-    );
-
-    $form['actions'] = array('#type' => 'actions');
-    $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Continue'));
-
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validateForm(array &$form, array &$form_state) {
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function submitForm(array &$form, array &$form_state) {
-    $form_values = $form_state['values'];
-    $bundle = $form['#bundle'];
-    $entity_type = $form['#entity_type'];
-    $field_name = $form['#field_name'];
-    $instance = $form['#instance'];
-
-    $entity_form_display = entity_get_form_display($entity_type, $bundle, 'default')
-      ->setComponent($field_name, array(
-        'type' => $form_values['widget_type'],
-      ));
-
-    try {
-      $entity_form_display->save();
-      drupal_set_message(t('Changed the widget for field %label.', array('%label' => $instance['label'])));
-
-      if ($instance['required'] && empty($instance['default_value']) && empty($instance['default_value_function']) && $instance['widget']['type'] == 'field_hidden') {
-        drupal_set_message(t('Field %label is required and uses the "hidden" widget. You might want to configure a default value.', array('%label' => $instance['label'])), 'warning');
-      }
-    }
-    catch (\Exception $e) {
-      drupal_set_message(t('There was a problem changing the widget for field %label.', array('%label' => $instance['label'])), 'error');
-    }
-
-    $form_state['redirect'] = $this->getNextDestination();
-  }
-
-}
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FormDisplayOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/FormDisplayOverview.php
new file mode 100644
index 0000000000000000000000000000000000000000..d2ab86a19477f188ef94ff1dc7459ca7815ed171
--- /dev/null
+++ b/core/modules/field_ui/lib/Drupal/field_ui/FormDisplayOverview.php
@@ -0,0 +1,161 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field_ui\FormDisplayOverview.
+ */
+
+namespace Drupal\field_ui;
+
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Controller\ControllerInterface;
+use Drupal\entity\EntityDisplayBaseInterface;
+use Drupal\field\FieldInstanceInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Field UI form display overview form.
+ */
+class FormDisplayOverview extends DisplayOverviewBase implements ControllerInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('plugin.manager.entity'),
+      $container->get('plugin.manager.field.widget')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormID() {
+    return 'field_ui_form_display_overview_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function buildFieldRow($field_id, FieldInstanceInterface $instance, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) {
+    $field_row = parent::buildFieldRow($field_id, $instance, $entity_display, $form, $form_state);
+
+    // Update the (invisible) title of the 'plugin' column.
+    $field_row['plugin']['#title'] = t('Formatter for @title', array('@title' => $instance['label']));
+    if (!empty($field_row['plugin']['settings_edit_form']) && ($plugin = $entity_display->getRenderer($field_id))) {
+      $plugin_type_info = $plugin->getPluginDefinition();
+      $field_row['plugin']['settings_edit_form']['label']['#markup'] = t('Widget settings:') . ' <span class="plugin-name">' . $plugin_type_info['label'] . '</span>';
+    }
+
+    return $field_row;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEntityDisplay($mode) {
+    return entity_get_form_display($this->entity_type, $this->bundle, $mode);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getExtraFields() {
+    return field_info_extra_fields($this->entity_type, $this->bundle, 'form');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getPlugin($instance, $configuration) {
+    $plugin = NULL;
+
+    if ($configuration && $configuration['type'] != 'hidden') {
+      $plugin = $this->pluginManager->getInstance(array(
+        'field_definition' => $instance,
+        'form_mode' => $this->mode,
+        'configuration' => $configuration
+      ));
+    }
+
+    return $plugin;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getDefaultPlugin($field_type) {
+    return $this->fieldTypes[$field_type]['default_widget'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getDisplayModes() {
+    return entity_get_form_modes($this->entity_type);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getDisplayModeSettings() {
+    return field_form_mode_settings($this->entity_type, $this->bundle);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function saveDisplayModeSettings($display_mode_settings) {
+    $bundle_settings = field_bundle_settings($this->entity_type, $this->bundle);
+    $bundle_settings['form_modes'] = NestedArray::mergeDeep($bundle_settings['form_modes'], $display_mode_settings);
+    field_bundle_settings($this->entity_type, $this->bundle, $bundle_settings);
+  }
+
+  /**
+   * {@inheritdoc
+   */
+  protected function getTableHeader() {
+    return array(
+      t('Field'),
+      t('Weight'),
+      t('Parent'),
+      array('data' => t('Widget'), 'colspan' => 3),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getOverviewPath($mode) {
+    return $this->entityManager->getAdminPath($this->entity_type, $this->bundle) . "/form-display/$mode";
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function alterSettingsForm(array &$settings_form, $plugin, FieldInstanceInterface $instance, array $form, array &$form_state) {
+    $context = array(
+      'widget' => $plugin,
+      'field' => $instance->getField(),
+      'instance' => $instance,
+      'form_mode' => $this->mode,
+      'form' => $form,
+    );
+    drupal_alter('field_widget_settings_form', $settings_form, $form_state, $context);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function alterSettingsSummary(array &$summary, $plugin, FieldInstanceInterface $instance) {
+    $context = array(
+      'widget' => $plugin,
+      'field' => $instance->getField(),
+      'instance' => $instance,
+      'form_mode' => $this->mode,
+    );
+    drupal_alter('field_widget_settings_summary', $summary, $context);
+  }
+
+}
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php b/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php
index ecf8de4b5405434385a1c412f448e02c8276795f..67b742b79891e5f1be1b44fb38e734755ef8640c 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php
@@ -83,6 +83,11 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
     $this->entity_type = $entity_type;
     $this->bundle = $bundle;
     $this->adminPath = $this->entityManager->getAdminPath($this->entity_type, $this->bundle);
+
+    // When displaying the form, make sure the list of fields is up-to-date.
+    if (empty($form_state['post'])) {
+      field_info_cache_clear();
+    }
   }
 
   /**
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php b/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php
index 55477a045750cfb89376afcee92d60303a77fe49..e994202ec1bbc4950c7bc8c3026551600153b4ac 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php
@@ -67,13 +67,6 @@ public function routes(RouteBuildEvent $event) {
         );
         $collection->add("field_ui.field_edit.$entity_type", $route);
 
-        $route = new Route(
-          "$path/fields/{field_instance}/widget-type",
-          array('_form' => '\Drupal\field_ui\Form\FieldWidgetTypeForm'),
-          array('_permission' => 'administer ' . $entity_type . ' fields')
-        );
-        $collection->add("field_ui.widget_type.$entity_type", $route);
-
         $route = new Route(
           "$path/fields/{field_instance}/delete",
           array('_entity_form' => 'field_instance.delete'),
@@ -93,6 +86,24 @@ public function routes(RouteBuildEvent $event) {
         );
         $collection->add("field_ui.overview.$entity_type", $route);
 
+        $route = new Route(
+          "$path/form-display",
+          array('_form' => '\Drupal\field_ui\FormDisplayOverview') + $defaults,
+          array('_permission' => 'administer ' . $entity_type . ' form display')
+        );
+        $collection->add("field_ui.form_display_overview.$entity_type", $route);
+
+        foreach (entity_get_form_modes($entity_type) as $form_mode => $form_mode_info) {
+          $route = new Route(
+            "$path/form-display/$form_mode",
+            array(
+              '_form' => '\Drupal\field_ui\FormDisplayOverview',
+              'mode' => $form_mode,
+            ) + $defaults,
+            array('_field_ui_form_mode_access' => 'administer ' . $entity_type . ' form display'));
+          $collection->add("field_ui.form_display_overview.$entity_type.$form_mode", $route);
+        }
+
         $route = new Route(
           "$path/display",
           array('_form' => '\Drupal\field_ui\DisplayOverview') + $defaults,
@@ -105,7 +116,7 @@ public function routes(RouteBuildEvent $event) {
             "$path/display/$view_mode",
             array(
               '_form' => '\Drupal\field_ui\DisplayOverview',
-              'view_mode' => $view_mode,
+              'mode' => $view_mode,
             ) + $defaults,
             array('_field_ui_view_mode_access' => 'administer ' . $entity_type . ' display'));
           $collection->add("field_ui.display_overview.$entity_type.$view_mode", $route);
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUIRouteTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUIRouteTest.php
index 32d2a7180cdf14cd3004a97bc25189fcb7277c94..669b58e999920e9db7aacb5adb13aef316f2ecde 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUIRouteTest.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUIRouteTest.php
@@ -46,7 +46,9 @@ public function setUp() {
    */
   public function testFieldUIRoutes() {
     $this->drupalGet('field-ui-test-no-bundle/manage/fields');
-    $this->assertText('No fields are present yet.');
+    // @todo Bring back this assertion in https://drupal.org/node/1963340.
+    // @see \Drupal\field_ui\FieldOverview::getRegions()
+    //$this->assertText('No fields are present yet.');
 
     $this->drupalGet('admin/structure/types/manage/article/fields');
     $this->assertTitle('Article | Drupal');
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php
index bc44cbd599c6a068e7907f8467d0d92b20b4d3e3..c8360236862a45d65215a92fbce65c9b4c32f25f 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php
@@ -26,7 +26,7 @@ function setUp() {
     parent::setUp();
 
     // Create test user.
-    $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer node fields', 'administer node display', 'administer taxonomy', 'administer taxonomy_term fields', 'administer taxonomy_term display', 'administer users', 'administer user display', 'bypass node access'));
+    $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer node fields', 'administer node form display', 'administer node display', 'administer taxonomy', 'administer taxonomy_term fields', 'administer taxonomy_term display', 'administer users', 'administer user display', 'bypass node access'));
     $this->drupalLogin($admin_user);
 
     // Create content type, with underscores.
@@ -67,10 +67,8 @@ function fieldUIAddNewField($bundle_path, $initial_edit, $field_edit = array(),
     // Use 'test_field' field type by default.
     $initial_edit += array(
       'fields[_add_new_field][type]' => 'test_field',
-      'fields[_add_new_field][widget_type]' => 'test_field_widget',
     );
     $label = $initial_edit['fields[_add_new_field][label]'];
-    $field_name = $initial_edit['fields[_add_new_field][field_name]'];
 
     // First step : 'Add new field' on the 'Manage fields' page.
     $this->drupalPost("$bundle_path/fields",  $initial_edit, t('Save'));
@@ -101,12 +99,7 @@ function fieldUIAddNewField($bundle_path, $initial_edit, $field_edit = array(),
    *   form).
    */
   function fieldUIAddExistingField($bundle_path, $initial_edit, $instance_edit = array()) {
-    // Use 'test_field_widget' by default.
-    $initial_edit += array(
-      'fields[_add_existing_field][widget_type]' => 'test_field_widget',
-    );
     $label = $initial_edit['fields[_add_existing_field][label]'];
-    $field_name = $initial_edit['fields[_add_existing_field][field_name]'];
 
     // First step : 'Re-use existing field' on the 'Manage fields' page.
     $this->drupalPost("$bundle_path/fields", $initial_edit, t('Save'));
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php
index c643cd0ffa4cbbe23ce2c05f5550e7194c317307..a5d8790ba8c05d97d7c406c81eef6577f93d93b7 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php
@@ -24,7 +24,7 @@ class ManageDisplayTest extends FieldUiTestBase {
   public static function getInfo() {
     return array(
       'name' => 'Manage display',
-      'description' => 'Test the Field UI "Manage display" screens.',
+      'description' => 'Test the Field UI "Manage display" and "Manage form display" screens.',
       'group' => 'Field UI',
     );
   }
@@ -81,17 +81,82 @@ function testFormatterUI() {
 
     // Click on the formatter settings button to open the formatter settings
     // form.
-    $this->drupalPostAJAX(NULL, array(), "field_test_formatter_settings_edit");
+    $this->drupalPostAJAX(NULL, array(), "field_test_settings_edit");
 
     // Assert that the field added in
     // field_test_field_formatter_settings_form_alter() is present.
     $fieldname = 'fields[field_test][settings_edit_form][settings][field_test_formatter_settings_form_alter]';
     $this->assertField($fieldname, 'The field added in hook_field_formatter_settings_form_alter() is present on the settings form.');
     $edit = array($fieldname => 'foo');
-    $this->drupalPostAJAX(NULL, $edit, "field_test_formatter_settings_update");
+    $this->drupalPostAJAX(NULL, $edit, "field_test_plugin_settings_update");
 
     // Confirm that the settings are updated on the settings form.
-    $this->drupalPostAJAX(NULL, array(), "field_test_formatter_settings_edit");
+    $this->drupalPostAJAX(NULL, array(), "field_test_settings_edit");
+    $this->assertFieldByName($fieldname, 'foo');
+  }
+
+  /**
+   * Tests widget settings.
+   */
+  public function testWidgetUI() {
+    $manage_fields = 'admin/structure/types/manage/' . $this->type;
+    $manage_display = $manage_fields . '/form-display';
+
+    // Create a field, and a node with some data for the field.
+    $edit = array(
+      'fields[_add_new_field][label]' => 'Test field',
+      'fields[_add_new_field][field_name]' => 'test',
+    );
+    $this->fieldUIAddNewField($manage_fields, $edit);
+
+    // Clear the test-side cache and get the saved field instance.
+    $display = entity_get_form_display('node', $this->type, 'default');
+    $display_options = $display->getComponent('field_test');
+    $widget_type = $display_options['type'];
+    $default_settings = field_info_widget_settings($widget_type);
+    $setting_name = key($default_settings);
+    $setting_value = $display_options['settings'][$setting_name];
+
+    // Display the "Manage form display" screen and check that the expected
+    // widget is selected.
+    $this->drupalGet($manage_display);
+    $this->assertFieldByName('fields[field_test][type]', $widget_type, 'The expected widget is selected.');
+    $this->assertText("$setting_name: $setting_value", 'The expected summary is displayed.');
+
+    // Change the widget and check that the summary is updated.
+    $edit = array('fields[field_test][type]' => 'test_field_widget_multiple', 'refresh_rows' => 'field_test');
+    $this->drupalPostAJAX(NULL, $edit, array('op' => t('Refresh')));
+    $widget_type = 'test_field_widget_multiple';
+    $default_settings = field_info_widget_settings($widget_type);
+    $setting_name = key($default_settings);
+    $setting_value = $default_settings[$setting_name];
+    $this->assertFieldByName('fields[field_test][type]', $widget_type, 'The expected widget is selected.');
+    $this->assertText("$setting_name: $setting_value", 'The expected summary is displayed.');
+
+    // Submit the form and check that the display is updated.
+    $this->drupalPost(NULL, array(), t('Save'));
+    $display = entity_get_form_display('node', $this->type, 'default');
+    $display_options = $display->getComponent('field_test');
+    $current_widget = $display_options['type'];
+    $current_setting_value = $display_options['settings'][$setting_name];
+    $this->assertEqual($current_widget, $widget_type, 'The widget was updated.');
+    $this->assertEqual($current_setting_value, $setting_value, 'The setting was updated.');
+
+    // Assert that hook_field_widget_settings_summary_alter() is called.
+    $this->assertText('field_test_field_widget_settings_summary_alter');
+
+    // Click on the widget settings button to open the widget settings form.
+    $this->drupalPostAJAX(NULL, array(), "field_test_settings_edit");
+
+    // Assert that the field added in
+    // field_test_field_widget_settings_form_alter() is present.
+    $fieldname = 'fields[field_test][settings_edit_form][settings][field_test_widget_settings_form_alter]';
+    $this->assertField($fieldname, 'The field added in hook_field_widget_settings_form_alter() is present on the settings form.');
+    $edit = array($fieldname => 'foo');
+    $this->drupalPostAJAX(NULL, $edit, "field_test_plugin_settings_update");
+
+    // Confirm that the settings are updated on the settings form.
+    $this->drupalPostAJAX(NULL, array(), "field_test_settings_edit");
     $this->assertFieldByName($fieldname, 'foo');
   }
 
@@ -137,7 +202,7 @@ function testViewModeCustom() {
 
     // Specialize the 'rss' mode, check that the field is displayed the same.
     $edit = array(
-      "view_modes_custom[rss]" => TRUE,
+      "display_modes_custom[rss]" => TRUE,
     );
     $this->drupalPost('admin/structure/types/manage/' . $this->type . '/display', $edit, t('Save'));
     $this->assertNodeViewText($node, 'rss', $output['field_test_with_prepare_view'], "The field is displayed as expected in newly specialized 'rss' mode.");
@@ -153,14 +218,14 @@ function testViewModeCustom() {
     // Set the view mode back to 'default', check that the field is displayed
     // accordingly.
     $edit = array(
-      "view_modes_custom[rss]" => FALSE,
+      "display_modes_custom[rss]" => FALSE,
     );
     $this->drupalPost('admin/structure/types/manage/' . $this->type . '/display', $edit, t('Save'));
     $this->assertNodeViewText($node, 'rss', $output['field_test_with_prepare_view'], "The field is displayed as expected when 'rss' mode is set back to 'default' settings.");
 
     // Specialize the view mode again.
     $edit = array(
-      "view_modes_custom[rss]" => TRUE,
+      "display_modes_custom[rss]" => TRUE,
     );
     $this->drupalPost('admin/structure/types/manage/' . $this->type . '/display', $edit, t('Save'));
     // Check that the previous settings for the view mode have been kept.
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
index 56370add8a1dc9cd95a252e9f51f80f84f6143ce..cd7037f9908921c4272c2ecbab37ed14f6e49887 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
@@ -89,7 +89,6 @@ function manageFieldsPage($type = '') {
       t('Label'),
       t('Machine name'),
       t('Field type'),
-      t('Widget'),
       t('Operations'),
     );
     foreach ($table_headers as $table_header) {
@@ -145,7 +144,6 @@ function updateField() {
     $this->drupalGet('admin/structure/types/manage/' . $this->type . '/fields/' . $instance_id);
     $edit = array(
       'instance[settings][test_instance_setting]' => $string,
-      'instance[widget][settings][test_widget_setting]' => $string,
     );
     $this->drupalPost(NULL, $edit, t('Save settings'));
 
@@ -236,13 +234,9 @@ function assertFieldSettings($bundle, $field_name, $string = 'dummy test string'
     $field = field_info_field($field_name);
     $this->assertTrue($field['settings']['test_field_setting'] == $string, 'Field settings were found.');
 
-    // Assert instance and widget settings.
+    // Assert instance settings.
     $instance = field_info_instance($entity_type, $field_name, $bundle);
     $this->assertTrue($instance['settings']['test_instance_setting'] == $string, 'Field instance settings were found.');
-
-    // Assert widget settings.
-    $widget_configuration = entity_get_form_display($entity_type, $bundle, 'default')->getComponent($field_name);
-    $this->assertTrue($widget_configuration['settings']['test_widget_setting'] == $string, 'Field widget settings were found.');
   }
 
   /**
@@ -411,11 +405,11 @@ function testLockedField() {
 
     // Check that the links for edit and delete are not present.
     $this->drupalGet('admin/structure/types/manage/' . $this->type . '/fields');
-    $locked = $this->xpath('//tr[@id=:field_name]/td[7]', array(':field_name' => $field->id()));
+    $locked = $this->xpath('//tr[@id=:field_name]/td[4]', array(':field_name' => $field->id()));
     $this->assertTrue(in_array('Locked', $locked), 'Field is marked as Locked in the UI');
-    $edit_link = $this->xpath('//tr[@id=:field_name]/td[7]', array(':field_name' => $field->id()));
+    $edit_link = $this->xpath('//tr[@id=:field_name]/td[4]', array(':field_name' => $field->id()));
     $this->assertFalse(in_array('edit', $edit_link), 'Edit option for locked field is not present the UI');
-    $delete_link = $this->xpath('//tr[@id=:field_name]/td[8]', array(':field_name' => $field->id()));
+    $delete_link = $this->xpath('//tr[@id=:field_name]/td[4]', array(':field_name' => $field->id()));
     $this->assertFalse(in_array('delete', $delete_link), 'Delete option for locked field is not present the UI');
   }
 
@@ -454,15 +448,6 @@ function testHiddenFields() {
     $bundle_path = 'admin/structure/types/manage/article/fields/';
     $this->drupalGet($bundle_path);
     $this->assertFalse($this->xpath('//select[@id="edit-add-existing-field-field-name"]//option[@value=:field_name]', array(':field_name' => $field_name)), "The 're-use existing field' select respects field types 'no_ui' property.");
-
-    // Remove the form display component to check the fallback label.
-    entity_get_form_display('node', $this->type, 'default')
-      ->removeComponent($field_name)
-      ->save();
-
-    $this->drupalGet('admin/structure/types/manage/' . $this->type . '/fields/');
-    $this->assertLinkByHref(url('admin/structure/types/manage/' . $this->type . '/fields/node.' . $this->type . '.'  . $field_name . '/widget-type'));
-    $this->assertLink('- Hidden -');
   }
 
   /**
@@ -488,7 +473,6 @@ function testDuplicateFieldName() {
       'fields[_add_new_field][field_name]' => 'tags',
       'fields[_add_new_field][label]' => $this->randomName(),
       'fields[_add_new_field][type]' => 'taxonomy_term_reference',
-      'fields[_add_new_field][widget_type]' => 'options_select',
     );
     $url = 'admin/structure/types/manage/' . $this->type . '/fields';
     $this->drupalPost($url, $edit, t('Save'));
@@ -497,49 +481,6 @@ function testDuplicateFieldName() {
     $this->assertUrl($url, array(), 'Stayed on the same page.');
   }
 
-  /**
-   * Tests changing the widget used by a field.
-   */
-  function testWidgetChange() {
-    $url_fields = 'admin/structure/types/manage/article/fields';
-    $url_tags_widget = $url_fields . '/node.article.field_tags/widget-type';
-
-    // Check that the field_tags field currently uses the 'options_select'
-    // widget.
-    $entity_form_display = entity_get_form_display('node', 'article', 'default')->getComponent('field_tags');
-    $this->assertEqual($entity_form_display['type'], 'options_select');
-
-    // Check that the "Manage fields" page shows the correct widget type.
-    $this->drupalGet($url_fields);
-    $link = current($this->xpath('//a[contains(@href, :href)]', array(':href' => $url_tags_widget)));
-    $this->assertEqual((string) $link, 'Select list');
-
-    // Go to the 'Widget type' form and check that the correct widget is
-    // selected.
-    $this->drupalGet($url_tags_widget);
-    $this->assertFieldByXPath("//select[@name='widget_type']", 'options_select');
-
-    // Change the widget type.
-    $edit = array(
-      'widget_type' => 'options_buttons',
-    );
-    $this->drupalPost(NULL, $edit, t('Continue'));
-
-    // Check that the "Manage fields" page shows the correct widget type.
-    $link = current($this->xpath('//a[contains(@href, :href)]', array(':href' => $url_tags_widget)));
-    $this->assertEqual((string) $link, 'Check boxes/radio buttons');
-
-    // Check that the field uses the newly set widget.
-    field_cache_clear();
-    $widget_configuration = entity_get_form_display('node', 'article', 'default')->getComponent('field_tags');
-    $this->assertEqual($widget_configuration['type'], 'options_buttons');
-
-    // Go to the 'Widget type' form and check that the correct widget is
-    // selected.
-    $this->drupalGet($url_tags_widget);
-    $this->assertFieldByXPath("//select[@name='widget_type']", 'options_buttons');
-  }
-
   /**
    * Tests that deletion removes fields and instances as expected for a term.
    */
diff --git a/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php b/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php
index c63df17266ddda94600ab9c6b91783099956503b..63564fa509e13d0f302afae45946b49f620881e7 100644
--- a/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php
+++ b/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php
@@ -51,6 +51,15 @@ public function settingsForm(array $form, array &$form_state) {
 
   /**
    * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+    $summary[] = t('Progress indicator: @progress_indicator', array('@progress_indicator' => $this->getSetting('progress_indicator')));
+    return $summary;
+  }
+
+  /**
+   * Overrides \Drupal\field\Plugin\Type\Widget\WidgetBase::formMultipleElements().
    *
    * Special handling for draggable multiple widgets and 'add more' button.
    */
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldRSSContentTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldRSSContentTest.php
index 7847a16b114079850206c882552075a1433ec5db..e241deaa97133e99be20d888b07ff5a125be1d6a 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileFieldRSSContentTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldRSSContentTest.php
@@ -48,7 +48,7 @@ function testFileFieldRSSContent() {
     // RSS display must be added manually.
     $this->drupalGet("admin/structure/types/manage/$type_name/display");
     $edit = array(
-      "view_modes_custom[rss]" => '1',
+      "display_modes_custom[rss]" => '1',
     );
     $this->drupalPost(NULL, $edit, t('Save'));
 
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php
index 2389423620e712ffdff17c8ad025d53958012dfa..2267b1a2c4573ecd5f2de2b6527f4f4650bdb97b 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php
@@ -253,7 +253,6 @@ function testPrivateFileComment() {
       'fields[_add_new_field][label]' => $label = $this->randomName(),
       'fields[_add_new_field][field_name]' => $name = strtolower($this->randomName()),
       'fields[_add_new_field][type]' => 'file',
-      'fields[_add_new_field][widget_type]' => 'file_generic',
     );
     $this->drupalPost('admin/structure/types/manage/article/comment/fields', $edit, t('Save'));
     $edit = array('field[settings][uri_scheme]' => 'private');
diff --git a/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php b/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php
index 3ad6e0f8e60dc64e0d146e18ec5ca7345546e182..d0ae8facfccebb0cc7b2a777c2e5752aa93cfb52 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php
@@ -33,7 +33,7 @@
 class ImageWidget extends FileWidget {
 
   /**
-   * Overrides \Drupal\file\Plugin\field\widget\FileWidget::settingsForm().
+   * {@inheritdoc}
    */
   public function settingsForm(array $form, array &$form_state) {
     $element = parent::settingsForm($form, $form_state);
@@ -53,6 +53,30 @@ public function settingsForm(array $form, array &$form_state) {
 
   /**
    * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = parent::settingsSummary();
+
+    $image_styles = image_style_options(FALSE);
+    // Unset possible 'No defined styles' option.
+    unset($image_styles['']);
+    // Styles could be lost because of enabled/disabled modules that defines
+    // their styles in code.
+    $image_style_setting = $this->getSetting('preview_image_style');
+    if (isset($image_styles[$image_style_setting])) {
+      $preview_image_style = t('Preview image style: @style', array('@style' => $image_styles[$image_style_setting]));
+    }
+    else {
+      $preview_image_style = t('Original image');
+    }
+
+    array_unshift($summary, $preview_image_style);
+
+    return $summary;
+  }
+
+  /**
+   * Overrides \Drupal\file\Plugin\field\widget\FileWidget::formMultipleElements().
    *
    * Special handling for draggable multiple widgets and 'add more' button.
    */
diff --git a/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php b/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php
index f9606139a0d905fc81bc6babf168910d5d918031..d5bc6fddc5235340697611944c8e58a7b4a78fd9 100644
--- a/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php
+++ b/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php
@@ -104,6 +104,30 @@ public function settingsForm(array $form, array &$form_state) {
     return $elements;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+
+    $placeholder_title = $this->getSetting('placeholder_title');
+    $placeholder_url = $this->getSetting('placeholder_url');
+    if (empty($placeholder_title) && empty($placeholder_url)) {
+      $summary[] = t('No placeholders');
+    }
+    else {
+      if (!empty($placeholder_title)) {
+        $summary[] = t('Title placeholder: @placeholder_title', array('@placeholder_title' => $placeholder_title));
+      }
+      if (!empty($placeholder_url)) {
+        $summary[] = t('URL placeholder: @placeholder_url', array('@placeholder_url' => $placeholder_url));
+      }
+    }
+
+    return $summary;
+  }
+
+
   /**
    * Form element validation handler for link_field_widget_form().
    *
diff --git a/core/modules/link/lib/Drupal/link/Tests/LinkFieldUITest.php b/core/modules/link/lib/Drupal/link/Tests/LinkFieldUITest.php
index f8ff1609759ebee7bc4e884092212cfaf1b40234..910ff1412e9213dfcba1924cde6f47d62fabbea2 100644
--- a/core/modules/link/lib/Drupal/link/Tests/LinkFieldUITest.php
+++ b/core/modules/link/lib/Drupal/link/Tests/LinkFieldUITest.php
@@ -51,7 +51,6 @@ function testFieldUI() {
       'fields[_add_new_field][label]' => $label,
       'fields[_add_new_field][field_name]' => $field_name,
       'fields[_add_new_field][type]' => 'link',
-      'fields[_add_new_field][widget_type]' => 'link_default',
     );
     $this->drupalPost("$type_path/fields", $edit, t('Save'));
     // Proceed to the Edit (field instance settings) page.
diff --git a/core/modules/node/lib/Drupal/node/NodeTypeListController.php b/core/modules/node/lib/Drupal/node/NodeTypeListController.php
index 12ca23771bf8fed93bc275d61cded3ec55ab8dcb..d6be67d779fa04a7bb494d255a0f92a4da480c96 100644
--- a/core/modules/node/lib/Drupal/node/NodeTypeListController.php
+++ b/core/modules/node/lib/Drupal/node/NodeTypeListController.php
@@ -99,12 +99,20 @@ public function getOperations(EntityInterface $entity) {
         'weight' => 0,
       );
     }
+    if ($this->moduleHandler->moduleExists('field_ui') && user_access('administer node form display')) {
+      $operations['manage-form-display'] = array(
+        'title' => t('Manage form display'),
+        'href' => $uri['path'] . '/form-display',
+        'options' => $uri['options'],
+        'weight' => 5,
+      );
+    }
     if ($this->moduleHandler->moduleExists('field_ui') && user_access('administer node display')) {
       $operations['manage-display'] = array(
         'title' => t('Manage display'),
         'href' => $uri['path'] . '/display',
         'options' => $uri['options'],
-        'weight' => 5,
+        'weight' => 10,
       );
     }
     if ($entity->isLocked()) {
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
index 27e31c615a618c57a369980579b2117ea29d6700..1a0b7ed85e4c721928be0549f49d36ce9a564786 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
@@ -32,7 +32,7 @@ public static function getInfo() {
   function setUp() {
     parent::setUp();
 
-    $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer node fields', 'administer node display', 'administer languages', 'administer site configuration'));
+    $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer node fields', 'administer node form display', 'administer node display', 'administer languages', 'administer site configuration'));
     $this->drupalLogin($web_user);
   }
 
@@ -75,10 +75,11 @@ function testNodeTypeInitialLanguageDefaults() {
     $this->assertField('langcode', 'Language is selectable on node add/edit page when language not hidden.');
     $this->assertOptionSelected('edit-langcode', 'hu', 'The initial language is the site default on the node add page after the site default language is changed.');
 
-    // Tests if the language field can be rearranged on the manage fields tab.
-    $this->drupalGet('admin/structure/types/manage/article/fields');
+    // Tests if the language field can be rearranged on the manage form display
+    // tab.
+    $this->drupalGet('admin/structure/types/manage/article/form-display');
     $language_field = $this->xpath('//*[@id="language"]');
-    $this->assert(!empty($language_field), 'Language field is visible on manage fields tab.');
+    $this->assert(!empty($language_field), 'Language field is visible on manage form display tab.');
 
     // Tests if the language field can be rearranged on the manage display tab.
     $this->drupalGet('admin/structure/types/manage/article/display');
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 9d04a6381bde26f8d924b25c9a123ea692e29b30..d9a365d1f137eae0d5f361bec1fcf872ff28b08d 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -119,6 +119,9 @@ function node_help($path, $arg) {
     case 'admin/structure/types/add':
       return '<p>' . t('Individual content types can have different fields, behaviors, and permissions assigned to them.') . '</p>';
 
+    case 'admin/structure/types/manage/%/form-display':
+      return '<p>' . t('Content items can be edited using different form modes. Here, you can define which fields are shown and hidden when %type content is edited in each form mode, and define how the field form widgets are displayed in each form mode.', array('%type' => node_type_get_label($arg[4]))) . '</p>' ;
+
     case 'admin/structure/types/manage/%/display':
       $type =  entity_load('node_type', $arg[4]);
       return '<p>' . t('Content items can be displayed using different view modes: Teaser, Full content, Print, RSS, etc. <em>Teaser</em> is a short format that is typically used in lists of multiple content items. <em>Full content</em> is typically used when the content is displayed on its own page.') . '</p>' .
diff --git a/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php b/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php
index 39eddf94a4f2384b511dd55cbf338bacec6031ee..1d628ba691d01a83388a7497437d40bd3ca8f3fe 100644
--- a/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php
+++ b/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php
@@ -44,6 +44,23 @@ public function settingsForm(array $form, array &$form_state) {
     return $element;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+
+    $placeholder = $this->getSetting('placeholder');
+    if (!empty($placeholder)) {
+      $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder));
+    }
+    else {
+      $summary[] = t('No placeholder');
+    }
+
+    return $summary;
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php
index 904509cbf4172fcd83c7f9def7ab3d7adf0dff6a..8bea40629b6605a0ed74bec79257858df7283d2e 100644
--- a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php
+++ b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php
@@ -167,7 +167,6 @@ function testNumberIntegerField() {
       'fields[_add_new_field][label]'=> $label,
       'fields[_add_new_field][field_name]' => $field_name,
       'fields[_add_new_field][type]' => 'number_integer',
-      'fields[_add_new_field][widget_type]' => 'number',
     );
     $this->drupalPost(NULL, $edit, t('Save'));
 
diff --git a/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php b/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php
index fd0d230d3432a6fbc2f2fae394779ca55f380537..25f98658407c88ec6f2f3de302c23367afc7a633 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php
@@ -41,6 +41,18 @@ public function settingsForm(array $form, array &$form_state) {
     return $element;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+
+    $display_label = $this->getSetting('display_label');
+    $summary[] = t('Use field label: @display_label', array('@display_label' => ($display_label ? t('Yes') : 'No')));
+
+    return $summary;
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php
index 8d335c395b7c7ad73f0502804fb0e8d0b5ca5304..dbc1876f05ae4ae4a136b6c1f46195322d8e2c72 100644
--- a/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php
+++ b/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php
@@ -530,7 +530,7 @@ function testOnOffCheckbox() {
     $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
 
     // Create admin user.
-    $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer node fields', 'administer taxonomy'));
+    $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer node fields', 'administer node form display', 'administer taxonomy'));
     $this->drupalLogin($admin_user);
 
     // Create a test field instance.
@@ -549,39 +549,37 @@ function testOnOffCheckbox() {
       ))
       ->save();
 
-    // Go to the edit page and check if the default settings works as expected
-    $fieldEditUrl = 'admin/structure/types/manage/page/fields/node.page.bool';
+    // Go to the form display page and check if the default settings works as
+    // expected.
+    $fieldEditUrl = 'admin/structure/types/manage/page/form-display';
     $this->drupalGet($fieldEditUrl);
 
+    $field_name = $this->bool['field_name'];
+    // Click on the widget settings button to open the widget settings form.
+    $this->drupalPostAJAX(NULL, array(), $field_name . "_settings_edit");
+
     $this->assertText(
       'Use field label instead of the "On value" as label',
       t('Display setting checkbox available.')
     );
 
-    $this->assertFieldByXPath(
-      '*//label[@for="edit-' . $this->bool['field_name'] . '-und" and text()="MyOnValue"]',
-      TRUE,
-      t('Default case shows "On value"')
-    );
+    // Enable setting.
+    $edit = array('fields[' . $field_name . '][settings_edit_form][settings][display_label]' => 1);
+    $this->drupalPostAJAX(NULL, $edit, $field_name . "_plugin_settings_update");
+    $this->drupalPost(NULL, NULL, 'Save');
 
-    // Enable setting
-    $edit = array('instance[widget][settings][display_label]' => 1);
-    // Save the new Settings
-    $this->drupalPost($fieldEditUrl, $edit, t('Save settings'));
-
-    // Go again to the edit page and check if the setting
-    // is stored and has the expected effect
+    // Go again to the form display page and check if the setting
+    // is stored and has the expected effect.
     $this->drupalGet($fieldEditUrl);
+    $this->assertText('Use field label: Yes', 'Checking the display settings checkbox updated the value.');
+
+    $this->drupalPostAJAX(NULL, array(), $field_name . "_settings_edit");
     $this->assertText(
       'Use field label instead of the "On value" as label',
       t('Display setting checkbox is available')
     );
-    $this->assertFieldChecked(
-      'edit-instance-widget-settings-display-label',
-      t('Display settings checkbox checked')
-    );
     $this->assertFieldByXPath(
-      '*//label[@for="edit-' . $this->bool['field_name'] . '-und" and text()="' . $this->bool['field_name'] . '"]',
+      '*//input[@id="edit-fields-' . $field_name . '-settings-edit-form-settings-display-label" and @value="1"]',
       TRUE,
       t('Display label changes label of the checkbox')
     );
diff --git a/core/modules/overlay/overlay.module b/core/modules/overlay/overlay.module
index 79b2854b5e40c69a0c1b3de03d4ab151165d45b5..40a0c76a65aa917272585d46fc47f6a4fa644dc2 100644
--- a/core/modules/overlay/overlay.module
+++ b/core/modules/overlay/overlay.module
@@ -100,7 +100,7 @@ function overlay_field_extra_fields() {
 /**
  * Implements hook_form_FORM_ID_alter().
  */
-function overlay_form_user_profile_form_alter(&$form, &$form_state) {
+function overlay_form_user_form_alter(&$form, &$form_state) {
   $account = $form_state['controller']->getEntity();
   if (user_access('access overlay', $account)) {
     $account_data = Drupal::service('user.data')->get('overlay', $account->id(), 'enabled');
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/ArbitraryRebuildTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/ArbitraryRebuildTest.php
index ff1bad3c41156e827974810e5f7d166554244d17..cc6546a2d23eb39cb2007f454d9c6df40a8e3a7c 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/ArbitraryRebuildTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/ArbitraryRebuildTest.php
@@ -44,11 +44,8 @@ function setUp() {
       'field_name' => 'test_multiple',
       'bundle' => 'user',
       'label' => 'Test a multiple valued field',
-      'settings' => array(
-        'user_register_form' => TRUE,
-      ),
     ))->save();
-    entity_get_form_display('user', 'user', 'default')
+    entity_get_form_display('user', 'user', 'register')
       ->setComponent('test_multiple', array(
         'type' => 'text_textfield',
         'weight' => 0,
diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php
index 4bdfbb553295e4e0638014b62e12ac65c5de1e17..fd1c08f5b3fa16aef287ca6329c8f86d9f67ff38 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php
@@ -149,10 +149,6 @@ function testBreadCrumbs() {
       "admin/structure/types/manage/$type/fields" => t('Manage fields'),
     );
     $this->assertBreadcrumb("admin/structure/types/manage/$type/fields/node.$type.body", $trail);
-    $trail += array(
-      "admin/structure/types/manage/$type/fields/node.$type.body" => t('Body'),
-    );
-    $this->assertBreadcrumb("admin/structure/types/manage/$type/fields/node.$type.body/widget-type", $trail);
 
     // Verify Filter text format administration breadcrumbs.
     $filter_formats = filter_formats();
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
index 2dfeae73240015824176f169ad61f2a343ee2ba9..79abf93447184efe1f6a8c4c88034df5e53d6ae0 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
@@ -170,7 +170,9 @@ function testFieldUpgradeToConfig() {
         'settings' => array(
           'display_summary' => TRUE,
           'text_processing' => 1,
-          'user_register_form' => FALSE,
+          // This setting has been removed in field_update_8005(). We keep it
+          // here, commented out, to prove that the upgrade path is working.
+          //'user_register_form' => FALSE,
         ),
         'status' => 1,
         'langcode' => 'und',
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index ae4131d75bcac3a6d4708c5262f392138bbb65af..3d7896bfc30c5ca014c6ce9ef3ff9ca6ac4a4500 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2556,7 +2556,7 @@ function system_custom_theme() {
 /**
  * Implements hook_form_FORM_ID_alter().
  */
-function system_form_user_profile_form_alter(&$form, &$form_state) {
+function system_form_user_form_alter(&$form, &$form_state) {
   if (config('system.timezone')->get('user.configurable')) {
     system_user_timezone($form, $form_state);
   }
@@ -2608,7 +2608,7 @@ function system_user_timezone(&$form, &$form_state) {
   $form['timezone']['timezone'] = array(
     '#type' => 'select',
     '#title' => t('Time zone'),
-    '#default_value' => isset($account->timezone) ? $account->timezone : ($account->uid == $user->uid ? config('system.date')->get('timezone.default') : ''),
+    '#default_value' => isset($account->timezone) ? $account->timezone : ($account->uid == $user->uid ? config('system.timezone')->get('default') : ''),
     '#options' => system_time_zones($account->uid != $user->uid),
     '#description' => t('Select the desired local time and time zone. Dates and times throughout this site will be displayed using this time zone.'),
   );
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php
index 78f8fb3a5e8fa7298c38771a0b435b1bd34ce801..10c9aefd6cbda9d11f209c49f7598af018581b6c 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php
@@ -44,6 +44,24 @@ public function settingsForm(array $form, array &$form_state) {
     return $element;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+
+    $summary[] = t('Textfield size: !size', array('!size' => $this->getSetting('size')));
+    $placeholder = $this->getSetting('placeholder');
+    if (!empty($placeholder)) {
+      $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder));
+    }
+    else {
+      $summary[] = t('No placeholder');
+    }
+
+    return $summary;
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php
index 1b8bb3b7f92b9d5cc1dd2646d67c8f5ec1ebe4e8..c9b807830254d80fe0622f15e0f29c4dbb6f2711 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php
@@ -80,7 +80,7 @@ function testTaxonomyRss() {
     // RSS display must be added manually.
     $this->drupalGet("admin/structure/types/manage/article/display");
     $edit = array(
-      "view_modes_custom[rss]" => '1',
+      "display_modes_custom[rss]" => '1',
     );
     $this->drupalPost(NULL, $edit, t('Save'));
 
diff --git a/core/modules/telephone/lib/Drupal/telephone/Plugin/field/widget/TelephoneDefaultWidget.php b/core/modules/telephone/lib/Drupal/telephone/Plugin/field/widget/TelephoneDefaultWidget.php
index 66884fe498fb0dfb38b060f2c0cc1d2d3ead93c4..444dc3aab20d8ff3dc5c158de3e13362e32d85c1 100644
--- a/core/modules/telephone/lib/Drupal/telephone/Plugin/field/widget/TelephoneDefaultWidget.php
+++ b/core/modules/telephone/lib/Drupal/telephone/Plugin/field/widget/TelephoneDefaultWidget.php
@@ -28,6 +28,7 @@
  */
 class TelephoneDefaultWidget extends WidgetBase {
 
+
   /**
    * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::settingsForm().
    */
@@ -41,6 +42,23 @@ public function settingsForm(array $form, array &$form_state) {
     return $element;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+
+    $placeholder = $this->getSetting('placeholder');
+    if (!empty($placeholder)) {
+      $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder));
+    }
+    else {
+      $summary[] = t('No placeholder');
+    }
+
+    return $summary;
+  }
+
   /**
    * Implements \Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement().
    */
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php
index 2fe37a00cf7afd2434d6d696b420cee4bf3297fb..72eff195266d9ad815dfb47f7cd62a482ebecbf9 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php
@@ -49,6 +49,21 @@ public function settingsForm(array $form, array &$form_state) {
     return $element;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+
+    $summary[] = t('Number of rows: !rows', array('!rows' => $this->getSetting('rows')));
+    $placeholder = $this->getSetting('placeholder');
+    if (!empty($placeholder)) {
+      $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder));
+    }
+
+    return $summary;
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php
index ef7dc0d2121ae030bc8720928345d5a71291da2d..300af1811fd4a7877dfa0530cb6909afeec3b1c0 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php
@@ -30,6 +30,32 @@
  */
 class TextareaWithSummaryWidget extends TextareaWidget {
 
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, array &$form_state) {
+    $element = parent::settingsForm($form, $form_state);
+    $element['summary_rows'] = array(
+      '#type' => 'number',
+      '#title' => t('Summary rows'),
+      '#default_value' => $this->getSetting('summary_rows'),
+      '#required' => TRUE,
+      '#min' => 1,
+    );
+    return $element;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = parent::settingsSummary();
+
+    $summary[] = t('Number of summary rows: !rows', array('!rows' => $this->getSetting('summary_rows')));
+
+    return $summary;
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php
index 7012c75c5e9700b379bbd5c8aaafc2b9c1e0fe06..5319aabc11ab7b51601f6ee3c316c38c3c9e3a63 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php
@@ -49,6 +49,21 @@ public function settingsForm(array $form, array &$form_state) {
     return $element;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+
+    $summary[] = t('Textfield size: !size', array('!size' => $this->getSetting('size')));
+    $placeholder = $this->getSetting('placeholder');
+    if (!empty($placeholder)) {
+      $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder));
+    }
+
+    return $summary;
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/user/config/entity.form_mode.user.register.yml b/core/modules/user/config/entity.form_mode.user.register.yml
new file mode 100644
index 0000000000000000000000000000000000000000..222bac768541292d066253cde49ba231297ad5bc
--- /dev/null
+++ b/core/modules/user/config/entity.form_mode.user.register.yml
@@ -0,0 +1,4 @@
+id: user.register
+label: Register
+status: '1'
+targetEntityType: user
diff --git a/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php b/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php
index c9a671b2e72c876a1ffefb8c08c687d1b132e16c..4f8912867653c53caa01efa5fea5bf8d693e1bed 100644
--- a/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php
+++ b/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php
@@ -28,12 +28,11 @@
  *     "access" = "Drupal\user\UserAccessController",
  *     "render" = "Drupal\Core\Entity\EntityRenderController",
  *     "form" = {
- *       "profile" = "Drupal\user\ProfileFormController",
+ *       "default" = "Drupal\user\ProfileFormController",
  *       "register" = "Drupal\user\RegisterFormController"
  *     },
  *     "translation" = "Drupal\user\ProfileTranslationController"
  *   },
- *   default_operation = "profile",
  *   base_table = "users",
  *   uri_callback = "user_uri",
  *   route_base_path = "admin/config/people/accounts",
diff --git a/core/modules/user/lib/Drupal/user/RegisterFormController.php b/core/modules/user/lib/Drupal/user/RegisterFormController.php
index f9f6b676cea971faffa7c94437323a3110b8f4b8..1b0b76f49f36f5c965cfa10e7fa97d10cd81f7e0 100644
--- a/core/modules/user/lib/Drupal/user/RegisterFormController.php
+++ b/core/modules/user/lib/Drupal/user/RegisterFormController.php
@@ -42,14 +42,8 @@ public function form(array $form, array &$form_state) {
     // Start with the default user account fields.
     $form = parent::form($form, $form_state, $account);
 
-    // Attach field widgets, and hide the ones where the 'user_register_form'
-    // setting is not on.
+    // Attach field widgets.
     field_attach_form($account, $form, $form_state);
-    foreach (field_info_instances('user', 'user') as $field_name => $instance) {
-      if (empty($instance['settings']['user_register_form'])) {
-        $form[$field_name]['#access'] = FALSE;
-      }
-    }
 
     if ($admin) {
       // Redirect back to page which initiated the create request; usually
diff --git a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php
index 683bbdac447c4fd4a0fa4a524530198daf2eb910..da27a0ef5b974a2711ae5e55e38d87511155ac59 100644
--- a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php
+++ b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php
@@ -207,7 +207,6 @@ function testRegistrationWithUserFields() {
       'label' => 'Some user field',
       'bundle' => 'user',
       'required' => TRUE,
-      'settings' => array('user_register_form' => FALSE),
     ));
     $instance->save();
     entity_get_form_display('user', 'user', 'default')
@@ -219,8 +218,10 @@ function testRegistrationWithUserFields() {
     $this->assertNoText($instance->label(), 'The field does not appear on user registration form');
 
     // Have the field appear on the registration form.
-    $instance->settings['user_register_form'] = TRUE;
-    $instance->save();
+    entity_get_form_display('user', 'user', 'register')
+      ->setComponent('test_user_field', array('type' => 'test_field_widget'))
+      ->save();
+
     $this->drupalGet('user/register');
     $this->assertText($instance->label(), 'The field appears on user registration form');
 
diff --git a/core/modules/user/user.install b/core/modules/user/user.install
index 454c62867bdbfdc03acccc9cf6890c8c56b2decd..37dc77075e89aa27d7b15d867c73bebcde1d26cd 100644
--- a/core/modules/user/user.install
+++ b/core/modules/user/user.install
@@ -1074,6 +1074,21 @@ function user_update_8019() {
   }
 }
 
+/**
+ * Create the 'register' form mode.
+ */
+function user_update_8020() {
+  $uuid = new Uuid();
+
+  config("entity.form_mode.user.register")
+    ->set('id', "user.register")
+    ->set('uuid', $uuid->generate())
+    ->set('label', 'Register')
+    ->set('targetEntityType', 'user')
+    ->set('status', '1')
+    ->save();
+}
+
 /**
  * @} End of "addtogroup updates-7.x-to-8.x".
  */
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 74d3743c98a0333526e950e34a52e0aff7783b2f..eb6b4f39f98fa3d02c03ce263762c79e3fdfa844 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -80,7 +80,9 @@ function user_help($path, $arg) {
       $output .= '</ul>';
       return $output;
     case 'admin/config/people/accounts/fields':
-      return '<p>' . t('This form lets administrators add, edit, and arrange fields for storing user data.') . '</p>';
+      return '<p>' . t('This form lets administrators add and edit fields for storing user data.') . '</p>';
+    case 'admin/config/people/accounts/form-display':
+      return '<p>' . t('This form lets administrators configure how form fields should be displayed when editing a user profile.') . '</p>';
     case 'admin/config/people/accounts/display':
       return '<p>' . t('This form lets administrators configure how fields should be displayed when rendering a user profile page.') . '</p>';
     case 'admin/people/search':
@@ -199,19 +201,6 @@ function user_picture_enabled() {
   return (bool) field_info_instance('user', 'user_picture', 'user');
 }
 
-/**
- * Implements hook_field_info_alter().
- */
-function user_field_info_alter(&$info) {
-  // Add the 'user_register_form' instance setting to all field types.
-  foreach ($info as $field_type => &$field_type_info) {
-    $field_type_info += array('instance_settings' => array());
-    $field_type_info['instance_settings'] += array(
-      'user_register_form' => FALSE,
-    );
-  }
-}
-
 /**
  * Implements hook_field_extra_fields().
  */
@@ -1007,7 +996,7 @@ function user_menu() {
   $items['user/%user/edit'] = array(
     'title' => 'Edit',
     'page callback' => 'entity_get_form',
-    'page arguments' => array(1, 'profile'),
+    'page arguments' => array(1),
     'access callback' => 'entity_page_access',
     'access arguments' => array(1, 'update'),
     'type' => MENU_LOCAL_TASK,
@@ -2100,55 +2089,6 @@ function user_node_load($nodes, $types) {
   }
 }
 
-/**
- * Implements hook_form_FORM_ID_alter() for 'field_ui_field_instance_edit_form'.
- *
- * Add a checkbox for the 'user_register_form' instance settings on the 'Edit
- * field instance' form.
- */
-function user_form_field_ui_field_instance_edit_form_alter(&$form, &$form_state, $form_id) {
-  $instance = $form_state['instance'];
-
-  if ($instance['entity_type'] == 'user') {
-    $form['instance']['settings']['user_register_form'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Display on user registration form.'),
-      '#description' => t("This is compulsory for 'required' fields."),
-      // Field instances created in D7 beta releases before the setting was
-      // introduced might be set as 'required' and 'not shown on user_register
-      // form'. We make sure the checkbox comes as 'checked' for those.
-      '#default_value' => $instance['settings']['user_register_form'] || $instance['required'],
-      // Display just below the 'required' checkbox.
-      '#weight' => $form['instance']['required']['#weight'] + .1,
-      // Disabled when the 'required' checkbox is checked.
-      '#states' => array(
-        'enabled' => array('input[name="instance[required]"]' => array('checked' => FALSE)),
-      ),
-      // Checked when the 'required' checkbox is checked. This is done through
-      // a custom behavior, since the #states system would also synchronize on
-      // uncheck.
-      '#attached' => array(
-        'library' => array(array('user', 'drupal.user')),
-      ),
-    );
-
-    array_unshift($form['#submit'], 'user_form_field_ui_field_instance_edit_form_submit');
-  }
-}
-
-/**
- * Additional submit handler for the 'Edit field instance' form.
- *
- * Make sure the 'user_register_form' setting is set for required fields.
- */
-function user_form_field_ui_field_instance_edit_form_submit($form, &$form_state) {
-  $instance = $form_state['values']['instance'];
-
-  if (!empty($instance['required'])) {
-    form_set_value($form['instance']['settings']['user_register_form'], 1, $form_state);
-  }
-}
-
 /**
  * Implements hook_modules_installed().
  */
diff --git a/core/themes/seven/style.css b/core/themes/seven/style.css
index 4db790a851b24c83312ce527f2834fc3406ad272..a0a828906d3440fd43bd9ed61fc49879dc755b0b 100644
--- a/core/themes/seven/style.css
+++ b/core/themes/seven/style.css
@@ -1021,23 +1021,23 @@ h1#overlay-title {
 
 /* Field UI */
 
-#field-display-overview input.field-formatter-settings-edit {
+#field-display-overview input.field-plugin-settings-edit {
   margin: 0;
   padding: 1px 8px;
 }
-#field-display-overview tr.field-formatter-settings-changed {
+#field-display-overview tr.field-plugin-settings-changed {
   background: #ffffbb;
 }
 #field-display-overview tr.drag {
   background: #ffee77;
 }
-#field-display-overview tr.field-formatter-settings-editing {
+#field-display-overview tr.field-plugin-settings-editing {
   background: #d5e9f2;
 }
-#field-display-overview .field-formatter-settings-edit-form .form-item {
+#field-display-overview .field-plugin-settings-edit-form .form-item {
   margin: 10px 0;
 }
-#field-display-overview .field-formatter-settings-edit-form .form-submit {
+#field-display-overview .field-plugin-settings-edit-form .form-submit {
   margin-bottom: 0;
 }