Monday, November 08, 2010 at 12:05 AM.

	<<2/1/02; 10:35:16 PM by JES
		<<Added a link to the Create Theme page.
	<<1/27/02; 4:47:29 PM by JES
		<<After applying a Theme, publish the home page, so the new Theme will be visible on the public site right away.
	<<1/14/02; 11:20:11 AM by JES
		<<Add each Theme to the list within a try block, so that if the .fttb file is corrupt, or doesn't contain the data that we expect, you won't get a macro error.
	<<1/1/02; 10:18:32 PM by JES
		<<Added a warning below the Themes list, before the Apply Theme button. Added a help link.
		<<Don't render the confirmation page as a box. No Yes/No buttons -- use an Apply Theme button instead. Changed the title of the confirm page to "Themes: Confirm".
	<<12/31/01; 3:01:01 AM by JES
		<<Created. Render a page that lists the available Themes, and allows the user to apply a Theme to their website.

local (htmltext, indentlevel=0);
on add (s) {
	htmltext = htmltext + string.filledstring ("\t", indentlevel) + s + "\r"};
local (pta = html.getpagetableaddress ());
local (adrblog = radio.weblog.init ());

pta^.title = radio.string.getLocalizedString ("viewThemes.title");

if pta^.method == "POST" {
	<<scratchpad.params = pta^.radioResponder.postArgs; edit (@scratchpad.params)
	local (adrargs = @pta^.radioResponder.postArgs);
	if defined (adrargs^.applyTheme) { //the user clicked the Apply Theme button -- render confirm page
		pta^.title = radio.string.getlocalizedstring ("viewThemes.confirmPageTitle");
		local (shortName = adrargs^.theme);
		local (f = radio.theme.getThemeFilePath (shortName));
		local (theme);
		radio.theme.importThemeFile (f, @theme);
		bundle { //render the confirm form
			<<bundle //start the table
				<<add ("<table border=\"0\" cellpadding=\"3\" cellspacing=\"1\" bgcolor=\"" + + "\" width=\"350\">"); indentlevel++
			<<bundle //confirm heading
				<<add ("<tr bgcolor=\"" + + "\"><td align=\"left\"><b>" + radio.string.getlocalizedString ("viewThemes.confirm") + "</b></td></tr>")
			<<add ("<tr bgcolor=\"" + + "\"><td>"); indentlevel++
			add ("<form method=\"POST\">");
			local (t); new (tableType, @t);
			t.theme =;
			add (radio.string.getLocalizedString ("viewThemes.confirmText", @t));
			add ("<input type=\"hidden\" name=\"theme\" value=\"" + shortName +"\">");
			add ("<p>");
			bundle { //apply theme button
				add ("<input type=\"submit\" name=\"confirmApplyTheme\" value=\" " + radio.string.getlocalizedstring ("viewThemes.applyTheme") + " \">  </p></form>")}};
			<<bundle //yes and no buttons
				<<add ("<input type=\"submit\" name=\"dontApplyTheme\" value=\" " + radio.string.getlocalizedstring ("viewThemes.noButton") + " \">  ")
				<<add ("<input type=\"submit\" name=\"confirmApplyTheme\" value=\" " + radio.string.getlocalizedstring ("viewThemes.yesButton") + " \">  </p></form>")
			<<add ("</td></tr>"); indentlevel--
			<<add ("</table>"); indentlevel--
		return (htmltext)};
	if defined (adrargs^.confirmApplyTheme) { //the user approved application of the Theme
		local (shortName = adrargs^.theme);
		local (f = radio.theme.getThemeFilePath (shortName));
		local (theme);
		radio.theme.importThemeFile (f, @theme);
		radio.theme.apply.main (@theme);
		radio.weblog.publish ();
		adrblog^.prefs.lastThemeApplied = shortName;
		local (t); new (tableType, @t);
		t.theme =;
		bundle { //set confirm message = radio.string.getlocalizedstring ("viewThemes.themeAppliedConfirm", @t)};
		radio.webserver.redirect (pta^.uri);
		return ("")}};

bundle { //list Themes
	local (lastThemeApplied = "default");
	if defined (adrblog^.prefs.lastThemeApplied) {
		lastThemeApplied = adrblog^.prefs.lastThemeApplied};
	bundle { //add explanatory text
		local (t); new (tableType, @t);
		t.createThemeUrl =;
		add (radio.string.getlocalizedstring ("viewThemes.explanation", @t) + " " + radio.userInterface.helpLink ("The Themes command") + "<p>")};
	bundle { //possibly add a confirm message
		if defined ( {
			add ("<br><font color=\"navy\">" + + "</font><br>");
			delete (}};
	add ("<form method=\"POST\">"); indentlevel++;
	bundle { //start the table
		add ("<table cellspacing=\"0\" cellpadding=\"6\" border=\"0\">"); indentlevel++};
	bundle { //add the themes
		local (folder = radio.theme.getThemesFolder ());
		local (floop);
		fileloop (floop in folder) {
			try { //1/14/02 JES: don't fail if the .fttb doesn't contain what we expect
				local (fname = file.fileFromPath (floop));
				if not (string.lower (fname) endsWith ".fttb") {
				local (themeTable);
				radio.theme.importThemeFile (floop, @themeTable);
				add ("<tr>"); indentlevel++;
				local (adrinfo =;
				local (author = adrinfo^.author);
				local (authorEmail = adrinfo^.authorEmail);
				local (createDate = adrinfo^.creationDate);
				local (description = adrinfo^.description);
				local (name = adrinfo^.name);
				local (siteUrl = adrinfo^.siteUrl);
				local (shortName = radio.theme.getShortName (name));
				bundle { //radio button
					add ("<td valign=\"top\">"); indentlevel++;
					if string.lower (shortName) == string.lower (lastThemeApplied) {
						add ("<input type=\"radio\" name=\"theme\" value=\"" + shortName + "\" checked>")}
					else {
						add ("<input type=\"radio\" name=\"theme\" value=\"" + shortName + "\">")};
					add ("</td>"); indentlevel--};
				bundle { //theme link, description and credits
					add ("<td valign=\"top\">"); indentlevel++;
					add ("<b><a href=\"" + siteUrl + "\">" + name + "</a></b><br>");
					add ("<font size=\"-1\" class=\"small\">" + description + "</font><br>");
					bundle { //add credits
						local (t); new (tableType, @t); = "<a href=\"mailto:" + authorEmail + "\">" + author + "</a>"; = createDate;
						add ("<font size=\"-1\" class=\"small\">" + radio.string.getlocalizedstring ("viewThemes.createdBy", @t) + "</font>")};
					add ("</td>"); indentlevel--};
				add ("</tr>"); indentlevel--}}};
	add ("</table>"); indentlevel--;
	bundle { //warning text
		add ("<p>" + radio.string.getlocalizedstring ("viewThemes.warning") + "</p>")};
	bundle { //add submit button
		add ("<p><input type=\"submit\" name=\"applyTheme\" value=\"" + radio.string.getlocalizedstring ("viewThemes.applyTheme") + "\"></p>")};
	add ("</form>"); indentlevel--};

return (htmltext)

This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.