<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[31533] trunk/src: Add theme browsing and theme switching to the Customizer</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/31533">31533</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/31533","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>markjaquith</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2015-02-24 20:30:22 +0000 (Tue, 24 Feb 2015)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Add theme browsing and theme switching to the Customizer

* Brings into core the Customizer Theme Switcher feature plugin
* You can now browse, preview, and activate themes right from the Customizer

fixes <a href="https://core.trac.wordpress.org/ticket/31303">#31303</a>.
props celloexpressions, afercia, westonruter, folletto, designsimply</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpadmincsscustomizecontrolscss">trunk/src/wp-admin/css/customize-controls.css</a></li>
<li><a href="#trunksrcwpadmincustomizephp">trunk/src/wp-admin/customize.php</a></li>
<li><a href="#trunksrcwpadminincludesthemephp">trunk/src/wp-admin/includes/theme.php</a></li>
<li><a href="#trunksrcwpadminjscustomizecontrolsjs">trunk/src/wp-admin/js/customize-controls.js</a></li>
<li><a href="#trunksrcwpincludesadminbarphp">trunk/src/wp-includes/admin-bar.php</a></li>
<li><a href="#trunksrcwpincludesclasswpcustomizecontrolphp">trunk/src/wp-includes/class-wp-customize-control.php</a></li>
<li><a href="#trunksrcwpincludesclasswpcustomizemanagerphp">trunk/src/wp-includes/class-wp-customize-manager.php</a></li>
<li><a href="#trunksrcwpincludesclasswpcustomizesectionphp">trunk/src/wp-includes/class-wp-customize-section.php</a></li>
<li><a href="#trunksrcwpincludesversionphp">trunk/src/wp-includes/version.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpadmincsscustomizecontrolscss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/css/customize-controls.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/css/customize-controls.css     2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-admin/css/customize-controls.css       2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -827,7 +827,177 @@
</span><span class="cx" style="display: block; padding: 0 10px">        float: right;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Themes
+ */
+@-webkit-keyframes customize-reload {
+       0%   { opacity: 0; }
+       100% { opacity: 1; }
+}
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+@-moz-keyframes customize-reload {
+       0%   { opacity: 0; }
+       100% { opacity: 1; }
+}
+
+@keyframes customize-reload {
+       0%   { opacity: 0; }
+       100% { opacity: 1; }
+}
+
+/* #customize-container is reused from customize-loader.js, hence the naming. */
+.wp-customizer .customize-loading #customize-container {
+       display: block;
+       -webkit-animation: customize-reload .75s; /* Can't use `transition` because `display` changes here. */
+       -moz-animation: customize-reload .75s;
+       animation: customize-reload .75s;
+}
+
+.customize-themes-panel {
+       display: none;
+       padding: 0 8px;
+       background: #f1f1f1;
+       box-sizing: border-box;
+       -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+}
+
+.control-section.open .customize-themes-panel {
+       display: block;
+}
+
+#customize-theme-controls .customize-themes-panel .accordion-section-content {
+       background: transparent;
+       display: block;
+}
+
+.customize-control.customize-control-theme {
+       margin-bottom: 8px;
+}
+
+.wp-customizer .theme-browser .themes {
+       padding-bottom: 8px;
+}
+
+.wp-customizer .theme-browser .theme {
+       margin: 0;
+       width: 100%;
+}
+
+.wp-customizer .theme-browser .theme .theme-actions {
+       -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+       opacity: 1;
+}
+
+#customize-controls h3.theme-name {
+       font-size: 15px;
+}
+
+.wp-customizer .theme-browser .theme.active .theme-name {
+       padding-right: 15px;
+}
+
+.wp-customizer #themes-filter {
+       width: 100%;
+}
+
+/* Panel-like behavior */
+#accordion-section-themes .accordion-section-title:after {
+       content: "\f148";
+}
+
+.rtl #accordion-section-themes .accordion-section-title:after {
+       -webkit-transform: rotate(180deg);
+       -ms-transform: rotate(180deg);
+       transform: rotate(180deg);
+}
+
+#customize-theme-controls .control-section.current-panel > h3.accordion-section-title {
+       left: 0;
+}
+
+.customize-themes-panel.control-panel-content {
+       position: absolute;
+       left: -100%;
+       top: 0;
+       width: 100%;
+       border-top: 1px solid #ddd;
+}
+
+.in-themes-panel #customize-info,
+.in-themes-panel #customize-theme-controls > ul > .accordion-section {
+       left: 100%;
+}
+
+.themes-panel-back:before {
+       top: 13px;
+       left: 14px;
+}
+
+.in-themes-panel .themes-panel-back {
+       left: 0;
+}
+
+.in-sub-panel .themes-panel-back {
+       display: none;
+}
+
+.control-panel-back.themes-panel-back:before {
+       content: "\f345";
+}
+
+.rtl .control-panel-back.themes-panel-back:before {
+       content: "\f341";
+}
+
+/* Details View */
+.wp-customizer .theme-overlay {
+       display: none;
+}
+
+.wp-customizer.modal-open .theme-overlay {
+       position: fixed;
+       left: 0;
+       top: 0;
+       right: 0;
+       bottom: 0;
+       z-index: 109;
+}
+
+.wp-customizer .theme-overlay .theme-backdrop {
+       background: rgba( 238, 238, 238, 0.75 );
+       position: fixed;
+       z-index: 110;
+}
+
+.wp-customizer .theme-overlay .theme-wrap {
+       left: 90px;
+       right: 90px;
+       top: 45px;
+       bottom: 45px;
+       z-index: 120;
+       max-width: 1740px; /* To ensure that theme screenshots are not displayed larger than 880px wide. */
+}
+
+.wp-customizer .theme-overlay .theme-actions {
+       text-align: right; /* Because there's only one action, match the pattern of media modals and right-align the action. */
+}
+
+.modal-open .in-themes-panel #customize-controls .wp-full-overlay-sidebar-content {
+       overflow: visible; /* Prevent the top-level Customizer controls from becoming visible when elements on the right of the details modal are focused. */
+}
+
+/* Small Screens */
+@media (max-width:850px), (max-height:472px) {
+       .wp-customizer .theme-overlay .theme-wrap {
+               left: 0;
+               right: 0;
+               top: 0;
+               bottom: 0;
+       }       
+}
+
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /** Handle cheaters. */
</span><span class="cx" style="display: block; padding: 0 10px"> body.cheatin {
</span><span class="cx" style="display: block; padding: 0 10px">        font-size: medium;
</span></span></pre></div>
<a id="trunksrcwpadmincustomizephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/customize.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/customize.php  2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-admin/customize.php    2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -136,40 +136,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        <span class="control-panel-back" tabindex="-1"><span class="screen-reader-text"><?php _e( 'Back' ); ?></span></span>
</span><span class="cx" style="display: block; padding: 0 10px">                </div>
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                <?php
-                       $screenshot = $wp_customize->theme()->get_screenshot();
-                       $cannot_expand = ! ( $wp_customize->is_theme_active() || $screenshot || $wp_customize->theme()->get('Description') );
-               ?>
-
</del><span class="cx" style="display: block; padding: 0 10px">                 <div id="widgets-right"><!-- For Widget Customizer, many widgets try to look for instances under div#widgets-right, so we have to add that ID to a container div in the Customizer for compat -->
</span><span class="cx" style="display: block; padding: 0 10px">                <div class="wp-full-overlay-sidebar-content" tabindex="-1">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        <div id="customize-info" class="accordion-section <?php if ( $cannot_expand ) echo ' cannot-expand'; ?>">
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 <div id="customize-info" class="accordion-section">
</ins><span class="cx" style="display: block; padding: 0 10px">                                 <div class="accordion-section-title" aria-label="<?php esc_attr_e( 'Customizer Options' ); ?>" tabindex="0">
</span><span class="cx" style="display: block; padding: 0 10px">                                        <span class="preview-notice"><?php
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                if ( ! $wp_customize->is_theme_active() ) {
-                                                       /* translators: %s is the theme name in the Customize/Live Preview pane */
-                                                       echo sprintf( __( 'You are previewing %s' ), '<strong class="theme-name">' . $wp_customize->theme()->display('Name') . '</strong>' );
-                                               } else {
-                                                       /* translators: %s is the site/panel title in the Customize pane */
-                                                       echo sprintf( __( 'You are customizing %s' ), '<strong class="theme-name site-title">' . get_bloginfo( 'name' ) . '</strong>' );
-                                               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         echo sprintf( __( 'You are customizing %s' ), '<strong class="theme-name site-title">' . get_bloginfo( 'name' ) . '</strong>' );
</ins><span class="cx" style="display: block; padding: 0 10px">                                         ?></span>
</span><span class="cx" style="display: block; padding: 0 10px">                                </div>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                <?php if ( ! $cannot_expand ) : ?>
-                               <div class="accordion-section-content">
-                                       <?php if ( ! $wp_customize->is_theme_active() ) :
-                                               if ( $screenshot ) : ?>
-                                                       <img class="theme-screenshot" src="<?php echo esc_url( $screenshot ); ?>" />
-                                               <?php endif; ?>
-
-                                               <?php if ( $wp_customize->theme()->get('Description') ): ?>
-                                                       <div class="theme-description"><?php echo $wp_customize->theme()->display('Description'); ?></div>
-                                               <?php endif;
-                                       else:
-                                               echo __( 'The Customizer allows you to preview changes to your site before publishing them. You can also navigate to different pages on your site to preview them.' );
-                                       endif; ?>
-                               </div>
-                               <?php endif; ?>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         <div class="accordion-section-content"><?php
+                                       echo __( 'The Customizer allows you to preview changes to your site before publishing them. You can also navigate to different pages on your site to preview them.' );
+                               ?></div>
</ins><span class="cx" style="display: block; padding: 0 10px">                         </div>
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        <div id="customize-theme-controls">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -246,7 +223,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                'url'      => array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'preview'       => esc_url_raw( $url ? $url : home_url( '/' ) ),
</span><span class="cx" style="display: block; padding: 0 10px">                        'parent'        => esc_url_raw( admin_url() ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        'activated'     => esc_url_raw( admin_url( 'themes.php?activated=true&previewed' ) ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 'activated'     => esc_url_raw( home_url( '/' ) ),
</ins><span class="cx" style="display: block; padding: 0 10px">                         'ajax'          => esc_url_raw( admin_url( 'admin-ajax.php', 'relative' ) ),
</span><span class="cx" style="display: block; padding: 0 10px">                        'allowed'       => array_map( 'esc_url_raw', $allowed_urls ),
</span><span class="cx" style="display: block; padding: 0 10px">                        'isCrossDomain' => $cross_domain,
</span></span></pre></div>
<a id="trunksrcwpadminincludesthemephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/theme.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/theme.php     2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-admin/includes/theme.php       2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -486,3 +486,58 @@
</span><span class="cx" style="display: block; padding: 0 10px">        $prepared_themes = apply_filters( 'wp_prepare_themes_for_js', $prepared_themes );
</span><span class="cx" style="display: block; padding: 0 10px">        return array_values( $prepared_themes );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+/**
+ * Print JS templates for the theme-browsing UI in the Customizer.
+ *
+ * @since 4.2.0
+ */
+function customize_themes_print_templates() {
+       ?>
+       <script type="text/html" id="tmpl-customize-themes-details-view">
+               <div class="theme-backdrop"></div>
+               <div class="theme-wrap">
+                       <div class="theme-header">
+                               <button type="button" class="left dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Show previous theme' ); ?></span></button>
+                               <button type="button" class="right dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Show next theme' ); ?></span></button>
+                               <button type="button" class="close dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Close details dialog' ); ?></span></button>
+                       </div>
+                       <div class="theme-about">
+                               <div class="theme-screenshots">
+                               <# if ( data.screenshot[0] ) { #>
+                                       <div class="screenshot"><img src="{{ data.screenshot[0] }}" alt="" /></div>
+                               <# } else { #>
+                                       <div class="screenshot blank"></div>
+                               <# } #>
+                               </div>
+
+                               <div class="theme-info">
+                                       <# if ( data.active ) { #>
+                                               <span class="current-label"><?php _e( 'Current Theme' ); ?></span>
+                                       <# } #>
+                                       <h3 class="theme-name">{{{ data.name }}}<span class="theme-version"><?php printf( __( 'Version: %s' ), '{{ data.version }}' ); ?></span></h3>
+                                       <h4 class="theme-author"><?php printf( __( 'By %s' ), '{{{ data.authorAndUri }}}' ); ?></h4>
+                                       <p class="theme-description">{{{ data.description }}}</p>
+
+                                       <# if ( data.parent ) { #>
+                                               <p class="parent-theme"><?php printf( __( 'This is a child theme of %s.' ), '<strong>{{{ data.parent }}}</strong>' ); ?></p>
+                                       <# } #>
+
+                                       <# if ( data.tags ) { #>
+                                               <p class="theme-tags"><span><?php _e( 'Tags:' ); ?></span> {{ data.tags }}</p>
+                                       <# } #>
+                               </div>
+                       </div>
+
+                       <div class="theme-actions">
+                               <# if ( ! data.active ) { #>
+                                       <div class="inactive-theme">
+                                               <a href="<?php echo add_query_arg( 'theme', '{{ data.id }}', remove_query_arg( 'theme' ) ); ?>" target="_top" class="button button-primary"><?php _e( 'Live Preview' ); ?></a>
+                                       </div>
+                               <# } #>
+                       </div>
+               </div>
+       </script>
+       <?php
+}
+add_action( 'customize_controls_print_footer_scripts', 'customize_themes_print_templates' );
</ins></span></pre></div>
<a id="trunksrcwpadminjscustomizecontrolsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/js/customize-controls.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/js/customize-controls.js       2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-admin/js/customize-controls.js 2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -521,6 +521,351 @@
</span><span class="cx" style="display: block; padding: 0 10px">        });
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * wp.customize.ThemesSection
+        *
+        * Custom section for themes that functions similarly to a backwards panel,
+        * and also handles the theme-details view rendering and navigation.
+        *
+        * @constructor
+        * @augments wp.customize.Section
+        * @augments wp.customize.Container
+        */
+       api.ThemesSection = api.Section.extend({
+               currentTheme: '',
+               overlay: '',
+               template: '',
+
+               /**
+                * @since 4.2.0
+                */
+               ready: function () {
+                       var section = this;
+                       section.overlay = section.container.find( '.theme-overlay' );
+                       section.template = wp.template( 'customize-themes-details-view' );
+
+                       // Bind global keyboard events.
+                       $( 'body' ).on( 'keyup', function( event ) {
+                               if ( ! section.overlay.find( '.theme-wrap' ).is( ':visible' ) ) {
+                                       return;
+                               }
+
+                               // Pressing the right arrow key fires a theme:next event
+                               if ( 39 === event.keyCode ) {
+                                       section.nextTheme();
+                               }
+
+                               // Pressing the left arrow key fires a theme:previous event
+                               if ( 37 === event.keyCode ) {
+                                       section.previousTheme();
+                               }
+
+                               // Pressing the escape key fires a theme:collapse event
+                               if ( 27 === event.keyCode ) {
+                                       section.closeDetails();
+                               }
+                       });
+               },
+
+               /**
+                * @since 4.2.0
+                */
+               attachEvents: function () {
+                       var meta, section = this;
+
+                       // Expand/Collapse section/panel.
+                       section.container.find( '.accordion-section-title' ).on( 'click keydown', function( event ) {
+                               if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+                                       return;
+                               }
+                               event.preventDefault(); // Keep this AFTER the key filter above
+
+                               if ( section.expanded() ) {
+                                       section.collapse();
+                               } else {
+                                       section.expand();
+                               }
+                       });
+
+                       section.container.find( '.themes-panel-back' ).on( 'click keydown', function( event ) {
+                               if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+                                       return;
+                               }
+
+                               event.preventDefault(); // Keep this AFTER the key filter above
+
+                               section.collapse();
+                       });
+
+                       // Theme navigation in details view.
+                       section.container.on( 'click keydown', '.left', function( event ) {
+                               if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+                                       return;
+                               }
+
+                               event.preventDefault(); // Keep this AFTER the key filter above
+
+                               section.previousTheme();
+                       });
+
+                       section.container.on( 'click keydown', '.right', function( event ) {
+                               if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+                                       return;
+                               }
+
+                               event.preventDefault(); // Keep this AFTER the key filter above
+
+                               section.nextTheme();
+                       });
+
+                       section.container.on( 'click keydown', '.theme-backdrop, .close', function( event ) {
+                               if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+                                       return;
+                               }
+
+                               event.preventDefault(); // Keep this AFTER the key filter above
+
+                               section.closeDetails();
+                       });
+
+                       section.container.on( 'click keydown', '.theme-actions .button', function( event ) {
+                               if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+                                       return;
+                               }
+
+                               $( '.wp-full-overlay' ).addClass( 'customize-loading' );
+                       });
+
+                       section.container.on( 'input', '#themes-filter', function( event ) {
+                               var term = event.currentTarget.value.toLowerCase().trim().replace( '-', ' ' ),
+                                       controls = section.controls();
+                               controls.pop(); // Remove the last control (the add-new control).
+                               _.each( controls, function( control ) {
+                                       control.filter( term );
+                               });
+                               // Update theme count. Note that the add-theme tile is a div.customize-control.
+                               count = section.container.find( 'li.customize-control:visible' ).length;
+                               section.container.find( '.theme-count' ).text( count );
+                       });
+               },
+
+               /**
+                * Update UI to reflect expanded state
+                *
+                * @since 4.2.0
+                *
+                * @param {Boolean}  expanded
+                * @param {Object}   args
+                * @param {Boolean}  args.unchanged
+                * @param {Callback} args.completeCallback
+                */
+               onChangeExpanded: function ( expanded, args ) {
+
+                       // Immediately call the complete callback if there were no changes
+                       if ( args.unchanged ) {
+                               if ( args.completeCallback ) {
+                                       args.completeCallback();
+                               }
+                               return;
+                       }
+
+                       // Note: there is a second argument 'args' passed
+                       var position, scroll,
+                               panel = this,
+                               section = panel.container.closest( '.accordion-section' ),
+                               overlay = section.closest( '.wp-full-overlay' ),
+                               container = section.closest( '.accordion-container' ),
+                               siblings = container.find( '.open' ),
+                               topPanel = overlay.find( '#customize-theme-controls > ul > .accordion-section > .accordion-section-title' ).add( '#customize-info > .accordion-section-title' ),
+                               backBtn = overlay.find( '.themes-panel-back' ),
+                               panelTitle = section.find( '.accordion-section-title' ).first(),
+                               content = section.find( '.control-panel-content' );
+
+                       if ( expanded ) {
+
+                               // Collapse any sibling sections/panels
+                               api.section.each( function ( otherSection ) {
+                                       if ( otherSection !== panel ) {
+                                               otherSection.collapse( { duration: args.duration } );
+                                       }
+                               });
+                               api.panel.each( function ( otherPanel ) {
+                                       if ( panel !== otherPanel ) {
+                                               otherPanel.collapse( { duration: 0 } );
+                                       }
+                               });
+
+                               content.show( 0, function() {
+                                       position = content.offset().top;
+                                       scroll = container.scrollTop();
+                                       content.css( 'margin-top', ( 45 - position - scroll ) );
+                                       section.addClass( 'current-panel' );
+                                       overlay.addClass( 'in-themes-panel' );
+                                       container.scrollTop( 0 );
+                                       if ( args.completeCallback ) {
+                                               args.completeCallback();
+                                       }
+                               } );
+                               topPanel.attr( 'tabindex', '-1' );
+                               backBtn.attr( 'tabindex', '0' );
+                               backBtn.focus();
+                       } else {
+                               siblings.removeClass( 'open' );
+                               section.removeClass( 'current-panel' );
+                               overlay.removeClass( 'in-themes-panel' );
+                               content.delay( 180 ).hide( 0, function() {
+                                       content.css( 'margin-top', 'inherit' ); // Reset
+                                       if ( args.completeCallback ) {
+                                               args.completeCallback();
+                                       }
+                               } );
+                               topPanel.attr( 'tabindex', '0' );
+                               backBtn.attr( 'tabindex', '-1' );
+                               panelTitle.focus();
+                               container.scrollTop( 0 );
+                       }
+               },
+
+               /**
+                * Advance the modal to the next theme.
+                *
+                * @since 4.2.0
+                */
+               nextTheme: function () {
+                       var section = this;
+                       if ( section.getNextTheme() ) {
+                               section.showDetails( section.getNextTheme(), function() {
+                                       section.overlay.find( '.right' ).focus();
+                               } );
+                       }
+               },
+
+               /**
+                * Get the next theme model.
+                *
+                * @since 4.2.0
+                */
+               getNextTheme: function () {
+                       var control, next;
+                       control = api.control( 'theme_' + this.currentTheme );
+                       next = control.container.next( 'li.customize-control-theme' );
+                       if ( ! next.length ) {
+                               return false;
+                       }
+                       next = next[0].id.replace( 'customize-control-', '' );
+                       control = api.control( next );
+
+                       return control.params.theme;
+               },
+
+               /**
+                * Advance the modal to the previous theme.
+                *
+                * @since 4.2.0
+                */
+               previousTheme: function () {
+                       var section = this;
+                       if ( section.getPreviousTheme() ) {
+                               section.showDetails( section.getPreviousTheme(), function() {
+                                       section.overlay.find( '.left' ).focus();
+                               } );
+                       }
+               },
+
+               /**
+                * Get the previous theme model.
+                *
+                * @since 4.2.0
+                */
+               getPreviousTheme: function () {
+                       var control, previous;
+                       control = api.control( 'theme_' + this.currentTheme );
+                       previous = control.container.prev( 'li.customize-control-theme' );
+                       if ( ! previous.length ) {
+                               return false;
+                       }
+                       previous = previous[0].id.replace( 'customize-control-', '' );
+                       control = api.control( previous );
+
+                       return control.params.theme;
+               },
+
+               /**
+                * Disable buttons when we're viewing the first or last theme.
+                *
+                * @since 4.2.0
+                */
+               updateLimits: function () {
+                       if ( ! this.getNextTheme() ) {
+                               this.overlay.find( '.right' ).addClass( 'disabled' );
+                       }
+                       if ( ! this.getPreviousTheme() ) {
+                               this.overlay.find( '.left' ).addClass( 'disabled' );
+                       }
+               },
+
+               /**
+                * Render & show the theme details for a given theme model.
+                *
+                * @since 4.2.0
+                *
+                * @param {Object}   theme
+                */
+               showDetails: function ( theme, callback ) {
+                       var section = this;
+                       callback = callback || function(){};
+                       section.currentTheme = theme.id;
+                       section.overlay.html( section.template( theme ) )
+                                      .fadeIn( 'fast' )
+                                      .focus();
+                       $( 'body' ).addClass( 'modal-open' );
+                       section.containFocus( section.overlay );
+                       section.updateLimits();
+                       callback();
+               },
+
+               /**
+                * Close the theme details modal.
+                *
+                * @since 4.2.0
+                */
+               closeDetails: function ( theme ) {
+                       $( 'body' ).removeClass( 'modal-open' );
+                       this.overlay.fadeOut( 'fast' );
+                       api.control( 'theme_' + this.currentTheme ).focus();
+               },
+
+               /**
+                * Keep tab focus within the theme details modal.
+                *
+                * @since 4.2.0
+                */
+               containFocus: function( el ) {
+                       var tabbables;
+
+                       el.on( 'keydown', function( event ) {
+
+                               // Return if it's not the tab key
+                               // When navigating with prev/next focus is already handled
+                               if ( 9 !== event.keyCode ) {
+                                       return;
+                               }
+
+                               // uses jQuery UI to get the tabbable elements
+                               tabbables = $( ':tabbable', el );
+
+                               // Keep focus within the overlay
+                               if ( tabbables.last()[0] === event.target && ! event.shiftKey ) {
+                                       tabbables.first().focus();
+                                       return false;
+                               } else if ( tabbables.first()[0] === event.target && event.shiftKey ) {
+                                       tabbables.last().focus();
+                                       return false;
+                               }
+                       });
+               }
+       });
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * @since 4.1.0
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @class
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1409,6 +1754,63 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        });
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * wp.customize.ThemeControl
+        *
+        * @constructor
+        * @augments wp.customize.Control
+        * @augments wp.customize.Class
+        */
+       api.ThemeControl = api.Control.extend({
+
+               /**
+                * @since 4.2.0
+                */
+               ready: function() {
+                       var control = this;
+
+                       // Bind details view trigger.
+                       control.container.on( 'click keydown', '.theme', function( event ) {
+                               if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+                                       return;
+                               }
+
+                               if ( 'button' === event.target.className ) {
+                                       return;
+                               }
+
+                               api.section( control.section() ).showDetails( control.params.theme );
+                       });
+
+                       control.container.on( 'click keydown', '.theme-actions .button', function( event ) {
+                               if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+                                       return;
+                               }
+
+                               $( '.wp-full-overlay' ).addClass( 'customize-loading' );
+                       });
+               },
+
+               /**
+                * Show or hide the theme based on the presence of the term in the title, description, and author.
+                *
+                * @since 4.2.0
+                */
+               filter: function( term ) {
+                       var control = this,
+                           haystack = control.params.theme.name + ' '
+                                          + control.params.theme.description + ' '
+                                          + control.params.theme.tags + ' '
+                                          + control.params.theme.author;
+                       haystack = haystack.toLowerCase().replace( '-', ' ' );
+                       if ( -1 !== haystack.search( term ) ) {
+                               control.activate();
+                       } else {
+                               control.deactivate();
+                       }
+               }
+       });
+
</ins><span class="cx" style="display: block; padding: 0 10px">         // Change objects contained within the main customize object to Settings.
</span><span class="cx" style="display: block; padding: 0 10px">        api.defaultConstructor = api.Setting;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1853,14 +2255,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">        });
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        api.controlConstructor = {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                color:  api.ColorControl,
-               upload: api.UploadControl,
-               image:  api.ImageControl,
-               header: api.HeaderControl,
-               background: api.BackgroundControl
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         color:      api.ColorControl,
+               upload:     api.UploadControl,
+               image:      api.ImageControl,
+               header:     api.HeaderControl,
+               background: api.BackgroundControl,
+               theme:      api.ThemeControl
</ins><span class="cx" style="display: block; padding: 0 10px">         };
</span><span class="cx" style="display: block; padding: 0 10px">        api.panelConstructor = {};
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        api.sectionConstructor = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ api.sectionConstructor = {
+               themes: api.ThemesSection
+       };
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        $( function() {
</span><span class="cx" style="display: block; padding: 0 10px">                api.settings = window._wpCustomizeSettings;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2273,6 +2678,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                // Prompt user with AYS dialog if leaving the Customizer with unsaved changes
</span><span class="cx" style="display: block; padding: 0 10px">                $( window ).on( 'beforeunload', function () {
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( ! api.state( 'saved' )() ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                var timeout = setTimeout( function() {
+                                       overlay.removeClass( 'customize-loading' );
+                               }, 1 );
</ins><span class="cx" style="display: block; padding: 0 10px">                                 return api.l10n.saveAlert;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                } );
</span></span></pre></div>
<a id="trunksrcwpincludesadminbarphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/admin-bar.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/admin-bar.php       2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-includes/admin-bar.php 2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -650,14 +650,33 @@
</span><span class="cx" style="display: block; padding: 0 10px"> function wp_admin_bar_appearance_menu( $wp_admin_bar ) {
</span><span class="cx" style="display: block; padding: 0 10px">        $wp_admin_bar->add_group( array( 'parent' => 'site-name', 'id' => 'appearance' ) );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( current_user_can( 'switch_themes' ) || current_user_can( 'edit_theme_options' ) )
-               $wp_admin_bar->add_menu( array( 'parent' => 'appearance', 'id' => 'themes', 'title' => __('Themes'), 'href' => admin_url('themes.php') ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
+       $customize_url = add_query_arg( 'url', urlencode( $current_url ), wp_customize_url() );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( ! current_user_can( 'edit_theme_options' ) )
-               return;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( current_user_can( 'switch_themes' ) ) {
+               $wp_admin_bar->add_menu( array(
+                       'parent' => 'appearance',
+                       'id'     => 'themes',
+                       'title'  => __( 'Themes' ),
+                       'href'   => admin_url( 'themes.php' ),
+                       'meta'   => array(
+                               'class' => 'hide-if-customize',
+                       ),
+               ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
-       $customize_url = add_query_arg( 'url', urlencode( $current_url ), wp_customize_url() );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( current_user_can( 'customize' ) ) {
+                       $wp_admin_bar->add_menu( array(
+                               'parent' => 'appearance',
+                               'id'     => 'customize-themes',
+                               'title'  => __( 'Themes' ),
+                               'href'   => add_query_arg( urlencode( 'autofocus[section]' ), 'themes', $customize_url ), // urlencode() needed due to #16859
+                               'meta'   => array(
+                                       'class' => 'hide-if-no-customize',
+                               ),
+                       ) );
+               }
+       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">         if ( current_user_can( 'customize' ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                $wp_admin_bar->add_menu( array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'parent' => 'appearance',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -671,6 +690,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                add_action( 'wp_before_admin_bar_render', 'wp_customize_support_script' );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        if ( ! current_user_can( 'edit_theme_options' ) ) {
+               return;
+       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">         if ( current_theme_supports( 'widgets' )  ) {
</span><span class="cx" style="display: block; padding: 0 10px">                $wp_admin_bar->add_menu( array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'parent' => 'appearance',
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpcustomizecontrolphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-customize-control.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-customize-control.php      2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-includes/class-wp-customize-control.php        2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1101,6 +1101,101 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Customize Theme Control Class
+ *
+ * @package WordPress
+ * @subpackage Customize
+ * @since 4.2.0
+ */
+class WP_Customize_Theme_Control extends WP_Customize_Control {
+
+       public $type = 'theme';
+       public $theme;
+
+       /**
+        * Refresh the parameters passed to the JavaScript via JSON.
+        *
+        * @since 4.2.0
+        * @uses WP_Customize_Control::to_json()
+        */
+       public function to_json() {
+               parent::to_json();
+               $this->json['theme'] = $this->theme;
+       }
+
+       /**
+        * Don't render the control content from PHP, as it's rendered via JS on load.
+        *
+        * @since 4.2.0
+        */
+       public function render_content() {}
+
+       /**
+        * Render a JS template for theme display.
+        *
+        * @since 4.2.0
+        */
+       public function content_template() {
+       ?>
+               <div class="theme<# if ( data.theme.active ) { #> active<# } #>" tabindex="0" aria-describedby="{{ data.theme.id }}-action {{ data.theme.id }}-name">
+                       <# if ( data.theme.screenshot[0] ) { #>
+                               <div class="theme-screenshot">
+                                       <img src="{{ data.theme.screenshot[0] }}" alt="" />
+                               </div>
+                       <# } else { #>
+                               <div class="theme-screenshot blank"></div>
+                       <# } #>
+                       <span class="more-details" id="{{ data.theme.id }}-action"><?php _e( 'Theme Details' ); ?></span>
+                       <div class="theme-author"><?php printf( __( 'By %s' ), '{{ data.theme.author }}' ); ?></div>
+
+                       <# if ( data.theme.active ) { #>
+                               <h3 class="theme-name" id="{{ data.theme.id }}-name"><span><?php _ex( 'Previewing:', 'theme' ); ?></span> {{ data.theme.name }}</h3>
+                       <# } else { #>
+                               <h3 class="theme-name" id="{{ data.theme.id }}-name">{{ data.theme.name }}</h3>
+                       <# } #>
+
+                       <# if ( ! data.theme.active ) { #>
+                               <div class="theme-actions">
+                                       <a class="button" href="<?php echo add_query_arg( 'theme', '{{ data.theme.id }}', remove_query_arg( 'theme' ) ); ?>" target="_top"><?php _e( 'Live Preview' ); ?></a>
+                               </div>
+                       <# } #>
+               </div>
+       <?php
+       }
+}
+
+/**
+ * Customize New Theme Control Class
+ *
+ * @package WordPress
+ * @subpackage Customize
+ * @since 4.2.0
+ */
+class WP_Customize_New_Theme_Control extends WP_Customize_Control {
+
+       /**
+        * Render the new control.
+        *
+        * @since 4.2.0
+        */
+       public function render() {
+               if ( is_multisite() || ! current_user_can( 'install_themes') ) {
+                       return;
+               }
+               ?>
+               <div class="theme add-new-theme">
+                       <a href="<?php echo admin_url( 'theme-install.php' ); ?>" target="_top">
+                               <div class="theme-screenshot">
+                                       <span></span>
+                               </div>
+                               <h3 class="theme-name"><?php _e( 'Add New Theme' ); ?></h3>
+                       </a>
+               </div>
+               <?php
+       }
+}
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px">  * Widget Area Customize Control Class
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @since 3.9.0
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpcustomizemanagerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-customize-manager.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-customize-manager.php      2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-includes/class-wp-customize-manager.php        2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1110,7 +1110,39 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->register_control_type( 'WP_Customize_Upload_Control' );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->register_control_type( 'WP_Customize_Image_Control' );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->register_control_type( 'WP_Customize_Background_Image_Control' );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $this->register_control_type( 'WP_Customize_Theme_Control' );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                /* Themes */
+
+               $this->add_section( new WP_Customize_Themes_Section( $this, 'themes', array(
+                       'title' => sprintf( __( 'Theme: %s' ), $this->theme()->display('Name') ),
+                       'capability' => 'switch_themes',
+                       'priority' => 0,
+               ) ) );
+
+               // Themes Setting (unused - the theme is considerably more fundamental to the Customizer experience).
+               $this->add_setting( new WP_Customize_Filter_Setting( $this, 'active_theme', array(
+                       'capability' => 'switch_themes',
+               ) ) );
+
+               require_once( ABSPATH . 'wp-admin/includes/theme.php' );
+
+               // Theme Controls.
+               $themes = wp_prepare_themes_for_js();
+               foreach ( $themes as $theme ) {
+                       $theme_id = 'theme_' . $theme['id'];
+                       $this->add_control( new WP_Customize_Theme_Control( $this, $theme_id, array(
+                               'theme' => $theme,
+                               'section' => 'themes',
+                               'settings' => 'active_theme',
+                       ) ) );
+               }
+
+               $this->add_control( new WP_Customize_New_Theme_Control( $this, 'add_theme', array(
+                       'section' => 'themes',
+                       'settings' => 'active_theme',
+               ) ) );
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 /* Site Title & Tagline */
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $this->add_section( 'title_tagline', array(
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpcustomizesectionphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-customize-section.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-customize-section.php      2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-includes/class-wp-customize-section.php        2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -312,6 +312,57 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Customize Themes Section Class.
+ *
+ * A UI container for theme controls, which behaves like a backwards Panel.
+ *
+ * @package WordPress
+ * @subpackage Customize
+ * @since 4.2.0
+ */
+class WP_Customize_Themes_Section extends WP_Customize_Section {
+
+       public $type = 'themes';
+
+       /**
+        * Render the themes section, which behaves like a panel.
+        *
+        * @since 4.2.0
+        */
+       protected function render() {
+               $classes = 'accordion-section control-section control-section-' . $this->type;
+               ?>
+               <li id="accordion-section-<?php echo esc_attr( $this->id ); ?>" class="<?php echo esc_attr( $classes ); ?>">
+                       <h3 class="accordion-section-title" tabindex="0">
+                               <?php echo esc_html( $this->title ); ?>
+                               <span class="screen-reader-text"><?php _e( 'Press return or enter to expand' ); ?></span>
+                       </h3>
+                       <span class="control-panel-back themes-panel-back" tabindex="-1"><span class="screen-reader-text"><?php _e( 'Back' ); ?></span></span>
+                       <div class="customize-themes-panel control-panel-content themes-php">
+                               <h2><?php esc_html_e( 'Themes' ); ?>
+                                       <span class="title-count theme-count"><?php echo count( $this->controls ) - 1; ?></span>
+                               <?php if ( ! is_multisite() && current_user_can( 'install_themes' ) ) : ?>
+                                       <a href="<?php echo admin_url( 'theme-install.php' ); ?>" target="_top" class="add-new-h2"><?php echo esc_html_x( 'Add New', 'Add new theme' ); ?></a>
+                               <?php endif; ?>
+                               </h2>
+                               <div class="theme-overlay" tabindex="0" role="dialog" aria-label="<?php esc_attr_e( 'Theme details' ); ?>"></div>
+                               <div id="customize-container"></div>
+                               <?php if ( 6 < count( $this->controls ) ) : ?>
+                                       <p><label for="themes-filter">
+                                               <span class="screen-reader-text"><?php _e( 'Search installed themes...' ); ?></span>
+                                               <input type="search" id="themes-filter" placeholder="<?php esc_attr_e( 'Search installed themes...' ); ?>" />
+                                       </label></p>
+                               <?php endif; ?>
+                               <div class="theme-browser rendered">
+                                       <ul class="themes accordion-section-content">
+                                       </ul>
+                               </div>
+                       </div>
+               </li>
+<?php }
+}
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px">  * Customizer section representing widget area (sidebar).
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @package WordPress
</span></span></pre></div>
<a id="trunksrcwpincludesversionphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/version.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/version.php 2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-includes/version.php   2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11,7 +11,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @global int $wp_db_version
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-$wp_db_version = 31351;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+$wp_db_version = 31532;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px">  * Holds the TinyMCE version
</span></span></pre>
</div>
</div>

</body>
</html>