Index: /trunk/StyleCatcher/plugins/StyleCatcher/stylecatcher.pl
===================================================================
--- /trunk/StyleCatcher/plugins/StyleCatcher/stylecatcher.pl (revision 100)
+++ /trunk/StyleCatcher/plugins/StyleCatcher/stylecatcher.pl (revision 817)
@@ -1,6 +1,7 @@
-# Copyright 2005-2006 Six Apart. This code cannot be redistributed without
-# permission from www.sixapart.com.
+# Movable Type (r) Open Source (C) 2005-2008 Six Apart, Ltd.
+# This program is distributed under the terms of the
+# GNU General Public License, version 2.
 #
-# $Id: stylecatcher.pl 32007 2006-06-22 01:11:47Z jallen $
+# $Id: stylecatcher.pl 1568 2008-03-25 00:48:27Z bsmith $
 
 package MT::Plugin::StyleCatcher;
@@ -8,118 +9,54 @@
 use strict;
 use base 'MT::Plugin';
-use vars qw($VERSION);
-$VERSION = '1.1-dev';
+our $VERSION = '2.0';
 
 my $plugin;
 $plugin = MT::Plugin::StyleCatcher->new({
+    id => 'StyleCatcher',
     name => "StyleCatcher",
     version => $VERSION,
     doc_link => "http://www.sixapart.com/movabletype/styles/",
-    description => "<MT_TRANS phrase=\"StyleCatcher lets you easily browse through styles and then apply them to your blog in just a few clicks. To find out more about Movable Type styles, or for new sources for styles, visit the <a href='http://www.sixapart.com/movabletype/styles'>Movable Type styles</a> page.\">",
-    config_link => "stylecatcher.cgi",
-    author_name => "Nick O'Neil, Brad Choate",
-    author_link => "http://www.authenticgeek.net/",
+    description => q(<MT_TRANS phrase="StyleCatcher lets you easily browse through styles and then apply them to your blog in just a few clicks. To find out more about Movable Type styles, or for new sources for styles, visit the <a href='http://www.sixapart.com/movabletype/styles'>Movable Type styles</a> page.">),
+    author_name => "Six Apart, Ltd.",
+    author_link => "http://www.sixapart.com/",
     l10n_class => 'StyleCatcher::L10N',
-    config_template => \&configuration_template,
-    settings => new MT::PluginSettings([
-        ['webthemeroot'],
-        ['themeroot'],
-        ['stylelibrary'],
-    ]),
+    registry => {
+        stylecatcher_libraries => {
+            'sixapart_mt4' => {
+                url => 'http://www.sixapart.com/movabletype/styles/mt4/library',
+                label => 'MT 4 Style Library',
+                description_label => "A collection of styles compatible with Movable Type 4 default templates.",
+                order => 1,
+            },
+            # 'sixapart_mt3' => {
+            #     url => 'http://www.sixapart.com/movabletype/styles/mt3/library',
+            #     label => 'MT 3 Style Library',
+            #     description_label => "A collection of styles compatible with Movable Type 3.3+ default templates.",
+            #     order => 1000,
+            # },
+        },
+        applications => {
+            cms => {
+                methods => {
+                    stylecatcher_theme => '$StyleCatcher::StyleCatcher::CMS::view',
+                    stylecatcher_js => '$StyleCatcher::StyleCatcher::CMS::js',
+                    stylecatcher_apply => '$StyleCatcher::StyleCatcher::CMS::apply',
+                },
+                menus => {
+                    'design:theme' => {
+                        label => 'Styles',
+                        order => 300,
+                        mode => 'stylecatcher_theme',
+                        view => "blog",
+                        permission => 'edit_templates',
+                    },
+                },
+            },
+        },
+    },
 });
 MT->add_plugin($plugin);
-MT->add_plugin_action('list_template', 'stylecatcher.cgi', 'Select a Design using StyleCatcher');
-MT->add_plugin_action('blog','stylecatcher.cgi?', "Select a Design using StyleCatcher");
 
 sub instance { $plugin }
 
-sub configuration_template {
-    my $plugin = shift;
-    my ($param, $scope) = @_;
-
-    my $intro;
-    if ($scope eq 'system') {
-        if (!$param->{webthemeroot}) {
-            $param->{webthemeroot} = MT->instance->static_path;
-            $param->{webthemeroot} =~ s!/$!!;
-            $param->{webthemeroot} .= '/themes/';
-        }
-        $param->{themeroot} ||= File::Spec->catdir(MT->instance->mt_dir, 'mt-static', 'themes');
-        $param->{stylelibrary} ||= $StyleCatcher::DEFAULT_STYLE_LIBRARY;
-        $intro = q{<MT_TRANS phrase="<p>You must define a global theme repository where themes can be stored locally.  If a particular blog has not been configured for it's own theme paths, it will use these settings directly. If a blog has it's own theme paths, then the theme will be copied to that location when applied to that weblog. The paths defined here must physically exist and be writable by the webserver.</p>">};
-    } else {
-
-        my $system_plugin_config = $plugin->get_config_hash();
-        unless ($system_plugin_config && $system_plugin_config->{webthemeroot} && $system_plugin_config->{themeroot}) {
-            return q{<MT_TRANS phrase="<p style="color: #f00;"><strong>NOTE:</strong> StyleCatcher must first be configured from the system-level plugins listing before it can be used on any blog.</p>">};    
-          }
-            
-        if (my $blog = MT->instance->blog) {
-            if (!$param->{webthemeroot}) {
-                my $url = $blog->site_url;
-                $url =~ s!/$!!;
-                $url .= '/themes/';
-                $param->{webthemeroot} = $url;
-            }
-            if (!$param->{themeroot}) {
-                my $path = $blog->site_path;
-                $path = File::Spec->catdir($path, 'themes');
-                $param->{themeroot} = $path;
-            }
-        }
-        $intro = q{<MT_TRANS phrase="<p>If you wish to store your themes locally for this blog, you can configure your theme URL and path below.  Although downloaded themes will still be stored in the system-level directory, they will be copied to this directory when they are applied. The paths defined here must physically exist and be writable by the webserver.</p>">};
-
-    }
-
-    return qq{
-$intro
-
-<div class="setting">
-<div class="label"><label for="stycat_webthemeroot"><MT_TRANS phrase="Theme Root URL:"></label></div>
-<div class="field">
-<input type="text" name="webthemeroot" id="stycat_webthemeroot" value="<TMPL_VAR NAME=WEBTHEMEROOT ESCAPE=HTML>" style="width: 95%" />
-</div>
-</div>
-
-<div class="setting">
-<div class="label"><label for="stycat_themeroot"><MT_TRANS phrase="Theme Root Path:"></label></div>
-<div class="field">
-<input type="text" name="themeroot" id="stycat_themeroot" value="<TMPL_VAR NAME=THEMEROOT ESCAPE=HTML>" style="width: 95%" />
-</div>
-</div>
-
-<div class="setting">
-<div class="label"><label for="stycat_stylelibrary"><MT_TRANS phrase="Style Library URL:"></label></div>
-<div class="field">
-<input type="text" name="stylelibrary" id="stycat_stylelibrary" value="<TMPL_VAR NAME=STYLELIBRARY ESCAPE=HTML>" style="width: 95%" />
-</div>
-</div>
-    };
-}
-
-sub save_config {
-    my $plugin = shift;
-    my ($param, $scope) = @_;
-    my $themeroot = $param->{themeroot};
-    return 1 unless $themeroot;
-
-    my $app = MT->instance;
-
-    require MT::FileMgr;
-    my $filemgr = MT::FileMgr->new('Local')
-        or return $app->error(MT::FileMgr->errstr);
-
-    my $base_weblog_path = File::Spec->catfile($plugin->{full_path},
-                                               "base-weblog.css");
-    my $base_weblog = $filemgr->get_data($base_weblog_path);
-    $filemgr->mkpath($param->{themeroot})
-        or die $plugin->translate("Unable to create the theme root directory. Error: [_1]", $filemgr->errstr);
-
-    defined($filemgr->put_data($base_weblog,
-        File::Spec->catfile($param->{themeroot}, "base-weblog.css")))
-        or die $plugin->translate("Unable to write base-weblog.css to themeroot. File Manager gave the error: [_1]. Are you sure your theme root directory is web-server writable?", $filemgr->errstr);
-
-    return $plugin->SUPER::save_config(@_);
-}
-
 1;
Index: /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N.pm
===================================================================
--- /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N.pm (revision 43)
+++ /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N.pm (revision 817)
@@ -1,7 +1,7 @@
-# Copyright 2001-2006 Six Apart. This code cannot be redistributed without
-# permission from www.sixapart.com.  For more information, consult your
-# Movable Type license.
+# Movable Type (r) Open Source (C) 2005-2008 Six Apart, Ltd.
+# This program is distributed under the terms of the
+# GNU General Public License, version 2.
 #
-# $Id: L10N.pm 29367 2006-05-20 04:42:10Z bchoate $
+# $Id: L10N.pm 1174 2008-01-08 21:02:50Z bchoate $
 
 package StyleCatcher::L10N;
Index: /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/es.pm
===================================================================
--- /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/es.pm (revision 817)
+++ /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/es.pm (revision 817)
@@ -0,0 +1,60 @@
+# Movable Type (r) Open Source (C) 2005-2008 Six Apart, Ltd.
+# This program is distributed under the terms of the
+# GNU General Public License, version 2.
+#
+# $Id$
+
+package StyleCatcher::L10N::es;
+
+use strict;
+use base 'StyleCatcher::L10N::en_us';
+use vars qw( %Lexicon );
+
+## The following is the translation table.
+
+%Lexicon = (
+## plugins/StyleCatcher/lib/StyleCatcher/CMS.pm
+	'Your mt-static directory could not be found. Please configure \'StaticFilePath\' to continue.' => 'No se encontrÃ³ el directorio mt-static. Por favor, configure el \'StaticFilePath\' para continuar.',
+	'Could not create [_1] folder - Check that your \'themes\' folder is webserver-writable.' => 'No se pudo crear el directorio [_1] - Compruebe que el servidor web puede escribir en la carpeta \'themes\'.',
+	'Error downloading image: [_1]' => 'Error descargando imagen: [_1]',
+	'Successfully applied new theme selection.' => 'Se aplicÃ³ con Ã©xito la nueva selecciÃ³n de estilo.',
+	'Invalid URL: [_1]' => 'URL no vÃ¡lida: [_1]',
+
+## plugins/StyleCatcher/tmpl/view.tmpl
+	'Select a Style' => 'Seleccione un estilo',
+	'3-Columns, Wide, Thin, Thin' => '3 columnas, ancha, delgada, delgada',
+	'3-Columns, Thin, Wide, Thin' => '3 columnas, delgada, ancha, delgada',
+	'2-Columns, Thin, Wide' => '2 columnas, delgada, ancha',
+	'2-Columns, Wide, Thin' => '2 columnas, ancha, delgada',
+	'2-Columns, Wide, Medium' => '2 columnas, ancha, media', # Translate - New
+	'None available' => 'Ninguno disponible',
+	'Applying...' => 'Aplicando...',
+	'Apply Design' => 'Aplicar diseÃ±o',
+	'Error applying theme: ' => 'Error aplicando tema:',
+	'The selected theme has been applied, but as you have changed the layout, you will need to republish your blog to apply the new layout.' => 'Se ha aplicado el tema seleccionado, pero como la disposiciÃ³n ha cambiado, deberÃ¡ republicar el blog para que se aplique la disposiciÃ³n.',
+	'The selected theme has been applied!' => 'Â¡Se ha aplicado el tema seleccionado!',
+	'Error loading themes! -- [_1]' => 'Â¡Error cargando temas! -- [_1]',
+	'Stylesheet or Repository URL' => 'URL de la hoja de estilo o repositorio:',
+	'Stylesheet or Repository URL:' => 'URL de la hoja de estilo o repositorio:',
+	'Download Styles' => 'Descargar estilos',
+	'Current theme for your weblog' => 'Estilo actual de su weblog',
+	'Current Style' => 'Estilo actual',
+	'Locally saved themes' => 'Estilos guardados localmente',
+	'Saved Styles' => 'Estilos guardados',
+	'Default Styles' => 'Estilos predefinidos',
+	'Single themes from the web' => 'Estilos individuales del web',
+	'More Styles' => 'MÃ¡s estilos',
+	'Selected Design' => 'DiseÃ±o seleccionado',
+	'Layout' => 'DisposiciÃ³n',
+
+## plugins/StyleCatcher/stylecatcher.pl
+	'StyleCatcher lets you easily browse through styles and then apply them to your blog in just a few clicks. To find out more about Movable Type styles, or for new sources for styles, visit the <a href=\'http://www.sixapart.com/movabletype/styles\'>Movable Type styles</a> page.' => 'StyleCatcher le permite navegar fÃ¡cilmente por los estilos y aplicarlos a su blog fÃ¡cilmente. Para mÃ¡s informaciÃ³n sobre los estilos de Movable Type, o para encontrar mÃ¡s repositorios de estilos, visite la pÃ¡gina de <a href=\'http://www.sixapart.com/movabletype/styles\'>estilos de Movable Type</a>.',
+	'MT 4 Style Library' => 'LibrerÃ­a de estilos de MT 4',
+	'A collection of styles compatible with Movable Type 4 default templates.' => 'Una colecciÃ³n de estilos compatible con las plantillas predefinidas de Movable Type.',
+	'MT 3 Style Library' => 'LibrerÃ­a de estilos de MT 3',
+	'A collection of styles compatible with Movable Type 3.3+ default templates.' => 'Una colecciÃ³n de estilos compatible con las plantillas predefinidas de Movable 3.3+.',
+	'Styles' => 'Estilos',
+);
+
+1;
+
Index: /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/fr.pm
===================================================================
--- /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/fr.pm (revision 817)
+++ /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/fr.pm (revision 817)
@@ -0,0 +1,60 @@
+# Movable Type (r) Open Source (C) 2005-2008 Six Apart, Ltd.
+# This program is distributed under the terms of the
+# GNU General Public License, version 2.
+#
+# $Id$
+
+package StyleCatcher::L10N::fr;
+
+use strict;
+use base 'StyleCatcher::L10N::en_us';
+use vars qw( %Lexicon );
+
+## The following is the translation table.
+
+%Lexicon = (
+## plugins/StyleCatcher/lib/StyleCatcher/CMS.pm
+	'Your mt-static directory could not be found. Please configure \'StaticFilePath\' to continue.' => 'Le rÃ©pertoire mt-static n\'a pas pu Ãªtre trouvÃ©. Veuillez configurer le \'StaticFilePath\' pour continuer.',
+	'Could not create [_1] folder - Check that your \'themes\' folder is webserver-writable.' => 'Impossible de crÃ©er le dossier [_1] - VÃ©rifiez que votre dossier \'themes\' et en mode webserveur/Ã©criture.',
+	'Error downloading image: [_1]' => 'Erreur en tÃ©lÃ©chargeant l\'image : [_1]',
+	'Successfully applied new theme selection.' => 'SÃ©lection de nouveau ThÃšme appliquÃ©e avec succÃšs.',
+	'Invalid URL: [_1]' => 'URL inaccessible : [_1]',
+
+## plugins/StyleCatcher/tmpl/view.tmpl
+	'Select a Style' => 'Habillages',
+	'3-Columns, Wide, Thin, Thin' => '3-colonnes, large, fin, fin',
+	'3-Columns, Thin, Wide, Thin' => '3-colonnes, fin, large, fin',
+	'2-Columns, Thin, Wide' => '2-colonnes, fin, large',
+	'2-Columns, Wide, Thin' => '2-colonnes, large, fin',
+	'None available' => 'Aucun disponible',
+	'Applying...' => 'Appliquer...',
+	'Apply Design' => 'Appliquer l\'habillage',
+	'Error applying theme: ' => 'Erreur en appliquant l\'habillage:',
+	'The selected theme has been applied, but as you have changed the layout, you will need to republish your blog to apply the new layout.' => 'L\'habillage sÃ©lectionnÃ© a Ã©tÃ© appliquÃ©. Vous devez republier votre blog afin d\'appliquer la nouvelle mise en page.',
+	'The selected theme has been applied!' => 'L\'habillage sÃ©lectionnÃ© a Ã©tÃ© appliquÃ©!',
+	'Error loading themes! -- [_1]' => 'Erreur lors du chargement des habillages ! -- [_1]',
+	'Stylesheet or Repository URL' => 'URL de la feuille de style ou du rÃ©pertoire',
+	'Stylesheet or Repository URL:' => 'URL de la feuille de style ou du rÃ©pertoire:',
+	'Download Styles' => 'TÃ©lÃ©charger des habillages',
+	'Current theme for your weblog' => 'ThÃšme actuel de votre weblog',
+	'Current Style' => 'Habillage actuel',
+	'Locally saved themes' => 'ThÃšmes enregistrÃ©s localement',
+	'Saved Styles' => 'Habillages enregistrÃ©s',
+	'Default Styles' => 'Habillages par dÃ©faut',
+	'Single themes from the web' => 'ThÃšmes uniques venant du web',
+	'More Styles' => 'Plus d\'habillages',
+	'Selected Design' => 'Habillage sÃ©lectionnÃ©',
+	'Layout' => 'Mise en page',
+
+## plugins/StyleCatcher/stylecatcher.pl
+	'StyleCatcher lets you easily browse through styles and then apply them to your blog in just a few clicks. To find out more about Movable Type styles, or for new sources for styles, visit the <a href=\'http://www.sixapart.com/movabletype/styles\'>Movable Type styles</a> page.' => 'StyleCatcher vous permet de naviguer facilement Ã  travers des styles et de les appliquer Ã  votre blog en quelques clics seulement. Pour en savoir plus Ã  propos des styles Movable Type, ou pour avoir de nouvelles sources de styles, visitez la page <a href=\'http://www.sixapart.com/movabletype/styles\'>Movable Type styles</a>.',
+	'MT 4 Style Library' => 'BibliothÃšque MT4',
+	'A collection of styles compatible with Movable Type 4 default templates.' => 'Une gamme de styles compatibles avec les gabarits MT4 par dÃ©faut',
+	'MT 3 Style Library' => 'BibliothÃšque MT3',
+	'A collection of styles compatible with Movable Type 3.3+ default templates.' => 'Une gamme de styles compatibles avec les gabarits MT3.3+ par dÃ©faut',
+	'Styles' => 'Habillages',
+	'2-Columns, Wide, Medium' => '2-Colonnes, Large, Moyen', # Translate - New
+	);
+
+1;
+
Index: /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/de.pm
===================================================================
--- /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/de.pm (revision 817)
+++ /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/de.pm (revision 817)
@@ -0,0 +1,60 @@
+# Movable Type (r) Open Source (C) 2005-2008 Six Apart, Ltd.
+# This program is distributed under the terms of the
+# GNU General Public License, version 2.
+#
+# $Id$
+
+package StyleCatcher::L10N::de;
+
+use strict;
+use base 'StyleCatcher::L10N::en_us';
+use vars qw( %Lexicon );
+
+## The following is the translation table.
+
+%Lexicon = (
+## plugins/StyleCatcher/lib/StyleCatcher/CMS.pm
+	'Your mt-static directory could not be found. Please configure \'StaticFilePath\' to continue.' => 'Ihr mt-static-Ordner konnte nicht gefunden werden. Bitte konfigurieren Sie \'StaticFilePath\' um fortzufahren.',
+	'Could not create [_1] folder - Check that your \'themes\' folder is webserver-writable.' => 'Konnte den Ordner [_1] nicht anlegen. Stellen Sie sicher, daÃ der Webserver Schreibrechte auf dem \'themes\'-Ordner hat.',
+	'Error downloading image: [_1]' => 'Fehler beim Herunterladen einer Bilddatei: [_1]',
+	'Successfully applied new theme selection.' => 'Neue Themenauswahl erfolgreich angewendet.',
+	'Invalid URL: [_1]' => 'UngÃŒltige URL: [_1]',
+
+## plugins/StyleCatcher/tmpl/view.tmpl
+	'Select a Style' => 'Design wÃ€hlen',
+	'3-Columns, Wide, Thin, Thin' => 'Dreispaltig: breit - schmal - schmal',
+	'3-Columns, Thin, Wide, Thin' => 'Dreispaltig: schmal - breit - schmal',
+	'2-Columns, Thin, Wide' => 'Zweispaltig: schmal - breit',
+	'2-Columns, Wide, Thin' => 'Zweispaltig: breit - schmal',
+	'None available' => 'Keine verfÃŒgbar',
+	'Applying...' => 'Wende an...',
+	'Apply Design' => 'Design ÃŒbernehmen',
+	'Error applying theme: ' => 'Fehler bei der Ãbernahme des Themas:',
+	'The selected theme has been applied, but as you have changed the layout, you will need to republish your blog to apply the new layout.' => 'Das gewÃ€hlte Thema wurde ÃŒbernommen. Da das Layout geÃ€ndert wurde, verÃ¶ffentlichen Sie das Blog bitte erneut, um die Ãnderungen wirksam werden zu lassen.',
+	'The selected theme has been applied!' => 'Das Thema wurde ÃŒbernommen!',
+	'Error loading themes! -- [_1]' => 'Fehler beim Laden der Themen -- [_1]',
+	'Stylesheet or Repository URL' => 'URL des Stylesheets oder der Sammlung',
+	'Stylesheet or Repository URL:' => 'URL des Stylesheets oder der Sammlung:',
+	'Download Styles' => 'Designs herunterladen',
+	'Current theme for your weblog' => 'Aktuelles Theme Ihres Weblogs',
+	'Current Style' => 'Derzeitige Design',
+	'Locally saved themes' => 'Lokal gespeicherte Themes',
+	'Saved Styles' => 'Gespeicherte Designs',
+	'Default Styles' => 'Standarddesigns',
+	'Single themes from the web' => 'Einzelne Themes aus dem Web',
+	'More Styles' => 'Weitere Designs',
+	'Selected Design' => 'GewÃ€hltes Design',
+	'Layout' => 'Layout',
+
+## plugins/StyleCatcher/stylecatcher.pl
+	'StyleCatcher lets you easily browse through styles and then apply them to your blog in just a few clicks. To find out more about Movable Type styles, or for new sources for styles, visit the <a href=\'http://www.sixapart.com/movabletype/styles\'>Movable Type styles</a> page.' => 'Mit StyleCatchter kÃ¶nnen Sie spielend leicht neue Designvorlagen fÃŒr Ihre Blogs finden und mit wenigen Klicks direkt aus dem Internet installieren. Mehr dazu auf der <a href=\'http://www.sixapart.com/movabletype/styles\'>Movable Type Styles</a>-Seite.',
+	'MT 4 Style Library' => 'MT 4-Designs',
+	'A collection of styles compatible with Movable Type 4 default templates.' => 'Mit den Standardvorlagen von MT 3.3+  kompatible Designvorlagen',
+	'MT 3 Style Library' => 'MT 3-Design',
+	'A collection of styles compatible with Movable Type 3.3+ default templates.' => 'Mit den Standardvorlagen von MT 3.3+  kompatible Designvorlagen',
+	'Styles' => 'Designs',
+	'2-Columns, Wide, Medium' => 'Zweispaltig: breit - mittel', # Translate - New # OK
+	);
+
+1;
+
Index: /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/en_us.pm
===================================================================
--- /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/en_us.pm (revision 28)
+++ /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/en_us.pm (revision 817)
@@ -1,2 +1,8 @@
+# Movable Type (r) Open Source (C) 2005-2008 Six Apart, Ltd.
+# This program is distributed under the terms of the
+# GNU General Public License, version 2.
+#
+# $Id: en_us.pm 1174 2008-01-08 21:02:50Z bchoate $
+
 package StyleCatcher::L10N::en_us;
 
Index: /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/nl.pm
===================================================================
--- /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/nl.pm (revision 817)
+++ /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/nl.pm (revision 817)
@@ -0,0 +1,61 @@
+# Movable Type (r) Open Source (C) 2005-2008 Six Apart, Ltd.
+# This program is distributed under the terms of the
+# GNU General Public License, version 2.
+#
+# $Id$
+
+package StyleCatcher::L10N::nl;
+
+use strict;
+use base 'StyleCatcher::L10N::en_us';
+use vars qw( %Lexicon );
+
+## The following is the translation table.
+
+%Lexicon = (
+## plugins/StyleCatcher/lib/StyleCatcher/CMS.pm
+	'Your mt-static directory could not be found. Please configure \'StaticFilePath\' to continue.' => 'Uw mt-static map kon niet worden gevonden.  Gelieve \'StaticFilePath\' te configureren om verder te gaan.',
+	'Could not create [_1] folder - Check that your \'themes\' folder is webserver-writable.' => 'Kon map [_1] niet aanmaken - Controleer of uw \'themes\' map beschrijfbaar is voor de webserver.',
+	'Error downloading image: [_1]' => 'Fout bij downloaden afbeelding: [_1]',
+	'Successfully applied new theme selection.' => 'Nieuwe thema-selectie met succes toegepast.',
+	'Invalid URL: [_1]' => 'Ongeldige URL: [_1]',
+
+## plugins/StyleCatcher/tmpl/view.tmpl
+	'Select a Style' => 'Selecteer een stijl',
+	'3-Columns, Wide, Thin, Thin' => '3-kolommen, breed, smal, smal',
+	'3-Columns, Thin, Wide, Thin' => '3-kolommen, smal, breed, smal',
+	'2-Columns, Thin, Wide' => '2-kolommen, smal, breed',
+	'2-Columns, Wide, Thin' => '2-kolommen, breed, smal',
+	'2-Columns, Wide, Medium' => '2-kolommen, breed, medium', # Translate - New
+	'None available' => 'Geen beschikbaar',
+	'Applying...' => 'Wordt toegepast...',
+	'Apply Design' => 'Design toepassen',
+	'Error applying theme: ' => 'Fout bij toepassen thema:',
+	'The selected theme has been applied, but as you have changed the layout, you will need to republish your blog to apply the new layout.' => 'Het geselecteerde thema is toegepast, maar omdat u een andere lay-out heeft gekozen, moet u eerst uw weblog opnieuw publiceren om de nieuwe lay-out zichtbaar te maken.',
+	'The selected theme has been applied!' => 'Het geselecteerde thema is toegepast',
+	'Error loading themes! -- [_1]' => 'Fout bij het laden van thema\'s! -- [_1]',
+	'Stylesheet or Repository URL' => 'Stylesheet of bibliotheek URL',
+	'Stylesheet or Repository URL:' => 'Stylesheet of bibliotheek URL:',
+	'Download Styles' => 'Stijlen downloaden',
+	'Current theme for your weblog' => 'Huidig thema van uw weblog',
+	'Current Style' => 'Huidige stijl',
+	'Locally saved themes' => 'Lokaal opgeslagen thema\'s',
+	'Saved Styles' => 'Opgeslagen stijlen',
+	'Default Styles' => 'Standaard stijlen',
+	'Single themes from the web' => 'Losse thema\'s van het web',
+	'More Styles' => 'Meer stijlen',
+	'Selected Design' => 'Geselecteerde designs',
+	'Layout' => 'Lay-out',
+
+## plugins/StyleCatcher/stylecatcher.pl
+	'StyleCatcher lets you easily browse through styles and then apply them to your blog in just a few clicks. To find out more about Movable Type styles, or for new sources for styles, visit the <a href=\'http://www.sixapart.com/movabletype/styles\'>Movable Type styles</a> page.' => 'Met StyleCatcher kunt u makkelijk een keuze maken tussen stijlen om ze daarna op uw blog toe te passen in een paar klikken.  Om meer te weten over Movable Type stijlen, of om een bron te vinden van nog meer stijlen, bezoek de <a href=\'http://www.sixapart.com/movabletype/styles\'>Movable Type styles</a> pagina.',
+	'MT 4 Style Library' => 'MT 4 Stijlenbibliotheek',
+	'A collection of styles compatible with Movable Type 4 default templates.' => 'Een verzameling stijlen compatibel met de standaardsjablonen van Movable Type 4.',
+	'MT 3 Style Library' => 'MT 3 Stijlenbibliotheek',
+	'A collection of styles compatible with Movable Type 3.3+ default templates.' => 'Een verzameling stijlen compatibel met de standaardsjablonen van Movable Type 3.3+.',
+	'Styles' => 'Stijlen',
+
+);
+
+1;
+
Index: /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/ja.pm
===================================================================
--- /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/ja.pm (revision 68)
+++ /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/ja.pm (revision 817)
@@ -1,2 +1,8 @@
+# Movable Type (r) Open Source (C) 2005-2008 Six Apart, Ltd.
+# This program is distributed under the terms of the
+# GNU General Public License, version 2.
+#
+# $Id: ja.pm 2003 2008-04-21 10:34:46Z fumiakiy $
+
 package StyleCatcher::L10N::ja;
 
@@ -8,59 +14,50 @@
 
 %Lexicon = (
-    'Applying...' => 'é©çšäž­...',
-    'Apply Selected Design' => 'ãã¶ã€ã³ãé©çš',
-    'Before using StyleCatcher, you must specify the Theme Root URL and Path for the installation in the system-level plugin settings for StyleCatcher.' => 'StyleCatcherãå©çšããã«ã¯ãã·ã¹ãã ã¡ãã¥ãŒã®StyleCatcherãã©ã°ã€ã³ã®èš­å®ã§ãã«ãŒãURLãšã«ãŒããã¹ãæå®ããå¿
+
+## plugins/StyleCatcher/tmpl/view.tmpl
+	'Select a Style' => 'ã¹ã¿ã€ã«ãéžæ',
+	'3-Columns, Wide, Thin, Thin' => '3ã«ã©ã ãå€§ã»å°ã»å°',
+	'3-Columns, Thin, Wide, Thin' => '3ã«ã©ã ãå°ã»å€§ã»å°',
+	'2-Columns, Thin, Wide' => '2ã«ã©ã ãå°ã»å€§',
+	'2-Columns, Wide, Thin' => '2ã«ã©ã ãå€§ã»å°',
+	'2-Columns, Wide, Medium' => '2ã«ã©ã ãå€§ã»äž­',
+	'2-Columns, Medium, Wide' => '2ã«ã©ã ãäž­ã»å€§', # Translate - New
+	'None available' => 'èŠã€ãããŸãã',
+	'Applying...' => 'é©çšäž­...',
+	'Apply Design' => 'ãã¶ã€ã³ãé©çš',
+	'Error applying theme: ' => 'ããŒããé©çšäž­ã«ãšã©ãŒãçºçããŸããã',
+	'The selected theme has been applied, but as you have changed the layout, you will need to republish your blog to apply the new layout.' => 'ããŒããé©çšããŸãããã¬ã€ã¢ãŠããå€æŽãããã®ã§ãåæ§ç¯ããå¿
 èŠããããŸãã',
-    'Choose this Design' => 'ãã®ãã¶ã€ã³ãéžæ',
-    'click here.' => 'ãããã¯ãªãã¯ããŠãã ããã',
-    'Configure plugin' => 'ãã©ã°ã€ã³ã®æ§æ',
-    "Could not create [_1] folder - Check that your 'themes' folder is webserver-writable." => '[_1] ãã£ã¬ã¯ããªãäœæã§ããŸããã§ãããWebãµãŒããŒããããŒãã®ãã£ã¬ã¯ããªã«æžãèŸŒã¿ãã§ãããã©ããç¢ºèªããŠãã ããã',
-    'Current Theme' => 'çŸåšã®ããŒã',
-    'Current theme for your weblog' => 'ãã­ã°ã®çŸåšã®ããŒã',
-    'Current Themes' => 'çŸåšã®ããŒã',
-    'Current themes for your weblogs' => 'ãã­ã°ã®çŸåšã®ããŒã',
-    'Error loading themes! -- [_1]' => 'ããŒããã­ãŒãã§ããŸããã§ãã: [_1]',
-    'Find Style' => 'ã¹ã¿ã€ã«æ€çŽ¢',
-    'Find Styles' => 'ã¹ã¿ã€ã«æ€çŽ¢',
-    'Hide Details' => 'è©³çŽ°ãé ã',
-    "Install <a href='http://greasemonkey.mozdev.org/'>GreaseMonkey</a>" => "<a href='http://greasemonkey.mozdev.org/'>GreaseMonkey</a>ã§",
-    "StyleCatcher user script." => "StyleCatcherã®ãŠãŒã¶ãŒã¹ã¯ãªãããå©çšãã",
-    "It will take a moment for themes to populate once you click 'Find Style'." => 'ã¹ã¿ã€ã«æ€çŽ¢ãã¯ãªãã¯ãããšãããŒããåãèŸŒã¿ãŸãïŒå°ãæéãããããŸãïŒã',
-    'Loading...' => 'ã­ãŒãäž­...',
-    'Locally saved themes' => 'ã­ãŒã«ã«ã«ä¿å­ãããããŒã',
-    'More Themes' => 'ãã®ä»ã®ããŒã',
-    'Movable Type styles' => 'Movable Type ã¹ã¿ã€ã«',
-    'NOTE:' => 'æ³š:',
-    ' page.' => 'ããŒãž',
-    'Please click on a theme before attempting to apply a new design to your blog.' => 'ãã­ã°ã«é©çšããããŒããã¯ãªãã¯ããŠéžæããŠãã ããã',
-    'Please select a weblog to apply this theme.' => 'ããŒããé©çšãããã­ã°ãéžæããŠãã ããã',
-    'Saved Themes' => 'ä¿å­æžã¿ããŒã',
-    'Select a Design using StyleCatcher' => 'StyleCatcherã§ãã¶ã€ã³ãéžã¶',
-    'Select a Weblog...' => 'ãã­ã°ãéžæ',
-    'Show Details' => 'è©³çŽ°è¡šç€º',
-    'Single themes from the web' => 'ãã®ä»ã®ããŒã',
-    "StyleCatcher lets you easily browse through styles and then apply them to your blog in just a few clicks. To find out more about Movable Type styles, or for new sources for styles, visit the <a href='http://www.sixapart.com/movabletype/styles'>Movable Type styles</a> page." => "StyleCatcherãäœ¿ããšãã»ãã®æ°åã¯ãªãã¯ããã ãã§ã¹ã¿ã€ã«ãæ¢ããŠãã­ã°ã«é©çšããããšãã§ããŸããMovable Typeã®ã¹ã¿ã€ã«ã«ã€ããŠã®è©³çŽ°ãã¹ã¿ã€ã«ã®é
+	'The selected theme has been applied!' => 'ããŒããé©çšããŸããã',
+	'Error loading themes! -- [_1]' => 'ããŒãã®èª­ã¿èŸŒã¿ã§ãšã©ãŒãçºçããŸãã! -- [_1]',
+	'Stylesheet or Repository URL' => 'ã¹ã¿ã€ã«ã·ãŒããŸãã¯ãªããžããªã®URL',
+	'Stylesheet or Repository URL:' => 'ã¹ã¿ã€ã«ã·ãŒããŸãã¯ãªããžããªã®URL:',
+	'Download Styles' => 'ã¹ã¿ã€ã«ãããŠã³ã­ãŒã',
+	'Current theme for your weblog' => 'é©çšãããŠããããŒã',
+	'Current Style' => 'çŸåšã®ã¹ã¿ã€ã«',
+	'Locally saved themes' => 'ä¿å­ãããŠããããŒã',
+	'Saved Styles' => 'ä¿å­ãããŠããã¹ã¿ã€ã«',
+	'Default Styles' => 'æ¢å®ã®ã¹ã¿ã€ã«',
+	'Single themes from the web' => 'ãã®ä»ã®ããŒã',
+	'More Styles' => 'ãã®ä»ã®ã¹ã¿ã€ã«',
+	'Selected Design' => 'éžæããããã¶ã€ã³',
+	'Layout' => 'ã¬ã€ã¢ãŠã',
+
+## plugins/StyleCatcher/lib/StyleCatcher/CMS.pm
+	'Your mt-static directory could not be found. Please configure \'StaticFilePath\' to continue.' => 'mt-staticãã£ã¬ã¯ããªãèŠã€ãããŸããã§ãããStaticFilePathãèš­å®ããŠãã ããã',
+	'Could not create [_1] folder - Check that your \'themes\' folder is webserver-writable.' => '[_1] ãã©ã«ããäœæã§ããŸããã\'themes\' ãã©ã«ããæžãèŸŒã¿å¯èœãç¢ºèªããŠãã ããã',
+	'Error downloading image: [_1]' => 'ç»åãããŠã³ã­ãŒãã§ããŸããã§ãã: [_1]',
+	'Successfully applied new theme selection.' => 'æ°ããããŒããé©çšããŸããã',
+	'Invalid URL: [_1]' => 'URLãäžæ­£ã§ã: [_1]',
+
+## plugins/StyleCatcher/stylecatcher.pl
+	'StyleCatcher lets you easily browse through styles and then apply them to your blog in just a few clicks. To find out more about Movable Type styles, or for new sources for styles, visit the <a href=\'http://www.sixapart.com/movabletype/styles\'>Movable Type styles</a> page.' => 'StyleCatcherãäœ¿ããšãã»ãã®æ°åã¯ãªãã¯ããã ãã§ã¹ã¿ã€ã«ãæ¢ããŠãã­ã°ã«é©çšããããšãã§ããŸããMovable Typeã®ã¹ã¿ã€ã«ã«ã€ããŠã®è©³çŽ°ãã¹ã¿ã€ã«ã®é
 åžå
-ã«ã€ããŠã¯ã<a href='http://www.sixapart.com/movabletype/styles'>Movable Type styles</a>ã®ããŒãžïŒè±èªïŒãžã¢ã¯ã»ã¹ããŠãã ããã",
-    'StyleCatcher must first be configured system-wide before it can be used.' => 'StyleCatcherãå©çšããã«ã¯ããŸãã·ã¹ãã ã¬ãã«ã§èš­å®ãè¡ãå¿
-èŠããããŸãã',
-    'Style Library URL:' => 'Style Libraryãžã®URL:',
-    'Successfully applied new theme selection.' => 'æ°ããããŒããé©çšããŸããã',
-    'Theme or Repository URL:' => 'ããŒã/ãªããžããªãžã®URL:',
-    'Theme Root Path:' => 'ããŒãã®ã«ãŒããã¹:',
-    'Theme Root URL:' => 'ããŒãã®ã«ãŒãURL:',
-    'The paths defined here must physically exist and be writable by the webserver.' => 'ãã®ãã¹ã¯ç©ççã«å­åšããã€WebãµãŒããŒããæžãèŸŒã¿å¯èœã§ãªããã°ãªããŸããã',
-    ' To change the location of your local theme repository, ' => ' ããŒããªããžããªã®å Žæãå€ããã«ã¯ ',
-    'Unable to create the theme root directory. Error: [_1]' => 'ããŒãã®ã«ãŒããã£ã¬ã¯ããªãäœæã§ããŸããã§ãã: [_1]',
-    'Unable to write base-weblog.css to themeroot. File Manager gave the error: [_1]. Are you sure your theme root directory is web-server writable?' => 'base-weblog.cssãããŒãã®ã«ãŒãã«æžãèŸŒããŸããã§ãã: [_1]ãWebãµãŒããŒããããŒãã®ã«ãŒããã£ã¬ã¯ããªã«æžãèŸŒã¿ãã§ãããã©ããç¢ºèªããŠãã ããã',
-    q{You don't appear to have any weblogs with a 'styles-site.css' template that you have rights to edit. Please check your weblog(s) for this template.} => 'styles-site.cssãã³ãã¬ãŒããå©çšããŠãããã­ã°ããããŸããããã®ãã³ãã¬ãŒãããã­ã°ã§ç¢ºèªããŠãã ããã',
-    q{You must define a global theme repository where themes can be stored locally.  If a particular blog has not been configured for it's own theme paths, it will use these settings. If a blog has it's own theme paths, then the theme will be copied to that location when applied to that weblog.} => 'ããŒããä¿å­ããããã®ã°ã­ãŒãã«ããŒããã£ã¬ã¯ããªãæå®ããŠãã ããããã­ã°ããšã®èš­å®ã§äžæžãããªãéããããã§ã®èš­å®ãå©çšãããŸãããã­ã°ã®èš­å®ã§äžæžãããå ŽåãããŒãã¯ãã­ã°ã«é©çšããããšãã«ãã®å Žæãžã³ããŒãããŸãã',
-    q{Your theme URL and path can be customized for this weblog.} => 'ãã®ãã­ã°çšã«ããŒãã®URLãšãã¹ãã«ã¹ã¿ãã€ãºã§ããŸãã', 
-    "<p>You must define a global theme repository where themes can be stored locally.  If a particular blog has not been configured for it's own theme paths, it will use these settings directly. If a blog has it's own theme paths, then the theme will be copied to that location when applied to that weblog. The paths defined here must physically exist and be writable by the webserver.</p>" => '<p>ããŒããä¿å­ããããã®ã°ã­ãŒãã«ããŒããã£ã¬ã¯ããªãæå®ããŠãã ããããã­ã°ããšã®èš­å®ã§äžæžãããªãéããããã§ã®èš­å®ãå©çšãããŸãããã­ã°ã®èš­å®ã§äžæžãããå ŽåãããŒãã¯ãã­ã°ã«é©çšããããšãã«ãã®å Žæãžã³ããŒãããŸãããã®ãã¹ã¯ç©ççã«å­åšããã€WebãµãŒããŒããæžãèŸŒã¿å¯èœã§ãªããã°ãªããŸããã</p>',
-    '<p style="color: #f00;"><strong>NOTE:</strong> StyleCatcher must first be configured from the system-level plugins listing before it can be used on any blog.</p>' => '<p style="color: #f00;"><strong>æ³šæïŒ</strong>StyleCatcherãå©çšããã«ã¯ããŸãã·ã¹ãã ã¬ãã«ã§èš­å®ãè¡ãå¿
-èŠããããŸãã',
-    "<p>If you wish to store your themes locally for this blog, you can configure your theme URL and path below.  Although downloaded themes will still be stored in the system-level directory, they will be copied to this directory when they are applied. The paths defined here must physically exist and be writable by the webserver.</p>" => '<p>ããŒãã®ãã¡ã€ã«ããã­ã°ããšã«ä¿å­ãããå Žåã¯ãããŒãã®URLãšãã¹ãä»¥äžã«èš­å®ããŠãã ãããããŠã³ã­ãŒããããããŒãã¯ã·ã¹ãã ã¬ãã«ã§èš­å®ãããã£ã¬ã¯ãªã«ä¿å­ãããŸããããã­ã°ã«é©çšããã°ããã§æå®ãããã£ã¬ã¯ããªã«ãã³ããŒãããŸãããã®ãã¹ã¯ç©ççã«å­åšããã€WebãµãŒããŒããæžãèŸŒã¿å¯èœã§ãªããã°ãªããŸããã</p>',
-
-
+ã«ã€ããŠã¯ã<a href=\'http://www.sixapart.com/movabletype/styles\'>Movable Type styles</a>ã®ããŒãžïŒè±èªïŒãžã¢ã¯ã»ã¹ããŠãã ããã',
+	'MT 4 Style Library' => 'MT 4 ã¹ã¿ã€ã«ã©ã€ãã©ãª',
+	'A collection of styles compatible with Movable Type 4 default templates.' => 'Movable Type 4ã®ããã©ã«ããã³ãã¬ãŒããšäºææ§ã®ããã¹ã¿ã€ã«ã§ãã',
+	'MT 3 Style Library' => 'MT 3 ã¹ã¿ã€ã«ã©ã€ãã©ãª',
+	'A collection of styles compatible with Movable Type 3.3+ default templates.' => 'Movable Type 3.3xã®ããã©ã«ããã³ãã¬ãŒããšäºææ§ã®ããã¹ã¿ã€ã«ã§ãã',
+	'Styles' => 'ã¹ã¿ã€ã«',
 );
 
Index: /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/CMS.pm
===================================================================
--- /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/CMS.pm (revision 817)
+++ /trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/CMS.pm (revision 817)
@@ -0,0 +1,690 @@
+# Movable Type (r) Open Source (C) 2005-2008 Six Apart, Ltd.
+# This program is distributed under the terms of the
+# GNU General Public License, version 2.
+#
+# $Id: CMS.pm 2576 2008-06-14 00:35:33Z bchoate $
+
+package StyleCatcher::CMS;
+
+use strict;
+use File::Basename qw(basename);
+
+our $DEFAULT_STYLE_LIBRARY;
+
+sub style_library {
+    return MT->registry("stylecatcher_libraries");
+}
+
+sub file_mgr {
+    my $app = MT->instance;
+    require MT::FileMgr;
+    my $filemgr = MT::FileMgr->new('Local')
+      or return $app->error( MT::FileMgr->errstr );
+    $filemgr;
+}
+
+sub listify {
+    my ($data) = @_;
+    my @list;
+    foreach my $k (keys %$data) {
+        my %entry = %{ $data->{$k} };
+        $entry{key} = $k;
+        delete $entry{plugin};
+        $entry{label} = $entry{label}->() if ref($entry{label});
+        $entry{description_label} = $entry{description_label}->() if ref($entry{description_label});
+        push @list, \%entry;
+    }
+    @list = sort { $a->{order} <=> $b->{order} } @list;
+    \@list;
+}
+
+sub view {
+    my $app     = shift;
+    my $blog_id = $app->param('blog_id');
+    $app->return_to_dashboard( redirect => 1 ) unless $blog_id;
+
+    my $blog = MT::Blog->load($blog_id);
+    return $app->errtrans("Invalid request") unless $blog;
+
+    my $static_path = $app->static_file_path;
+    if (! -d $static_path ) {
+        return $app->errtrans("Your mt-static directory could not be found. Please configure 'StaticFilePath' to continue.");
+    }
+
+    my $themeroot =
+      File::Spec->catdir( $app->static_file_path, 'support', 'themes' );
+    my $webthemeroot = $app->static_path . 'support/themes';
+    my $stylelibrary = listify(style_library());
+    my $theme_data   = make_themes();
+    my $styled_blogs = fetch_blogs();
+
+    my $config = plugin()->get_config_hash();
+
+    my @blog_loop;
+    my %current_themes;
+    my ($blog_theme, $blog_layout);
+    foreach my $blog (@$styled_blogs) {
+        my $curr_theme = $config->{"current_theme_" . $blog->id} || '';
+        my $curr_layout = $config->{"current_layout_" . $blog->id} || 'layout-wtt';
+        push @blog_loop,
+          {
+            blog_id   => $blog->id,
+            blog_name => $blog->name,
+            layout    => $curr_layout,
+            theme_id  => $curr_theme,
+            view_link => $blog->site_url,
+          };
+        if ($blog->id == $blog_id) {
+            $blog_theme = $curr_theme;
+            $blog_layout = $curr_layout;
+        }
+        if ( $theme_data->{themes} && $curr_theme ) {
+            foreach my $theme ( @{ $theme_data->{themes} } ) {
+                if ( ($theme->{prefix} || '') . ':' . $theme->{name} eq $curr_theme ) {
+                    push @{ $theme->{blogs} }, $blog->id;
+                    next if exists $current_themes{ $theme->{name} };
+                    $current_themes{ $theme->{name} } = 1;
+                    push @{ $theme->{tags} }, 'collection:current';
+                }
+            }
+        }
+    }
+
+    push @{ $theme_data->{categories} }, 'current'
+      if %current_themes;
+
+    require JSON;
+    my $url   = $app->param('url');
+    my %param = (
+        version     => plugin()->version,
+        # blog_loop   => \@blog_loop,
+        blog_id => $blog_id,
+        themes_json => JSON::objToJson(
+            $theme_data, { pretty => 1, indent => 2, delimiter => 1 }
+        ),
+        auto_fetch => $url ? 1 : 0,
+        style_library => $stylelibrary,
+        current_theme => $blog_theme || '',
+        current_layout => $blog_layout || 'layout-wtt',
+        dynamic_blog => (($blog->custom_dynamic_templates || '') eq 'all'),
+    );
+
+    if ( $blog_id && @$styled_blogs ) {
+        my $blog = $styled_blogs->[0];
+        $param{blog_name} = $blog->name;
+        $param{blog_url}  = $blog->site_url;
+    }
+
+    my $path = $app->static_path;
+    $path .= '/' unless $path =~ m!/$!;
+    $path .= plugin()->envelope . "/";
+    $path = $app->base . $path if $path =~ m!^/!;
+    $param{plugin_static_uri} = $path;
+
+    $app->build_page( 'view.tmpl', \%param );
+}
+
+# AJAX/JSON modes
+
+# returns a json structure of styles given a particular url
+sub js {
+    # ydnar's remixer uses javascript files for each collection of styles -
+    # we generate these js files from css metadata
+    # StyleCatcher will pick up any metadata in the theme css file in the
+    # format of 'key: value' in comment-space
+    # The remixer only uses name, author, description at the moment.
+    my $app = shift;
+
+    my $data = fetch_themes($app->param('url'))
+        or return $app->json_error( $app->errstr );
+    return $app->json_result( $data );
+}
+
+# does the work after user selects a particular theme to apply to a blog
+sub apply {
+    my $app = shift;
+
+    my $blog_id = $app->param('blog_id');
+    my $url     = $app->param('url');
+    my $layout  = $app->param('layout');
+    my $name    = $app->param('name');
+
+    # Load the default stylesheet for this blog
+    my $tmpl = load_style_template($blog_id);
+
+    $app->validate_magic or return $app->json_error($app->translate("Invalid request"));
+    return $app->json_error($app->translate("Invalid request"))
+      unless $blog_id && $url && $tmpl;
+
+    my $static_path = $app->static_file_path;
+    if (! -d $static_path ) {
+        return $app->json_error($app->translate("Your mt-static directory could not be found. Please configure 'StaticFilePath' to continue."));
+    }
+
+    my $themeroot =
+      File::Spec->catdir( $static_path, 'support', 'themes' );
+    my $webthemeroot = $app->static_path . 'support/themes/';
+    my $mtthemeroot  = $app->static_path . 'themes/';
+    my $mtthemebase  = $app->static_path . 'themes-base/';
+
+    # Break up the css url in to a couple useful pieces
+    my @url = split( /\//, $url );
+
+    # if this isn't a local url, then we have to grab some files from
+    # yonder...
+    my $filemgr = file_mgr()
+      or return $app->json_error( MT::FileMgr->errstr );
+
+    if ( $url !~ m/^(\Q$webthemeroot\E|\Q$mtthemeroot\E)/ ) {
+        my $new_url = '';
+
+        for (0..(scalar(@url)-2)) {
+            $new_url .= $url[$_] . '/';
+        }
+        my ( $basename, $extension ) = split( /\./, $url[-1] );
+        if ($basename eq 'screen') {
+            $basename = $url[-2];
+        }
+
+        # Pick up the stylesheet
+        my $user_agent  = $app->new_ua;
+        my $css_request = HTTP::Request->new( GET => $url );
+        my $response    = $user_agent->request($css_request);
+
+        # Pick up the thumbnail and thumbnail-large
+        my $thumbnail_request =
+          HTTP::Request->new( GET => $new_url . "thumbnail.gif" );
+        my $thumbnail_response = $user_agent->request($thumbnail_request);
+        my $thumbnail_large_request =
+          HTTP::Request->new( GET => $new_url . "thumbnail-large.gif" );
+        my $thumbnail_large_response =
+          $user_agent->request($thumbnail_large_request);
+
+        # Parse out image filenames in the css and then write out the css file
+        # and thumbnails to our theme folder
+        my $content = $response->content;
+        $content =~ s!/\*.*?\*/!!gs;    # strip all comments first
+        my @images = $content =~
+          m/\b(?:url\(\s*)([a-zA-Z0-9_.-]+\.(?:gif|jpe?g|png))(?:\s*?\))/gi;
+        $filemgr->mkpath( File::Spec->catdir( $themeroot, $basename ) )
+          or return $app->json_error(
+            $app->translate(
+"Could not create [_1] folder - Check that your 'themes' folder is webserver-writable.",
+                $basename
+            )
+          );
+        $filemgr->put_data( $response->content,
+            File::Spec->catfile( $themeroot, $basename, $basename . '.css' ) );
+        if (($thumbnail_response->code >= 200) && ($thumbnail_response->code < 400)) {
+        $filemgr->put_data( $thumbnail_response->content,
+            File::Spec->catfile( $themeroot, $basename, "thumbnail.gif" ),
+            'upload' );
+        } else {
+            return $app->json_error($app->translate("Error downloading image: [_1]", $new_url . 'thumbnail.gif'))
+        }
+        if (($thumbnail_large_response->code >= 200) && ($thumbnail_large_response->code < 400)) {
+            $filemgr->put_data(
+                $thumbnail_large_response->content,
+                File::Spec->catfile( $themeroot, $basename, "thumbnail-large.gif" ),
+                'upload'
+            );
+        } else {
+            return $app->json_error($app->translate("Error downloading image: [_1]", $new_url . 'thumbnail-large.gif'))
+        }
+
+       # Pick up the images we parsed earlier and write them to the theme folder
+        for my $image_url (@images) {
+            my $image_request =
+              HTTP::Request->new( GET => $new_url . $image_url );
+            my $image_response = $user_agent->request($image_request);
+
+            my @image_url = split( /\//, $image_url );
+            my $image_filename = $image_url[-1];
+
+            if (($response->code >= 200) && ($response->code < 400)) {
+                $filemgr->put_data( $image_response->content,
+                    File::Spec->catfile( $themeroot, $basename, $image_filename ),
+                    'upload' )
+                  or return $app->json_error( $filemgr->errstr );
+            } else {
+                return $app->json_error($app->translate("Error downloading image: [_1]", $new_url . $image_url));
+            }
+        }
+        $url = "$webthemeroot$basename/$basename.css";
+    }
+    
+
+    my $url2 = $mtthemebase . "blog.css";
+
+    # Replacing the theme import or adding a new one at the beginning
+    my $template_text  = $tmpl->text();
+    my $replaced       = 0;
+    my $header =
+'/* This is the StyleCatcher theme addition. Do not remove this block. */';
+    my $footer = '/* end StyleCatcher imports */';
+    my $styles = $header . "\n" . <<"EOT" . $footer;
+\@import url($url2);
+\@import url($url);
+EOT
+    if ($template_text =~ s/\Q$header\E.*\Q$footer\E/$styles/s) {
+        $tmpl->text( $template_text );
+        $replaced = 1;
+    }
+    unless ($replaced) {
+
+        # we're dealing with a template that wasn't modified before now
+        # we will need to backup the existing one to make sure the new
+        # style is applied properly.
+        my @ts = MT::Util::offset_time_list( time, $blog_id );
+        my $ts = sprintf "%04d-%02d-%02d %02d:%02d:%02d", $ts[5] + 1900,
+          $ts[4] + 1, @ts[ 3, 2, 1, 0 ];
+        my $backup = $tmpl->clone;
+        delete $backup->{column_values}
+          {id};    # make sure we don't overwrite original
+        delete $backup->{changed_cols}{id};
+        $backup->name( $backup->name . ' (Backup from ' . $ts . ')' );
+        $backup->outfile('');
+        $backup->linked_file( $tmpl->linked_file );
+        $backup->rebuild_me(0);
+        $backup->build_dynamic(0);
+        $backup->identifier(undef);
+        $backup->type('backup');
+        $backup->save;
+        $tmpl->linked_file('');    # make sure this one isn't linked now
+        $tmpl->identifier('styles');
+        $tmpl->text($styles);
+    }
+
+    # Putting the stylesheet back together again
+    $tmpl->save or return $app->json_error( $tmpl->errstr );
+
+    my $blog = MT->model('blog')->load($blog_id)    
+      or return $app->json_error( $app->translate('No such blog [_1]', $blog_id) );
+    $blog->page_layout($layout);
+    $blog->touch();
+    $blog->save();
+
+    # rebuild only the stylesheet! forcibly. with prejudice.
+    $app->rebuild_indexes(
+        BlogID   => $tmpl->blog_id,
+        Template => $tmpl,
+        Force    => 1
+    );
+
+    my $p = plugin();
+    $name =~ s/^repo_\d+:/local:/;
+    $name =~ s/\.css$//;
+    $p->set_config_value('current_theme_' . $blog_id, $name);
+    if ($layout) {
+        $p->set_config_value('current_layout_' . $blog_id, $layout);
+    } else {
+        $p->set_config_value('current_layout_' . $blog_id, undef);
+    }
+
+    return $app->json_result(
+        {
+            message =>
+              $app->translate("Successfully applied new theme selection.")
+        }
+    );
+}
+
+# Utility methods
+
+sub fetch_blogs {
+    my $app     = MT->app;
+    my $user    = $app->user;
+    my $blog_id = $app->param('blog_id');
+
+    my @blogs;
+    if ($blog_id) {
+        @blogs = MT::Blog->load($blog_id);
+    } else {
+        if ( $user->is_superuser() ) {
+            if ($blog_id) {
+                @blogs = MT::Blog->load($blog_id);
+            }
+        }
+        else {
+            my $args = { author_id => $user->id };
+            $args->{blog_id} = $blog_id if $blog_id;
+            require MT::Permission;
+            my @perms = MT::Permission->load( { author_id => $user->id } );
+            foreach my $perm (@perms) {
+                next unless $perm->can_edit_templates;
+                push @blogs, MT::Blog->load( $perm->blog_id );
+            }
+        }
+    }
+    my @styled_blogs;
+    foreach my $blog (@blogs) {
+        my $tmpl = load_style_template( $blog->id );
+        if ($tmpl) {
+            push @styled_blogs, $blog;
+        }
+    }
+    @styled_blogs = sort { $a->name cmp $b->name } @styled_blogs;
+
+    \@styled_blogs;
+}
+
+sub load_style_template {
+    my ($blog_id) = @_;
+
+    require MT::Template;
+    my $tmpl;
+
+    $tmpl = MT::Template->load(
+        {
+            blog_id    => $blog_id,
+            identifier => 'styles'
+        }
+    );
+
+    $tmpl ||= MT::Template->load(
+        {
+            blog_id => $blog_id,
+            outfile => "styles.css"
+        }
+    );
+
+    # MT 3.x era stylesheet file
+    $tmpl ||= MT::Template->load(
+        {
+            blog_id => $blog_id,
+            outfile => "styles-site.css"
+        }
+    );
+
+    unless ($tmpl) {
+
+        # Create one since we didn't find a candidate
+        $tmpl = new MT::Template;
+        $tmpl->blog_id($blog_id);
+        $tmpl->identifier('styles');
+        $tmpl->outfile("styles.css");
+        $tmpl->text(<<'EOT');
+@import url(<$MTStaticWebPath$>themes-base/blog.css);
+@import url(<$MTStaticWebPath$>themes/minimalist-red/styles.css);
+EOT
+        $tmpl->save();
+    }
+
+    $tmpl;
+}
+
+# pulls a list of themes available from a particular url
+sub fetch_themes {
+    my $app = MT->app;
+    my ($url) = @_;
+    return undef unless $url;
+
+    my $blog_id = $app->param('blog_id');
+    my $data    = {};
+
+  # If we have a url then we're specifying a specific theme (css) or repo (html)
+    # Pick up the file (html with <link>s or a css file with metadata)
+    my $user_agent = $app->new_ua;
+    my $request    = HTTP::Request->new( GET => $url );
+    my $response   = $user_agent->request($request);
+
+    # Make a repo if you've got a ton of links or an automagic entry if
+    # you're a css file
+    my $type = $response->headers->{'content-type'};
+    $type = shift @$type if ref $type eq 'ARRAY';
+    if ( $type =~ m!^text/css! ) {
+        $data->{auto}{url} = $url;
+        my $theme = fetch_theme( $url, ['collection:auto'] );
+        $data->{themes} = [$theme];
+    }
+    elsif ( $type =~ m!^text/html! ) {
+        my @repo_themes;
+        for my $link (
+            ref( $response->headers->{'link'} ) eq 'ARRAY'
+            ? @{ $response->headers->{'link'} }
+            : $response->headers->{'link'}
+          )
+        {
+            my ( $css, @parsed_link ) = split( /;/, $link );
+            $css =~ s/[<>]//g;
+            my %attr;
+            foreach (@parsed_link) {
+                my ( $name, $val ) = split /=/, $_, 2;
+                $name =~ s/^ //;
+                $val  =~ s/^['"]|['"]$//g;
+                next if $name eq '/';
+                $attr{ lc($name) } = $val;
+            }
+            next unless lc $attr{rel}  eq 'theme';
+            next unless lc $attr{type} eq 'text/x-theme';
+
+            # Fix for relative theme locations
+            if ($css !~ m!^https?://!) {
+                my $new_css = $url;
+                $new_css =~ s!/[a-z0-9_-]+\.[a-z]+?$|/$!/!;
+                $new_css .= $css;
+                $css = $new_css;
+            }
+            push @repo_themes, $css;
+        }
+
+        my $themes = [];
+        for my $repo_theme (@repo_themes) {
+            my $theme = fetch_theme( $repo_theme, [] );
+            push @$themes, $theme if $theme;
+        }
+        $data->{themes} = $themes;
+        if ( $data->{repo}{display_name} = $response->headers->{'title'} ) {
+            $data->{repo}{name} =
+              MT::Util::dirify( $data->{repo}{display_name} );
+        }
+        else {
+            $data->{repo}{display_name} = $url;
+            $data->{repo}{name}         = MT::Util::dirify($url);
+        }
+        $data->{repo}{url} = $url;
+    }
+    else {
+        return $app->error( $app->translate('Invalid URL: [_1]', $url) );
+    }
+
+    $data;
+}
+
+# sets up the object structure we return through json to populate
+# the mixer.
+sub make_themes {
+    my $app = MT->instance;
+
+    # categories
+    #   current    (for active theme)
+    #   repo       (for themes found at repo link)
+    #   my-designs (for themes that are stored locally)
+    #   mt-designs (for themes that are local and installed by default)
+    #   auto       (for link to a single css file)
+
+    # structure of "data"
+    #   categories => [ one, two, three ]  ie: 'current', 'repo'
+    #   themes => [
+    #       { theme }
+    #   ]
+    #   repo => {
+    #       display_name => 'display name',
+    #       name => 'repo name',
+    #       url => 'url of repo',
+    #   }
+
+# structure of "theme"
+#   theme => {
+#       name => 'theme_dir',
+#       imageSmall => 'link_to/thumbnail.gif',
+#       imageBig => 'link_to/thumbnail-large.gif',
+#       title => 'Theme Title',
+#       description => 'Theme description.',
+#       url_css => 'link_to/theme.css',
+#       url_zip => 'link_to/theme.zip',
+#       author => 'Author Name',
+#       author_url => 'http://author.com/'
+#       author_affiliation => 'Author Co.',
+#       layouts => "comma,delimited,layout,list"
+#       sort => 'theme_sortable_name',
+#       tags => ['association:tag']  ie, 'color:blue', 'designer:author', 'collection:repo'
+#   }
+
+    my ( $categories, $themes );
+    my $sys_root = File::Spec->catdir( $app->static_file_path, 'themes' );
+
+    # Generate our list of themes within the themeroot directory
+    my @sys_list = glob( File::Spec->catfile( $sys_root, "*" ) );
+    $categories->{'mt-designs'} = 1 if @sys_list;
+    for my $theme (@sys_list) {
+        my $theme_dir = $theme;
+        my $theme_url = $app->static_path . 'themes';
+        next unless -d $theme;
+        $theme =~ s/.*[\\\/]//;
+        $themes->{$theme} =
+          fetch_theme( $theme_dir, ['collection:mt-designs'], $theme_url,
+            $theme_dir );
+        $themes->{$theme}{name} = $themes->{$theme}{name};
+        $themes->{$theme}{prefix} = 'default';
+    }
+
+    my $themeroot =
+      File::Spec->catdir( $app->static_file_path, 'support', 'themes' );
+
+    # Generate our list of themes within the themeroot directory
+    my @themeroot_list = glob( File::Spec->catfile( $themeroot, "*" ) );
+    $categories->{'my-designs'} = 1 if @themeroot_list;
+    for my $theme (@themeroot_list) {
+        my $theme_dir = $theme;
+        next unless -d $theme;
+        $theme =~ s/.*[\\\/]//;
+        $themes->{$theme} =
+          fetch_theme( $theme_dir, ['collection:my-designs'] );
+        $themes->{$theme}{prefix} = 'local';
+    }
+
+    my $data = {
+        categories => [ keys %$categories ],
+        themes     => [ values %$themes ]
+    };
+
+    $data;
+}
+
+sub fetch_theme {
+    my $app = MT->app;
+    my ( $url, $tags, $baseurl, $basepath ) = @_;
+
+    my $theme;
+    my $stylesheet;
+    my $new_url;
+    my $themeroot;
+    if ( $url =~ m/^https?:/i ) {
+
+        # Pick up the css file
+        my $user_agent  = $app->new_ua;
+        my $css_request = HTTP::Request->new( GET => $url );
+        my $response    = $user_agent->request($css_request);
+        $stylesheet = $response->content if ($response->code >= 200) && ($response->code < 400);
+        return unless $stylesheet;
+
+# Break up the css url in to a couple useful pieces (generalize and break me out)
+        $theme = $url;
+        # discard any generic 'screen.css' filename
+        $theme =~ s!/screen.css$!!;
+        $theme =~ s/.*[\\\/]//;
+        my @url = split( /\//, $url );
+        for ( 0 .. ( scalar(@url) - 2 ) ) {
+            $new_url .= $url[$_] . '/';
+        }
+    }
+    else {
+        $themeroot = $basepath
+          || File::Spec->catdir( $app->static_file_path, 'support', 'themes' );
+        my $webthemeroot = $baseurl || $app->static_path . 'support/themes';
+
+        $theme = $url;
+        $theme =~ s/.*[\\\/]//;
+        my $file = File::Spec->catfile( $url, "$theme.css" );
+        $new_url = "$webthemeroot/$theme/";
+        if ( -e $file ) {
+            $stylesheet = file_mgr()->get_data($file);
+            $url        = $new_url . "$theme.css";
+        }
+        else {
+            $file = File::Spec->catfile( $url, "screen.css" );
+            if ( -e $file ) {
+                $stylesheet = file_mgr()->get_data($file);
+                $url        = $new_url . "screen.css";
+            }
+        }
+    }
+
+    # Pick up the metadata from the css
+    my @css_lines = split( /\r?\n/, $stylesheet || '' );
+    my $commented = 0;
+    my @comments;
+    for my $line (@css_lines) {
+        my $pos;
+        $pos = index( $line, "/*" );
+        unless ( $pos == -1 ) {
+            $line = substr( $line, $pos + 2 );
+            $commented = 1;
+        }
+        if ($commented) {
+            $pos = index( $line, "*/" );
+            unless ( $pos == -1 ) {
+                $line = substr( $line, 0, $pos );
+                $commented = 0;
+            }
+            push @comments, $line;
+        }
+    }
+
+    my $comment;
+    my %metadata;
+
+    # Trim me white space, yarr
+    for (@comments) {
+
+        # TBD: strip any "risky" content; we don't want any
+        # XSS in this content.
+        # Strip any null bytes
+        tr/\x00//d;
+        s/^\s+|\s+$//g;
+        my ( $key, $value ) = split( /:/, $_, 2 ) or next;
+        next unless defined $value;
+        $value =~ s/^\s+//;
+        $metadata{ lc $key } = $value;
+    }
+
+    my $thumbnail_link;
+    $thumbnail_link = $new_url . 'thumbnail.gif';
+    my $thumbnail_large_link;
+    $thumbnail_large_link = $new_url . 'thumbnail-large.gif';
+
+    require MT::Util;
+    my $data = {
+        name        => $theme,
+        description => $metadata{description} || '',
+        title       => $metadata{name} || '(Untitled)',
+        url         => $url,
+        imageSmall  => $thumbnail_link,
+        imageBig    => $thumbnail_large_link,
+        author      => $metadata{designer} || $metadata{author} || '',
+        author_url  => $metadata{designer_url} || $metadata{author_url} || '',
+        author_affiliation => $metadata{author_affiliation} || '',
+        layouts            => $metadata{layouts} || '',
+        'sort'             => $metadata{name} || '',
+        tags               => $tags,
+        blogs              => [],
+    };
+    $data;
+}
+
+sub plugin {
+    return MT->component('StyleCatcher');
+}
+
+1;
Index: /trunk/StyleCatcher/plugins/StyleCatcher/tmpl/view.tmpl
===================================================================
--- /trunk/StyleCatcher/plugins/StyleCatcher/tmpl/view.tmpl (revision 68)
+++ /trunk/StyleCatcher/plugins/StyleCatcher/tmpl/view.tmpl (revision 817)
@@ -1,476 +1,599 @@
-<TMPL_INCLUDE NAME="header.tmpl">
+<mt:setvarblock name="page_title"><__trans phrase="Select a Style"></mt:setvarblock>
+<mt:setvarblock name="html_head" append="1">
+<!-- stylecatcher -->
+<link rel="stylesheet" type="text/css" title="Default Layout" href="<mt:var name="plugin_static_uri">templates.css" />
+
+<script type="text/javascript" src="<mt:var name="static_uri">js/tc/mixer.js"></script>
+<script type="text/javascript" src="<mt:var name="static_uri">js/tc/mixer/tagmatch.js"></script>
+<script type="text/javascript" src="<mt:var name="static_uri">js/tc/mixer/display.js"></script>
+<script type="text/javascript" src="<mt:var name="static_uri">js/tc/client.js"></script>
 
 <!-- javascripts for this page -->
 
-        <script type="text/javascript">
-            var repoImg = "<TMPL_VAR NAME=PLUGIN_STATIC_URI>images/mixed-media.gif";
-            var selected;
-            var selected_blog_id;
-            var mixer;          
-            var matchCategory = /^category-/;
-            var categories = [];
-            var firstCategoryId;
-            var repo_urls = {};
-            var repos = [];
-
-            TC.attachLoadEvent( init );
-
-            function init() {
-                initMixer();
-                showDetails( false );
-
-<TMPL_IF NAME=THEMES_JSON>
-                var data = <TMPL_VAR NAME=THEMES_JSON>;
-                if (data.categories) {
-                    for (var i = 0; i < data.categories.length; i++)
-                        enableCategory(data.categories[i]);
-                }
-</TMPL_IF>
-
-                initCategories();
-                chooseCategory( firstCategoryId );
-
-                if (data.themes)
-                    loadThemes(data.themes, 'local');
-
-                <TMPL_IF NAME=AUTO_FETCH>
-                getStyles();
-                </TMPL_IF>
-            }
-
-            function enableCategory(cat) {
-                mixer.addTagIndexDisplay('display-'+cat, 1000, 'collection:'+cat);
-                var el = document.getElementById('category-' + cat);
-                if (el)
-                    el.style.display = 'block';
-            }
-
-            function initMixer()
-            {
-                mixer = new TC.Mixer();
-                // initialize mixer object
-                mixer.addSelectedDisplay( "display-details" );
-            }
-
-            function initCategories()
-            {
-                var element = document.getElementById( "categories" );
-                if( !element )
-                    return;
-                
-                categories.length = 0;
-                var elements = element.childNodes;
-                for( var i = 0; i < elements.length; i++ )
-                {
-                    element = elements[ i ];
-                    var categoryId = element.id;
-                    if( !categoryId )
-                        continue;
-                    
-                    if( !firstCategoryId ) {
-                        if (element.style.display != 'none') {
-                            firstCategoryId = categoryId;
+<script type="text/javascript">
+/* <![CDATA[ */
+    var repoImg = "<mt:var name="plugin_static_uri">images/mixed-media.gif";
+    var selected;
+    var blog_id = '<mt:var name="blog_id" escape="js">';
+    var dynamic_blog = <mt:if name="dynamic_blog">true<mt:else>false</mt:if>;
+    var mixer;          
+    var matchCategory = /^category-/;
+    var categories = [];
+    var firstCategoryId;
+    var repo_urls = {};
+    var repos = [];
+    var libraries = <mt:var name="style_library" to_json="1">;
+    var current_theme = '<mt:var name="current_theme">';
+    var current_layout = '<mt:var name="current_layout">';
+    var layout_names = {
+        "layout-wtt": "<__trans phrase="3-Columns, Wide, Thin, Thin" escape="js">",
+        "layout-twt": "<__trans phrase="3-Columns, Thin, Wide, Thin" escape="js">",
+        "layout-tw": "<__trans phrase="2-Columns, Thin, Wide" escape="js">",
+        "layout-wt": "<__trans phrase="2-Columns, Wide, Thin" escape="js">",
+        "layout-wm": "<__trans phrase="2-Columns, Wide, Medium" escape="js">",
+        "layout-mw": "<__trans phrase="2-Columns, Medium, Wide" escape="js">"
+    };
+
+    TC.attachLoadEvent( init );
+
+    function init() {
+        initMixer();
+
+<mt:if name="themes_json">
+        var data = <mt:var name="themes_json">;
+        if (data.categories) {
+            for (var i = 0; i < data.categories.length; i++)
+                enableCategory(data.categories[i]);
+        }
+</mt:if>
+
+        initCategories();
+        chooseCategory( firstCategoryId );
+
+        if (data.themes) {
+            loadThemes(data.themes);
+            if (current_theme) {
+                mixer.name = current_theme;
+                selectDesign();
+            } else {
+                showDetails();
+            }
+        }
+
+        <mt:if name="auto_fetch">
+        getStyles();
+        </mt:if>
+    }
+
+    function enableCategory(cat) {
+        mixer.addTagIndexDisplay('display-'+cat, 1000, 'collection:'+cat);
+        var el = getByID('category-' + cat);
+        if (el)
+            el.style.display = 'block';
+    }
+
+    function initMixer() {
+        mixer = new TC.Mixer();
+        // initialize mixer object
+        mixer.addSelectedDisplay( "display-details-content" );
+        mixer.onselect = selectDesign;
+    }
+
+    function initCategories() {
+        var element = getByID( "categories" );
+        if( !element )
+            return;
+        
+        categories.length = 0;
+        var elements = element.childNodes;
+        for( var i = 0; i < elements.length; i++ )
+        {
+            element = elements[ i ];
+            var categoryId = element.id;
+            if( !categoryId )
+                continue;
+            
+            if( !firstCategoryId ) {
+                if (element.style.display != 'none') {
+                    firstCategoryId = categoryId;
+                }
+            }
+            
+            var displayId = categoryId.replace( matchCategory, "display-" );
+            var display = getByID( displayId );
+
+            element.onclick = chooseCategoryClosure( categoryId );
+            TC.removeClassName( element, "category-selected" );
+
+            categories[ categoryId ] = {
+                "element" : element,
+                "display" : display
+            };
+        }
+    }
+
+    function chooseCategoryClosure( categoryId ) {
+        var func = function() { return chooseCategory( categoryId ); };
+        return func;
+    }
+
+    function chooseCategory( categoryId ) {
+        var titleElement = getByID( "selected-category-title" );
+
+        for( var id in categories ) {
+            var element = categories[ id ].element;
+            if (!element) continue;
+            var display = categories[ id ].display;
+
+            if( id == categoryId ) {
+                var repo_match = element.id.match(/^category-repo-(.+)$/);
+                if (repo_match) {
+                    var repo_id = repo_match[1];
+                    var repo;
+                    for (var i = 0; i < libraries.length; i++) {
+                        if (libraries[i].key == repo_id) {
+                            repo = libraries[i];
+                            break;
                         }
                     }
-                    
-                    var displayId = categoryId.replace( matchCategory, "display-" );
-                    var display = document.getElementById( displayId );
-                    
-                    element.onclick = chooseCategoryClosure( categoryId );
-                    TC.removeClassName( element, "category-selected" );
-                    
-                    categories[ categoryId ] =
-                    {
-                        "element" : element,
-                        "display" : display
-                    };
-                }
-            }
-
-            function chooseCategoryClosure( categoryId )
-            {
-                var func = function() { return chooseCategory( categoryId ); };
-                return func;
-            }
-
-            function chooseCategory( categoryId )
-            {
-                var titleElement = document.getElementById( "selected-category-title" );
+                    if (repo.url && !repo.loaded) {
+                        getStyles(repo_id, repo.url);
+                    }
+                }
+                TC.addClassName( element, "category-selected" );
+                display.style.display = "block";
                 
-                for( var id in categories )
-                {
-                    var element = categories[ id ].element;
-                    var display = categories[ id ].display;
-
-                    if( id == categoryId )
-                    {
-                        TC.addClassName( element, "category-selected" );
-                        display.style.display = "block";
-                        
-                        if( titleElement )
-                            titleElement.innerHTML = trans(element.firstChild.nextSibling.innerHTML);
-                        if (element.title.match(/^https?:/)) {
-                            var url_element = getByID("repo-url");
-                            url_element.value = element.title;
+                if( titleElement )
+                    titleElement.innerHTML = trans(element.firstChild.nextSibling.innerHTML);
+            }
+            else {
+                TC.removeClassName( element, "category-selected" );
+                if (display) display.style.display = "none";
+            }
+        }
+
+        // select first theme in category
+        mixer.name = '';
+        var select_design = getByID("select-design-controls");
+        TC.addClassName(select_design, "hidden");
+        mixer.display();
+        mixer.remix();
+    }
+
+    function showDetails() {
+        mixer.remix();
+    }
+
+    function selectDesign() {
+        var apply_button = getByID("apply-button");
+        var layout_select = getByID("layout-list");
+
+        var layouts;
+        if (mixer.name && mixer.entries[mixer.name])
+            layouts = mixer.entries[mixer.name].layouts;
+        var layout_list;
+        if (layouts) layout_list = layouts.split(/\s*,\s*/);
+        if (layouts && layout_list && layout_list.length) {
+            layout_select.options.length = 0;
+            var selected_layout = 0;
+            for (var i = 0; i < layout_list.length; i++) {
+                var opt = new Option(layout_names[layout_list[i]] ? layout_names[layout_list[i]] : layout_list[i], layout_list[i]);
+                layout_select.options[layout_select.options.length] = opt;
+                if (layout_list[i] == current_layout) {
+                    selected_layout = i;
+                }
+            }
+            layout_select.selectedIndex = selected_layout;
+            layout_select.disabled = false;
+        } else {
+            layout_select.options.length = 0;
+            layout_select.options[0] = new Option("<__trans phrase="None available" escape="js">", "");
+            layout_select.disabled = true;
+        }
+        showDetails();
+        var select_design = getByID("select-design-controls");
+        TC.removeClassName(select_design, "hidden");
+        updateApplyButton();
+    }
+
+    function updateApplyButton() {
+        var apply_button = getByID("apply-button");
+        var layout_select = getByID("layout-list");
+        var new_layout;
+        if (layout_select && layout_select.selectedIndex != -1) {
+            new_layout = layout_select.options[layout_select.selectedIndex].value;
+        }
+        var current_entry = mixer.entries[mixer.name];
+        if ((mixer.name == current_theme) && ((!new_layout || !current_layout) || ((new_layout && current_layout) && (new_layout == current_layout)))) {
+            // same theme, same layout. don't allow apply design to be enabled
+            apply_button.disabled = true;
+            TC.addClassName(apply_button, "disabled-button");
+        } else {
+            apply_button.disabled = false;
+            TC.removeClassName(apply_button, "disabled-button");
+        }
+    }
+
+    function applyDesign() {
+        // disable apply button; change text to "Applying..."
+        var btn = getByID("apply-button");
+        var layout = getByID("layout-list");
+        if (layout && layout.selectedIndex != -1) {
+            layout = layout.options[layout.selectedIndex].value;
+        }
+
+        selected = mixer.name;
+        var url = mixer.entries[mixer.name].url;
+
+        TC.addClassName(btn, "disabled-button");
+        btn.disabled = true;
+        btn.value = "<__trans phrase="Applying..." escape="js">";
+
+        var args = {
+            '__mode': 'stylecatcher_apply',
+            'url': url,
+            'magic_token': '<mt:var name="magic_token">',
+            'blog_id': blog_id,
+            'name': mixer.name
+        };
+        if (layout)
+            args['layout'] = layout;
+        var client = TC.Client.call({
+            'load': designApplied,
+            'uri': '<mt:var name="script_url">',
+            'method': 'POST',
+            'arguments': args
+        });
+    }
+
+    function designApplied(client, result) {
+        var btn = getByID("apply-button");
+        btn.value = "<__trans phrase="Apply Design" escape="js">";
+
+        var res;
+        try {
+            res = eval('(' + result + ')');
+        } catch (e) {
+        }
+        if (res && res.error) {
+            showMsg("<__trans phrase="Error applying theme: " escape="js">" + res.error, "theme-applied", "error");
+            TC.removeClassName(btn, "disabled-button");
+            btn.disabled = false;
+            return;
+        }
+
+        var layout = getByID("layout-list");
+        var new_layout;
+        if (layout && layout.selectedIndex != -1) {
+            new_layout = layout.options[layout.selectedIndex].value;
+        }
+        var entry = mixer.entries[selected];
+        if (entry) {
+            // make this the new 'current' theme
+            var found = false;
+            for (var i = 0; i < entry.tags.length; i++) {
+                if (entry.tags[i] == 'collection:current')
+                    found = true;
+            }
+            if (!found)
+                entry.tags[entry.tags.length] = 'collection:current';
+            /* we need to add the blog id of the blog that was
+               applied to for this entry */
+
+            found = false;
+            if (entry.blogs && entry.blogs.length) {
+                for (var i = 0; i < entry.blogs.length; i++) {
+                    if (entry.blogs[i] == blog_id)
+                        found = true;
+                }
+            }
+            if (!found)
+                entry.blogs[entry.blogs.length] = blog_id;
+
+            /* loop through all the 'current' themes and strip
+               this blog id from any that don't match the
+               selected theme */
+            for (var i in mixer.entries) {
+                if (i == selected)
+                    continue;
+                for (var j = 0; j < mixer.entries[i].blogs.length; j++) {
+                    if (mixer.entries[i].blogs[j] == blog_id) {
+                        mixer.entries[i].blogs.splice(j,1);
+                        break;
+                    }
+                }
+                if (mixer.entries[i].blogs.length == 0) {
+                    // no longer 'current'
+                    for (var j = 0; j < mixer.entries[i].tags.length; j++) {
+                        if (mixer.entries[i].tags[j] == 'collection:current') {
+                            mixer.entries[i].tags.splice(j,1);
+                            break;
                         }
                     }
-                    else
-                    {
-                        TC.removeClassName( element, "category-selected" );
-                        display.style.display = "none";
-                    }
-                }
-                
-                mixer.display();
-            }
-
-            function showDetails( show )
-            {
-                var showElement = document.getElementById( "show-details" );
-                var hideElement = document.getElementById( "hide-details" );
-                var detailsElement = document.getElementById( "details-wrapper" );
-                var templatesElement = document.getElementById( "templates-wrapper" );
-                
-                if( show )
-                {
-                    showElement.style.display = "none";
-                    hideElement.style.display = "block";
-                    detailsElement.style.display = "block";
-                    TC.removeClassName( templatesElement, "templates-wrapper-wide" );
-                    TC.addClassName( templatesElement, "templates-wrapper-narrow" );
-                }
-                else
-                {
-                    showElement.style.display = "block";
-                    hideElement.style.display = "none";
-                    detailsElement.style.display = "none";
-                    TC.addClassName( templatesElement, "templates-wrapper-wide" );
-                    TC.removeClassName( templatesElement, "templates-wrapper-narrow" );
-                }
-                
-                return false;
-            }
-
-            function applyDesign() {
-                // disable apply button; change text to "Applying..."
-<TMPL_IF NAME=SINGLE_BLOG>
-                var blog_id = '<TMPL_VAR NAME=SINGLE_BLOG>';
-<TMPL_ELSE>
-                var sel = getByID("select-blog");
-                var blog_id = sel.options[sel.selectedIndex].value;
-                if (!blog_id) {
-                    alert("<MT_TRANS phrase="Please select a weblog to apply this theme.">");
-                    return;
-                }
-</TMPL_IF>
-                var btn = getByID("apply-button");
-                if (!btn) return;
-
-                selected = mixer.name;
-                if (!selected) {
-                    alert("<MT_TRANS phrase="Please click on a theme before attempting to apply a new design to your blog.">");
-                    return;
-                }
-                var url = mixer.entries[mixer.name].url;
-
-                btn.disabled = true;
-                btn.value = "<MT_TRANS phrase="Applying...">";
-                selected_blog_id = blog_id;
-                var client = TC.Client.call({
-                    'load': designApplied,
-                    'uri': '<TMPL_VAR NAME=SCRIPT_URL>',
-                    'method': 'POST',
-                    'arguments': {
-                        '__mode': 'apply',
-                        'url': url,
-                        'magic_token': '<TMPL_VAR NAME=MAGIC_TOKEN>',
-                        'blog_id': blog_id
-                    }
-                });
-            }
-
-            function designApplied(client, result) {
-                var btn = getByID("apply-button");
-                var entry = mixer.entries[selected];
-                if (entry) {
-                    // make this the new 'current' theme
-                    var found = false;
-                    for (var i = 0; i < entry.tags.length; i++) {
-                        if (entry.tags[i] == 'collection:current')
-                            found = true;
-                    }
-                    if (!found)
-                        entry.tags[entry.tags.length] = 'collection:current';
-                    /* we need to add the blog id of the blog that was
-                       applied to for this entry */
-
-                    found = false;
-                    if (entry.blogs && entry.blogs.length) {
-                        for (var i = 0; i < entry.blogs.length; i++) {
-                            if (entry.blogs[i] == selected_blog_id)
-                                found = true;
+                }
+            }
+            mixer.createTagIndexes();
+        }
+
+        chooseCategory('category-current');
+        current_theme = selected;
+        mixer.name = selected;
+        var layout_changed = (current_layout && new_layout) && (current_layout != new_layout);
+        current_layout = new_layout;
+        selectDesign();
+
+        if (layout_changed && (!dynamic_blog)) {
+            showMsg("<__trans phrase="The selected theme has been applied, but as you have changed the layout, you will need to republish your blog to apply the new layout." escape="js">", 'theme-applied', "info", "all", blog_id);
+        } else {
+            showMsg("<__trans phrase="The selected theme has been applied!" escape="js">", 'theme-applied', "info");
+        }
+    }
+
+    function stylesLoaded(client, styles, repo_id) {
+        var btn = getByID("find-button");
+        TC.addClassName(TC.elementOrId("loading-styles"), "hidden");
+        TC.removeClassName(btn, "hidden");
+
+        var repo_num;
+        var cat;
+
+        var data;
+        try {
+            data = eval('('+styles+')');
+        } catch (e) {
+            showMsg("<__trans phrase="Error loading themes! -- [_1]" params="ERROR" escape="js">".replace(/ERROR/, styles), "error", "error");
+            return;
+        }
+        if (data.error) {
+            showMsg("<__trans phrase="Error loading themes! -- [_1]" params="ERROR" escape="js">".replace(/ERROR/, data.error), "error", "error");
+            return;
+        }
+        log(data.result);
+        if (!repo_id) {
+            if (data.result.repo) {
+                url = data.result.repo['url'];
+                if (repo_urls[url] != undefined) {
+                    repo_num = repo_urls[url];
+                    cat = 'repo_' + repo_num;
+                } else {
+                    repo_num = repos.length;
+                    repo_urls[url] = repo_num;
+
+                    // new repo -- create new
+                    // category for it
+                    cat = 'repo_' + repo_num;
+                    createCategory(cat, data.result.repo['display_name'], url);
+                }
+                repos[repo_num] = url;
+            }
+            if (data.result.auto) {
+                cat = 'more';
+                enableCategory(cat);
+            }
+            chooseCategory('category-' + cat);
+        } else {
+            var repo;
+            for (var i = 0; i < libraries.length; i++) {
+                if (libraries[i].key == repo_id) {
+                    repo = libraries[i];
+                    break;
+                }
+            }
+            if (repo) {
+                repo.loaded = true;
+                cat = 'repo-' + repo_id;
+                enableCategory(cat);
+                chooseCategory('category-' + cat);
+            }
+        }
+        if (data.result.themes)
+            loadThemes(data.result.themes, cat);
+    }
+
+    function createCategory(cat_name, cat_title, url) {
+        // things to create...
+        //   #1: new scrollbox under id 'categories'
+        /*
+                <div class="category" id="category-repo" title="Remote Styles" style="display: none">
+                    <img src="<mt:var name="plugin_static_uri">images/mixed-media.gif" alt="" /><span id="repo-name">Remote Styles</span>
+                </div>
+        */
+        var cats = getByID("categories");
+
+        element = document.createElement( "div" );
+        element.title = url;
+        element.className = "category";
+        element.id = "category-" + cat_name;
+
+        var img = document.createElement( "img" );
+        img.src = repoImg;
+        img.alt = "";
+        element.appendChild( img );
+
+        var spn = document.createElement( "span" );
+        spn.appendChild( document.createTextNode( cat_title ) );
+        element.appendChild( spn );
+
+        cats.appendChild( element );
+
+        //   #2: new div under id templates-wrapper
+        /*
+            <div class="scrollbox" id="display-repo" style="display: none;"></div>
+        */
+
+        var wrapper = getByID("templates-wrapper");
+
+        var div = document.createElement( "div" );
+        div.className = "scrollbox";
+        div.id = "display-" + cat_name;
+        wrapper.appendChild(div);
+        element.onclick = chooseCategoryClosure( element.id );
+
+        categories[ element.id ] =
+        {
+            "element" : element,
+            "display" : div
+        };
+
+        enableCategory(cat_name);
+    }
+
+    function loadThemes(themes, pfx) {
+        var names = {};
+        for (var i = 0; i < themes.length; i++) {
+            var prefix = themes[i]['prefix'];
+            if (!prefix) prefix = pfx;
+            var name = prefix + ':' + themes[i]['name'];
+            if (names[themes[i]['name']]) {
+                names[themes[i]['name']]++;
+                name += "_" + names[themes[i]['name']];
+            } else {
+                names[name] = 1;
+            }
+            themes[i]['name'] = name;
+            themes[i].tags[themes[i].tags.length] = "collection:"+prefix;
+            if (mixer.entries[name]) {
+                // merge in tags
+                var existing_tags = mixer.entries[name].tags;
+                if (existing_tags && existing_tags.length) {
+                    var new_tag_names = {};
+                    for (var j in themes[i].tags)
+                        new_tag_names[j] = true;
+                    for (var j = 0; j < existing_tags.length; j++) {
+                        if (!new_tag_names[existing_tags[j]]) {
+                            themes[i].tags[themes[i].tags.length] = existing_tags[j];
                         }
                     }
-                    if (!found)
-                        entry.blogs[entry.blogs.length] = selected_blog_id;
-
-                    /* loop through all the 'current' themes and strip
-                       this blog id from any that don't match the
-                       selected theme */
-                    for (var i in mixer.entries) {
-                        if (i == selected)
-                            continue;
-                        for (var j = 0; j < mixer.entries[i].blogs.length; j++) {
-                            if (mixer.entries[i].blogs[j] == selected_blog_id) {
-                                mixer.entries[i].blogs.splice(j,1);
-                                break;
-                            }
-                        }
-                        if (mixer.entries[i].blogs.length == 0) {
-                            // no longer 'current'
-                            for (var j = 0; j < mixer.entries[i].tags.length; j++) {
-                                if (mixer.entries[i].tags[j] == 'collection:current') {
-                                    mixer.entries[i].tags.splice(j,1);
-                                    break;
-                                }
-                            }
-                        }
-                    }
-                    mixer.createTagIndexes();
-                    mixer.remix();
-                }
-                chooseCategory('category-current');
-                if (!btn) return;
-                btn.value = "<MT_TRANS phrase="Choose this Design">";
-                btn.disabled = false;
-                alert(result);
-            }
-
-            function stylesLoaded(client, styles) {
-                var btn = getByID("find-button");
-                if (!btn) return;
-                var repo_num;
-                var cat;
-
-                var data;
-                try {
-                    data = eval('('+styles+')');
-                } catch (e) {
-                    alert(trans("Error loading themes! -- [_1]", styles));
-                    btn.value = "<MT_TRANS phrase="Find Style">";
-                    btn.disabled = false;
-                    return;
-                }
-                if (data.repo) {
-                    url = data.repo['url'];
-                    if (repo_urls[url] != undefined) {
-                        repo_num = repo_urls[url];
-                        cat = 'repo_' + repo_num;
-                    } else {
-                        repo_num = repos.length;
-                        repo_urls[url] = repo_num;
-
-                        // new repo -- create new
-                        // category for it
-                        cat = 'repo_' + repo_num;
-                        createCategory(cat, data.repo['display_name'], url);
-                    }
-                    repos[repo_num] = url;
-                }
-                if (data.auto) {
-                    cat = 'more';
-                    enableCategory(cat);
-                }
-                chooseCategory('category-' + cat);
-                if (data.themes)
-                    loadThemes(data.themes, cat);
-
-                btn.value = "<MT_TRANS phrase="Find Style">";
-                btn.disabled = false;
-            }
-
-            function createCategory(cat_name, cat_title, url) {
-                // things to create...
-                //   #1: new scrollbox under id 'categories'
-                /*
-                        <div class="category" id="category-repo" title="Remote Themes" style="display: none">
-                            <img src="<TMPL_VAR NAME=PLUGIN_STATIC_URI>images/mixed-media.gif" alt="" /><span id="repo-name">Remote Themes</span>
-                        </div>
-                */
-                var cats = getByID("categories");
-
-                element = document.createElement( "div" );
-                element.title = url;
-                element.className = "category";
-                element.id = "category-" + cat_name;
-
-                var img = document.createElement( "img" );
-                img.src = repoImg;
-                img.alt = "";
-                element.appendChild( img );
-
-                var spn = document.createElement( "span" );
-                spn.appendChild( document.createTextNode( cat_title ) );
-                element.appendChild( spn );
-
-                cats.appendChild( element );
-
-                //   #2: new div under id templates-wrapper
-                /*
-                    <div class="scrollbox" id="display-repo" style="display: none;"></div>
-                */
-
-                var wrapper = getByID("templates-wrapper");
-
-                var div = document.createElement( "div" );
-                div.className = "scrollbox";
-                div.id = "display-" + cat_name;
-                wrapper.appendChild(div);
-                element.onclick = chooseCategoryClosure( element.id );
-
-                categories[ element.id ] =
-                {
-                    "element" : element,
-                    "display" : div
-                };
-
-                enableCategory(cat_name);
-            }
-
-            function loadThemes(themes, prefix) {
-                var names = {};
-                for (var i = 0; i < themes.length; i++) {
-                    var name = prefix + '-' + themes[i]['name'];
-                    if (names[themes[i]['name']]) {
-                        names[themes[i]['name']]++;
-                        name += "_" + names[themes[i]['name']];
-                    } else {
-                        names[name] = 1;
-                    }
-                    themes[i]['name'] = name;
-                    themes[i].tags[themes[i].tags.length] = "collection:"+prefix;
-                    if (mixer.entries[name]) {
-                        // merge in tags
-                        var existing_tags = mixer.entries[name].tags;
-                        if (existing_tags && existing_tags.length) {
-                            var new_tag_names = {};
-                            for (var j in themes[i].tags)
-                                new_tag_names[j] = true;
-                            for (var j = 0; j < existing_tags.length; j++) {
-                                if (!new_tag_names[existing_tags[j]]) {
-                                    themes[i].tags[themes[i].tags.length] = existing_tags[j];
-                                }
-                            }
-                        }
-                    } else {
-                        mixer.addEntries(themes[i]);
-                    }
-                }
-                mixer.display();
-            }
-            function getStyles() {
-                var btn = getByID("find-button");
-                if (!btn) return;
-                btn.disabled = true;
-                btn.value = "<MT_TRANS phrase="Loading...">";
-
-                var el = getByID('repo-url');
-                if (!el) return;
-                var url = el.value;
-                var client = TC.Client.call({
-                    'load': stylesLoaded,
-                    'uri': '<TMPL_VAR NAME=SCRIPT_URL>',
-                    'method': 'POST',
-                    'arguments': {
-                        '__mode': 'js',
-                        'url': url
-                    }
-                });
-            }
-        </script>
-
-<!-- end script section -->
-
-        <div id="wrapper">
-
-<TMPL_IF NAME=BLOG_LOOP>
-
-         <p><MT_TRANS phrase="StyleCatcher lets you easily browse through styles and then apply them to your blog in just a few clicks. To find out more about Movable Type styles, or for new sources for styles, visit the <a href='http://www.sixapart.com/movabletype/styles'>Movable Type styles</a> page.">
-         <TMPL_IF NAME=CONFIG_LINK><MT_TRANS phrase=" To change the location of your local theme repository, <a href='<TMPL_VAR NAME=CONFIG_LINK>'> click here."></a></TMPL_IF></p>
-
-           <script type="text/javascript">
-           if(navigator.userAgent.indexOf("Firefox")!=-1){
-           var versionindex=navigator.userAgent.indexOf("Firefox")+8
-              document.writeln("<p><MT_TRANS phrase="Install <a href='http://greasemonkey.mozdev.org/'>GreaseMonkey</a>"> <a href='<TMPL_VAR NAME=SCRIPT_URL>?__mode=gm<TMPL_IF NAME=BLOG_ID>&amp;blog_id=<TMPL_VAR NAME=BLOG_ID></TMPL_IF>;file=stylecatcher.user.js'><MT_TRANS phrase="StyleCatcher user script."></a></p>");
-           }
-           </script>
-
-           <form method="get" action="<TMPL_VAR NAME=SCRIPT_URL>">
-              <strong><MT_TRANS phrase="Theme or Repository URL:"></strong>
-              <input class="repo-url" style="width:350px;" name="url" id="repo-url" value="<TMPL_VAR NAME=LAST_THEME_URL>" />
-              <input type="button" id="find-button" value="<MT_TRANS phrase="Find Styles">" onclick="getStyles()" />
-           </form>
-            <p><strong><MT_TRANS phrase="NOTE:"></strong> <MT_TRANS phrase="It will take a moment for themes to populate once you click 'Find Style'."></p> 
-            <p id="status-message" class="message" style="display: none"></p>
-            
-            <div id="template-picker">
-                <div id="categories-wrapper">
-                    <h2><MT_TRANS phrase="Categories"></h2>
-                    <div class="scrollbox" id="categories">
-<TMPL_IF NAME=SINGLE_BLOG>
-                        <div class="category" id="category-current" title="<MT_TRANS phrase="Current theme for your weblog">" style="display: none"><img src="<TMPL_VAR NAME=PLUGIN_STATIC_URI>images/top-rated.gif" alt="Your Current Theme" /><span><MT_TRANS phrase="Current Theme"></span>
-<TMPL_ELSE>
-                        <div class="category" id="category-current" title="<MT_TRANS phrase="Current themes for your weblogs">" style="display: none"><img src="<TMPL_VAR NAME=PLUGIN_STATIC_URI>images/top-rated.gif" alt="Your Current Themes" /><span><MT_TRANS phrase="Current Themes"></span>
-</TMPL_IF>
-                        </div>
-                        <div class="category" id="category-my-designs" title="<MT_TRANS phrase="Locally saved themes">" style="display: none"><img src="<TMPL_VAR NAME=PLUGIN_STATIC_URI>images/my-designs.gif" alt="my-designs" /><span><MT_TRANS phrase="Saved Themes"></span>
-                        </div>
-                        <div class="category" id="category-more" title="<MT_TRANS phrase="Single themes from the web">" style="display: none"><img src="<TMPL_VAR NAME=PLUGIN_STATIC_URI>images/featured.gif" alt="my-designs" /><span><MT_TRANS phrase="More Themes"></span>
-                        </div>
-                    </div>
-                </div>
-
-                <div id="templates-wrapper">
-                    <h2 id="selected-category-title"><MT_TRANS phrase="Templates"></h2>
-                    <div class="scrollbox" id="display-current" style="display: none;"></div>
-                    <div class="scrollbox" id="display-my-designs" style="display: none;"></div>
-                    <div class="scrollbox" id="display-more" style="display: none;"></div>
-                </div>
-
-                <div id="details-wrapper" style="display: none">
-                    <h2><MT_TRANS phrase="Details"></h2>
-                    <div id="display-details">
-                        <div class="tc-mixer-entry"></div>
-                    </div>
-                </div>
-
-                <a id="show-details" href="javascript:void(0);" onclick="return showDetails( true );" style="display: none"><MT_TRANS phrase="Show Details"></a>
-                <a id="hide-details" href="javascript:void(0);" onclick="return showDetails( false );" style="display: none"><MT_TRANS phrase="Hide Details"></a>
+                }
+            } else {
+                mixer.addEntries(themes[i]);
+            }
+        }
+        mixer.display();
+    }
+
+    function downloadStyles() {
+        var url;
+        if (url = prompt("<__trans phrase="Stylesheet or Repository URL" escape="js">")) {
+            getStyles(null, url);
+        }
+    }
+
+    function getStyles(repo_id, url) {
+        var btn = getByID("find-button");
+        TC.addClassName(btn, "hidden");
+        TC.removeClassName(TC.elementOrId("loading-styles"), "hidden");
+
+        var client = TC.Client.call({
+            'load': function(c,s) { stylesLoaded(c,s,repo_id) },
+            'uri': '<mt:var name="script_url">',
+            'method': 'POST',
+            'arguments': {
+                '__mode': 'stylecatcher_js',
+                'url': url
+            }
+        });
+    }
+/* ]]> */
+</script>
+<!-- end stylecatcher script section -->
+</mt:setvarblock>
+<mt:include name="include/header.tmpl">
+
+<div id="msg-block">
+</div>
+
+<div id="wrapper">
+
+<!--
+<form method="get" action="<mt:var name="script_url">">
+    <strong><__trans phrase="Stylesheet or Repository URL:"></strong>
+    <input class="repo-url" style="width:350px;" name="url" id="repo-url" value="<mt:var name="last_theme_url">" />
+    <input type="button" id="find-button" value="<__trans phrase="Download Styles">" onclick="getStyles()" />
+    <span class="hidden" id="loading-styles">
+        <img src="<mt:var name="static_uri">images/indicator.white.gif" height="16" width="16" alt="" />
+        <__trans phrase="Loading...">
+    </span>
+</form>
+-->
+
+<p id="status-message" class="message" style="display: none"></p>
+
+<div id="template-picker">
+    <div id="categories-wrapper">
+
+        <h2>
+            <span style="float:right">
+                <a href="javascript:void(0)" id="find-button" onclick="return downloadStyles()" class="icon-right icon-create" title="Download new styles">&nbsp;</a>
+
+            <span class="hidden" id="loading-styles">
+                <img src="<mt:var name="static_uri">images/indicator.white.gif" height="16" width="16" alt="" />
+            </span>
+
+            </span>
+
+            <__trans phrase="Categories">
+        </h2>
+
+        <div class="scrollbox" id="categories">
+            <div class="category" id="category-current" title="<__trans phrase="Current theme for your weblog">" style="display: none"><img src="<mt:var name="plugin_static_uri">images/top-rated.gif" alt="Your Current Style" /><span><__trans phrase="Current Style"></span>
             </div>
-            
-            <br class="clr" />
-
-            <div id="select-design-controls">
-<TMPL_UNLESS NAME=SINGLE_BLOG>
-            <select name="blog_id" id="select-blog">
-            <option value=""><MT_TRANS phrase="Select a Weblog..."></option>
-            <TMPL_LOOP NAME=BLOG_LOOP>
-            <option value="<TMPL_VAR NAME=BLOG_ID>"><TMPL_VAR NAME=BLOG_NAME></option>
-            </TMPL_LOOP>
-            </select>
-</TMPL_UNLESS>
-
-            <input type="button" name="choose" id="apply-button" onclick="applyDesign()" value="<MT_TRANS phrase="Apply Selected Design">" />
+            <div class="category" id="category-my-designs" title="<__trans phrase="Locally saved themes">" style="display: none"><img src="<mt:var name="plugin_static_uri">images/my-designs.gif" alt="my-designs" /><span><__trans phrase="Saved Styles"></span>
             </div>
-            <br class="clr" />
+            <div class="category" id="category-mt-designs" title="<__trans phrase="Default Styles">" style="display: none"><img src="<mt:var name="plugin_static_uri">images/gear.gif" alt="mt-designs" /><span><__trans phrase="Default Styles"></span>
+            </div>
+            <div class="category" id="category-more" title="<__trans phrase="Single themes from the web">" style="display: none"><img src="<mt:var name="plugin_static_uri">images/featured.gif" alt="my-designs" /><span><__trans phrase="More Styles"></span>
+            </div>
+            <mt:loop name="style_library">
+            <div class="category" id="category-repo-<mt:var name="key">" title="<mt:var name="description_label" escape="html">"><img src="<mt:var name="plugin_static_uri">images/featured.gif" alt="more-designs" /><span><mt:var name="label"></span>
+            </div>
+            </mt:loop>
         </div>
-
-<TMPL_ELSE>
-
-<p class="message">
-<MT_TRANS phrase="You don't appear to have any weblogs with a 'styles-site.css' template that you have rights to edit. Please check your weblog(s) for this template.">
-</p>
-
-</TMPL_IF>
-
-<TMPL_INCLUDE NAME="footer.tmpl">
+    </div>
+
+    <div id="templates-wrapper">
+        <h2 id="selected-category-title"><__trans phrase="Templates"></h2>
+        <div class="scrollbox" id="display-current" style="display: none;"></div>
+        <div class="scrollbox" id="display-my-designs" style="display: none;"></div>
+        <div class="scrollbox" id="display-mt-designs" style="display: none;"></div>
+        <div class="scrollbox" id="display-more" style="display: none;"></div>
+        <mt:loop name="style_library">
+        <div class="scrollbox" id="display-repo-<mt:var name="key">" style="display: none;"></div>
+        </mt:loop>
+    </div>
+
+    <div id="details-wrapper">
+        <h2><__trans phrase="Selected Design"></h2>
+        <div id="display-details">
+        <div id="select-design-controls" class="actions-bar">
+            <form method="get" action="">
+                <p>
+                    <label for="layout-list"><__trans phrase="Layout">:</label>
+                    <select id="layout-list" onchange="updateApplyButton()">
+                    </select>
+                </p>
+
+                <span class="button-actions actions">
+                <button
+                    type="button"
+                    accesskey="s"
+                    id="apply-button"
+                    title="<__trans phrase="Apply Design"> (s)"
+                    onclick="applyDesign()"
+                    class="primary-button"><__trans phrase="Apply Design"></button>
+                </span>
+            </form>
+        </div>
+
+        <div id="display-details-content"></div>
+
+
+    </div>
+
+</div>
+
+<br class="clr" />
+
+</div>
+
+<mt:include name="include/footer.tmpl">
Index: /trunk/StyleCatcher/mt-static/plugins/StyleCatcher/templates.css
===================================================================
--- /trunk/StyleCatcher/mt-static/plugins/StyleCatcher/templates.css (revision 7)
+++ /trunk/StyleCatcher/mt-static/plugins/StyleCatcher/templates.css (revision 817)
@@ -1,40 +1,40 @@
 td, input
 {
-	font-family: verdana, "lucida grande", geneva, arial, helvetica, sans-serif;
-	font-size: 11px;
-	font-weight: normal;
+    font-family: verdana, "lucida grande", geneva, arial, helvetica, sans-serif;
+    font-size: 11px;
+    font-weight: normal;
 }
 hr
 {
-	display: block;
-	line-height: 0;
-	height: 1px;
-	margin: 4px 0;
-	border: 0;
-	border-bottom: 1px #ccc solid;
-	padding: 0;
+    display: block;
+    line-height: 0;
+    height: 1px;
+    margin: 4px 0;
+    border: 0;
+    border-bottom: 1px #ccc solid;
+    padding: 0;
 }
 
 img
 {
-	border: 0;
+    border: 0;
 }
 
 .anchored
 {
-	position: relative;
-	top: 0;
-	left: 0;
-	width: 100%;
+    position: relative;
+    top: 0;
+    left: 0;
+    width: 100%;
 }
 
 .left
 {
-	float: left;
+    float: left;
 }
 
 .right
 {
-	float: right;
+    float: right;
 }
 
@@ -49,8 +49,8 @@
 .clr
 {
-	width: 0;
-	height: 0;
-	line-height: 0;
-	clear: both;
+    width: 0;
+    height: 0;
+    line-height: 0;
+    clear: both;
 }
 
@@ -84,5 +84,5 @@
 
 .inputs p {
-   line-height: 2.1em;
+   line-height: 2.1;
 }
 
@@ -115,21 +115,21 @@
 .tc-mixer-entry
 {
-	display: block;
-	float: left;
-	margin: 0;
-	border: 0;
-	padding: 8px;
-	height: 120px;
-	overflow: clip;
-	cursor: pointer;
-	-moz-border-radius: 8px;
+    display: block;
+    float: left;
+    margin: 0;
+    border: 0;
+    padding: 8px;
+    height: 120px;
+    overflow: clip;
+    cursor: pointer;
+    -moz-border-radius: 8px;
 }
 
 .tc-mixer-entry img
 {
-	width: 120px;
-	height: 90px;
-	border: 1px #999 solid;
-	margin: 0 0 2px 0;
+    width: 120px;
+    height: 90px;
+    border: 1px #999 solid;
+    margin: 0 0 2px 0;
 }
 
@@ -150,30 +150,30 @@
 #categories hr
 {
-	margin: 4px;
-	position: relative;
-	clear: both;
+    margin: 4px;
+    position: relative;
+    clear: both;
 }
 
 .hr
 {
-	display: block;
-	position: relative;
-	height: 0;
-	margin: 4px;
-	border-bottom: 1px solid #ccc;
-	padding: 0;
-	line-height: 0;
+    display: block;
+    position: relative;
+    height: 0;
+    margin: 4px;
+    border-bottom: 1px solid #ccc;
+    padding: 0;
+    line-height: 0;
 }
 
 .category
 {
-	display: block;
-	position: relative;
-	clear: both;
-	margin: 0;
-	border: 0;
-	padding: 4px;
-	cursor: pointer;
-	-moz-border-radius: 8px;
+    display: block;
+    position: relative;
+    clear: both;
+    margin: 0;
+    border: 0;
+    padding: 4px;
+    cursor: pointer;
+    -moz-border-radius: 8px;
 }
 
@@ -184,50 +184,50 @@
 .display-mini
 {
-	display: block;
-	position: relative;
-	left: 22px;
-	width: 104px;
-	margin: 0;
-	border: 0;
-	padding: 0;
-	line-height: 0;
+    display: block;
+    position: relative;
+    left: 22px;
+    width: 400px;
+    margin: 0;
+    border: 0;
+    padding: 0;
+    line-height: 0;
 }
 
 html>body .display-mini
 {
-	float: none;
-	clear: none;
+    float: none;
+    clear: none;
 }
 
 .display-mini .tc-mixer-entry
 {
-	display: inline;
-	float: none;
-	margin: 0 3px 0 0;
-	border: 0;
-	padding: 0;
-	height: auto;
-	overflow: clip;
-	cursor: pointer;
-	-moz-border-radius: 0;
+    display: inline;
+    float: none;
+    margin: 0 3px 0 0;
+    border: 0;
+    padding: 0;
+    height: auto;
+    overflow: clip;
+    cursor: pointer;
+    -moz-border-radius: 0;
 }
 
 .display-mini .tc-mixer-selected
 {
-	background: transparent;
+    background: transparent;
 }
 
 .display-mini img
 {
-	width: auto;
-	height: 12px;
-	margin: 0;
-	border: 0;
-	padding: 0;
+    width: auto;
+    height: 12px;
+    margin: 0;
+    border: 0;
+    padding: 0;
 }
 
 .display-mini .title .content
 {
-	display: none;
+    display: none;
 }
 
@@ -239,9 +239,9 @@
 h2
 {
-	font-size: 1em;
-	font-weight: bold;
-	margin: 0 0 4px 0;
-	padding: 0;
-	border: 0;
+    font-size: 1em;
+    font-weight: bold;
+    margin: 0 0 4px 0;
+    padding: 0;
+    border: 0;
 }
 
@@ -249,8 +249,8 @@
 #hide-details
 {
-	position: absolute;
-	right: 0;
-	top: 0;
-	font-size: 11px;
+    position: absolute;
+    right: 0;
+    top: 0;
+    font-size: 11px;
 }
 
@@ -268,84 +268,95 @@
 #wrapper
 {
-	width: 720px;
-	margin: 8px 0px;
+    width: 920px;
+    margin: 8px 0px;
 }
 
 #template-picker
 {
-	position: relative;
-	top: 8px;
-	left: 0;
-	width: 720px;
-	height: 450px;
+    position: relative;
+    top: 8px;
+    left: 0;
+    width: 720px;
+    height: 450px;
 }
 
 #categories-wrapper
 {
-	position: absolute;
-	left: 0;
-	top: 0;
-	width: 160px;
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 150px;
 }
 
 #templates-wrapper
 {
-	position: absolute;
-	left: 172px;
-	top: 0;
-}
-
-.templates-wrapper-wide { width: 575px; }
-.templates-wrapper-narrow { width: 180px; }
+    position: absolute;
+    left: 161px;
+    top: 0;
+    width: 440px;
+    height: 450px;
+}
 
 #details-wrapper
 {
-	position: absolute;
-	left: 364px;
-	top: 0;
-	width: 356px;
+    position: absolute;
+    left: 600px;
+    top: 0;
+    width: 300px;
 }
 
 .scrollbox
 {
-	display: block;
-	position: relative;
-	top: 0;
-	left: 0;
-	width: auto;
-	height: 410px;
-	overflow: auto;
-	margin: 0;
-	border: 1px #999 solid;
-	padding: 4px;
+    display: block;
+    position: relative;
+    top: 0;
+    left: 0;
+    width: auto;
+    height: 410px;
+    overflow: auto;
+    margin: 0;
+    border: 1px #999 solid;
+    padding: 4px;
 }
 
 #display-details
 {
-	position: relative;
-	left: 0;
-	top: 0;
-	height: 354px;
-	width: auto;
-	overflow: clip;
-	border: 1px #999 solid;
-	background-color: #eee;
-	padding: 32px 24px;
+    position: relative;
+    left: 0;
+    top: 0;
+    height: 398px;
+    width: auto;
+    overflow: clip;
+    border: 1px #999 solid;
+    background-color: #eee;
+    padding: 10px 10px;
+}
+
+#select-design-controls {
+    position: absolute;
+    width: 280px;
+    top: auto;
+    bottom: 10px;
+    margin-right: 10px;
+}
+
+.actions-bar .button-actions {
+    float: right;
 }
 
 #display-details .tc-mixer-entry
 {
-	display: block;
-	float: none;
-	margin: 0;
-	border: 0;
-	padding: 0;
-	height: auto;
-	overflow: display;
+    display: block;
+    float: none;
+    margin: 0;
+    border: 0;
+    padding: 0;
+    height: auto;
+    overflow: display;
 }
 
 #display-details .tc-mixer-selected
 {
-	background: transparent;
+    background: transparent;
 }
 
@@ -364,3 +375,7 @@
 #display-details .tags .content { display: inline; height: auto; word-spacing: 0.5em; }*/
 
-#display-details  img { width: 99%; height: auto; margin: 0 0 4px 0; }
+#display-details  img {
+    width: 278px;
+    height: 209px;
+    margin: 0 0 4px 0;
+}
