Index: wp-includes/theme.php
===================================================================
--- wp-includes/theme.php	(revision 7930)
+++ wp-includes/theme.php	(working copy)
@@ -479,6 +479,44 @@
 	echo '<link rel="stylesheet" href="' . $stylesheet . '" type="text/css" media="screen" />';
 }
 
+function preview_theme() {
+	if ( ! (isset($_GET['template']) && isset($_GET['preview'])) )
+		return;
+
+	if ( !current_user_can( 'switch_themes' ) )
+		return;
+
+	add_filter('template', create_function('', "return '$_GET[template]';") );
+
+	if ( isset($_GET['stylesheet']) )
+		add_filter('stylesheet', create_function('', "return '$_GET[stylesheet]';") );
+
+	ob_start( 'preview_theme_ob_filter' );
+}
+add_action('setup_theme', 'preview_theme');
+
+function preview_theme_ob_filter( $content ) {
+	return preg_replace_callback( "|(<a.*?href=([\"']))(.*?)([\"'].*?>)|", 'preview_theme_ob_filter_callback', $content );
+}
+
+function preview_theme_ob_filter_callback( $matches ) {
+	if (
+	    ( false !== strpos($matches[3], '/wp-admin/') )
+	||
+	    ( false !== strpos($matches[3], '://') && 0 !== strpos($matches[3], get_option('home')) )
+	||
+	    ( false !== strpos($matches[3], '/feed/') )
+	||
+	    ( false !== strpos($matches[3], '/trackback/') )
+	)
+		return $matches[1] . "#$matches[2] onclick=$matches[2]return false;" . $matches[4];
+
+	$link = add_query_arg( array('preview' => 1, 'template' => $_GET['template'], 'stylesheet' => @$_GET['stylesheet'] ), $matches[3] );
+	if ( 0 === strpos($link, 'preview=1') )
+		$link = "?$link";
+	return $matches[1] . attribute_escape( $link ) . $matches[4];
+}
+
 function switch_theme($template, $stylesheet) {
 	update_option('template', $template);
 	update_option('stylesheet', $stylesheet);
Index: wp-settings.php
===================================================================
--- wp-settings.php	(revision 7930)
+++ wp-settings.php	(working copy)
@@ -425,19 +425,8 @@
  */
 $wp           =& new WP();
 
+$wp->init();  // Sets up current user.
 
-/**
- * Web Path to the current active template directory
- * @since 1.5
- */
-define('TEMPLATEPATH', get_template_directory());
-
-/**
- * Web Path to the current active template stylesheet directory
- * @since 2.1
- */
-define('STYLESHEETPATH', get_stylesheet_directory());
-
 // Load the default text localization domain.
 load_default_textdomain();
 
@@ -460,6 +449,20 @@
  */
 $wp_locale =& new WP_Locale();
 
+do_action('setup_theme');
+
+/**
+ * Web Path to the current active template directory
+ * @since 1.5
+ */
+define('TEMPLATEPATH', get_template_directory());
+
+/**
+ * Web Path to the current active template stylesheet directory
+ * @since 2.1
+ */
+define('STYLESHEETPATH', get_stylesheet_directory());
+
 // Load functions for active theme.
 if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists(STYLESHEETPATH . '/functions.php') )
 	include(STYLESHEETPATH . '/functions.php');
@@ -478,8 +481,6 @@
 }
 register_shutdown_function('shutdown_action_hook');
 
-$wp->init();  // Sets up current user.
-
 // Everything is loaded and initialized.
 do_action('init');
 
Index: wp-admin/wp-admin.css
===================================================================
--- wp-admin/wp-admin.css	(revision 7930)
+++ wp-admin/wp-admin.css	(working copy)
@@ -52,30 +52,80 @@
 	margin: 10px 20px 10px 20px;
 }
 
-.available-theme {
-	width: 30%;
-	margin: 0 1em;
-	float: left;
-	text-align: center;
-	height: 28em;
-	overflow: hidden;
+table#availablethemes {
+	border-spacing: 0px;
+	border: none;
+	border-top: 1px solid #ccc;
+	border-bottom: 1px solid #ccc;
+	margin: 10px auto;
 }
+td.available-theme {
+	vertical-align: top;
+	width: 240px;
+	margin: 0;
+	padding: 20px;
+	text-align: left;
+}
+table#availablethemes td {
+	border: 1px solid #eee;
+	border-top: none;
+}
+table#availablethemes td.top {
+	border-top: none;
+}
+table#availablethemes td.right {
+	border-right: none;
+	border-left: none;
+}
+table#availablethemes td.bottom {
+	border-bottom: none;
+}
+table#availablethemes td.left {
+	border-right: none;
+	border-left: none;
+}
 
 .available-theme a.screenshot {
-	width: 250px;
-	height: 200px;
+	width: 240px;
+	height: 180px;
 	display: block;
-	margin: auto;
+	border: 1px solid #efefef;
 	margin-bottom: 10px;
 	overflow: hidden;
-	border-width: 1px;
-	border-style: solid;
 }
-
 .available-theme img {
-	width: 100%;
+	width: 240px;
 }
+.available-theme h3 {
+	margin: 15px 0 5px;
+}
 
+#current-theme {
+	margin-top: 1em;
+}
+
+#current-theme a {
+	border-bottom: none;
+}
+
+#current-theme h3 {
+	font-size: 17px;
+	font-weight: normal;
+	margin: 0;
+}
+
+#current-theme .description {
+	margin-top: 5px;
+}
+
+#current-theme img {
+	float: left;
+	border: 1px solid #666;
+	margin-right: 1em;
+	margin-bottom: 1.5em;
+	width: 150px;
+}
+
 .checkbox {
 	border: none;
 	margin: 0;
@@ -249,15 +299,6 @@
 	border-collapse: separate;
 }
 
-#currenttheme img {
-	float: left;
-	margin-right: 1em;
-	margin-bottom: 1.5em;
-	width: 300px;
-	border-width: 1px;
-	border-style: solid;
-}
-
 #quicktags {
 	padding: 0;
 	border: 0 none;
Index: wp-admin/js/theme-preview.js
===================================================================
--- wp-admin/js/theme-preview.js	(revision 0)
+++ wp-admin/js/theme-preview.js	(revision 0)
@@ -0,0 +1,46 @@
+jQuery(function($) {
+	if ( 'undefined' == typeof $.fn.pngFix )
+		$.fn.pngFix = function() { return this; }
+
+	var thickDims = function() {
+		var width = $(window).width();
+		var height = $(window).height();
+
+		var tbWindow = $('#TB_window');
+		if ( tbWindow.size() ) {
+			tbWindow.width( width - 100 ).height( height - 60 );
+			tb_position( width - 70, height - 60 );
+			$('#TB_iframeContent').height( height - 88 );
+		}
+
+		return $('a.thickbox').each( function() {
+			var href = $(this).parents('.available-theme').find('.previewlink').attr('href');
+			if ( !href )
+				return;
+			href = href.replace(/&width=[0-9]+/g, '');
+			href = href.replace(/&height=[0-9]+/g, '');
+			$(this).attr( 'href', href + '&width=' + ( width - 100 ) + '&height=' + ( height - 100 ) );
+		} );
+	}
+
+	thickDims()
+	.click( function() {
+		var alink = $(this).parents('.available-theme').find('.activatelink');
+		var url = alink.attr('href');
+		var text = alink.html();
+
+		var img = $('<img id="TB-close-png" src="/wp-admin/images/close-button.png" alt="close" title="close" />')
+			.wrap('<a href="#" id="TB-close-link" style="float: left; border-bottom: none;" onclick="tb_remove(); return false;"></a>')
+			.css( { width: 28, height: 28 } )
+			.parent().pngFix();
+
+		$('#TB_ajaxWindowTitle')
+			.before(img)
+			.append('&nbsp;<a href="' + url + '" target="_top" style="position: absolute; right: 1ex; font-weight: bold;">' + text + ' &raquo;</a>');
+
+		$('#TB_iframeContent').width('100%');
+		return false;
+	} );
+
+	$(window).resize( function() { thickDims() } );
+});
Index: wp-admin/images/close-button.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: wp-admin/images/close-button.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Index: wp-admin/themes.php
===================================================================
--- wp-admin/themes.php	(revision 7930)
+++ wp-admin/themes.php	(working copy)
@@ -1,6 +1,13 @@
 <?php
 require_once('admin.php');
 
+function switch_themes_css() {
+	echo "<style type='text/css' media='all'>
+		@import '../wp-includes/js/jquery/thickbox.css?1';
+		#TB_closeWindow, #TB_closeAjaxWindow { display: none; }
+		</style>\n";
+}
+
 if ( isset($_GET['action']) ) {
 	check_admin_referer('switch-theme_' . $_GET['template']);
 
@@ -13,6 +20,11 @@
 
 $title = __('Manage Themes');
 $parent_file = 'themes.php';
+
+wp_enqueue_script( 'theme-preview', '/wp-admin/js/theme-preview.js', array( 'thickbox', 'dimensions' ), 5 );
+
+add_action( 'admin_head', 'switch_themes_css' );
+
 require_once('admin-header.php');
 ?>
 
@@ -29,12 +41,12 @@
 
 <div class="wrap">
 <h2><?php _e('Current Theme'); ?></h2>
-<div id="currenttheme">
+<div id="current-theme">
 <?php if ( $ct->screenshot ) : ?>
 <img src="<?php echo get_option('siteurl') . '/' . $ct->stylesheet_dir . '/' . $ct->screenshot; ?>" alt="<?php _e('Current theme preview'); ?>" />
 <?php endif; ?>
 <h3><?php printf(_c('%1$s %2$s by %3$s|1: theme title, 2: theme version, 3: theme author'), $ct->title, $ct->version, $ct->author) ; ?></h3>
-<p><?php echo $ct->description; ?></p>
+<p class="description"><?php echo $ct->description; ?></p>
 <?php if ($ct->parent_theme) { ?>
 	<p><?php printf(__('The template files are located in <code>%2$s</code>.  The stylesheet files are located in <code>%3$s</code>.  <strong>%4$s</strong> uses templates from <strong>%5$s</strong>.  Changes made to the templates will affect both themes.'), $ct->title, $ct->template_dir, $ct->stylesheet_dir, $ct->title, $ct->parent_theme); ?></p>
 <?php } else { ?>
@@ -47,16 +59,31 @@
 
 <h2><?php _e('Available Themes'); ?></h2>
 <?php if ( 1 < count($themes) ) { ?>
-
+<table id="availablethemes" cellspacing="0" cellpadding="0">
 <?php
 $style = '';
 
 $theme_names = array_keys($themes);
 natcasesort($theme_names);
 
-foreach ($theme_names as $theme_name) {
-	if ( $theme_name == $ct->name )
-		continue;
+$rows = ceil(count($theme_names) / 3);
+for ( $row = 1; $row <= $rows; $row++ )
+	for ( $col = 1; $col <= 3; $col++ )
+		$table[$row][$col] = array_shift($theme_names);
+
+foreach ( $table as $row => $cols ) {
+?>
+<tr>
+<?php
+foreach ( $cols as $col => $theme_name ) {
+	$class = array('available-theme');
+	if ( $row == 1 ) $class[] = 'top';
+	if ( $col == 1 ) $class[] = 'left';
+	if ( $row == $rows ) $class[] = 'bottom';
+	if ( $col == 3 ) $class[] = 'right';
+?>
+	<td class="<?php echo join(' ', $class); ?>">
+<?php if ( !empty($theme_name) ) :
 	$template = $themes[$theme_name]['Template'];
 	$stylesheet = $themes[$theme_name]['Stylesheet'];
 	$title = $themes[$theme_name]['Title'];
@@ -65,25 +92,32 @@
 	$author = $themes[$theme_name]['Author'];
 	$screenshot = $themes[$theme_name]['Screenshot'];
 	$stylesheet_dir = $themes[$theme_name]['Stylesheet Dir'];
+	$preview_link = clean_url( get_option('home') . '/');
+	$preview_link = add_query_arg( array('preview' => 1, 'template' => $template, 'stylesheet' => $stylesheet, 'TB_iframe' => 'true', 'width' => 600, 'height' => 400 ), $preview_link );
+	$preview_text = attribute_escape( sprintf( __('Preview of "%s"'), $title ) );
 	$tags = $themes[$theme_name]['Tags'];
+	$thickbox_class = 'thickbox';
 	$activate_link = wp_nonce_url("themes.php?action=activate&amp;template=".urlencode($template)."&amp;stylesheet=".urlencode($stylesheet), 'switch-theme_' . $template);
+	$activate_text = attribute_escape( sprintf( __('Activate "%s"'), $title ) );
 ?>
-<div class="available-theme">
-<h3><a href="<?php echo $activate_link; ?>"><?php echo $title; ?></a></h3>
-
-<a href="<?php echo $activate_link; ?>" class="screenshot">
+		<a href="<?php echo $activate_link; ?>" class="<?php echo $thickbox_class; ?> screenshot">
 <?php if ( $screenshot ) : ?>
-<img src="<?php echo get_option('siteurl') . '/' . $stylesheet_dir . '/' . $screenshot; ?>" alt="" />
+			<img src="<?php echo ( $tpage == 'stage' ) ? $screenshot : get_option('siteurl') . '/' . $stylesheet_dir . '/' . $screenshot; ?>" alt="" />
 <?php endif; ?>
-</a>
-
-<p><?php echo $description; ?></p>
+		</a>
+		<h3><a class="<?php echo $thickbox_class; ?>" href="<?php echo $activate_link; ?>"><?php echo $title; ?></a></h3>
+		<p><?php echo $description; ?></p>
 <?php if ( $tags ) : ?>
-<p><?php _e('Tags:'); ?> <?php echo join(', ', $tags); ?></p>
+		<p><?php _e('Tags:'); ?> <?php echo join(', ', $tags); ?></p>
+		<noscript><p class="themeactions"><a href="<?php echo $preview_link; ?>" title="<?php echo $preview_text; ?>"><?php _e('Preview'); ?></a> <a href="<?php echo $activate_link; ?>" title="<?php echo $activate_text; ?>"><?php _e('Activate'); ?></a></p></noscript>
 <?php endif; ?>
-</div>
-<?php } // end foreach theme_names ?>
-
+		<div style="display:none;"><a class="previewlink" href="<?php echo $preview_link; ?>"><?php echo $preview_text; ?></a> <a class="activatelink" href="<?php echo $activate_link; ?>"><?php echo $activate_text; ?></a></div>
+<?php endif; // end if not empty theme_name ?>
+	</td>
+<?php } // end foreach $cols ?>
+</tr>
+<?php } // end foreach $table ?>
+</table>
 <?php } ?>
 
 <?php

