Here's what you'll see in the markup...
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script type="text/javascript">djConfig =
{"baseRelativePath":"/assets/static/dojo-0.4.3/","preventBackButtonFix":false,"parseWidgets":false,"locale":"en"}
</script>
<script type="text/javascript" src="/assets/static/dojo-0.4.3/dojo.js"></script><script
type="text/javascript" src="/assets/static/dojo-0.4.3/dojo2.js"></script>
<script type="text/javascript">
dojo.registerModulePath("tapestry", "/assets/static/tapestry");
</script>
<script type="text/javascript" src="/assets/static/tapestry/core.js"></script>
<script type="text/javascript">
dojo.require("tapestry.namespace");
tapestry.requestEncoding='UTF-8';
</script>
<!-- Application: trails -->
<!-- Page: Home -->
<!-- Generated: Tue Oct 09 18:38:01 EDT 2007 -->
<html>
<head>
<meta name="generator" content="Tapestry Application Framework, version 4.1.3"
/>
<title>Best WEB Application on the planet!</title>
<link rel="stylesheet" type="text/css" title="don't select"
href="/styles/tapestryskin/theme.css" />
<style type="text/css">
<!-- Checkout these Custom <HEAD> widget...Style Overrides -->
body {
padding: 5;
margin: 5;
background: #fff url(
/BlobService.svc?class=org.trails.demo.AdminLayout&contentType=image/gif&fileName=backgd-original.gif&id=1&property=background
) top left repeat;
}
div#main {
}
div#splash {
background: #fff url(
/BlobService.svc?class=org.trails.demo.AdminLayout&contentType=image/jpeg&fileName=bae.parts.splash.jpg&id=1&property=splash
) top left no-repeat;
}
div#page {
}
</style>
</head>
<body id="Body">
<script type="text/javascript"><!--
dojo.require("tapestry.widget.Widget");
dojo.require("dojo.widget.*");
dojo.require("dojo.html");
// --></script>
<div id="page">
<!-- header segment #1 -->
<a id="PageLink" href="/Home.page">
<div id="header">
Best regards
Ken in nashua
From: [EMAIL PROTECTED]
To: users@tapestry.apache.org
Subject: Re: T4 Custom Component Questions
Date: Tue, 9 Oct 2007 18:15:03 -0400
Hi Norm,
Below is text from a CustomHead I wrote. It does header/splash/icon images for
appfuse css-framework. Integrated to trails features I developed of course.
It will give you some insights for the shell derivative.
I am a trails developer. So anything trails you might want to tailor.
Can't help you with the menu.
Best regards
Ken in nashua
Customhead.java
-------------------------------------
package org.trails.demo.components;
import java.util.Date;
import java.util.Iterator;
import org.apache.hivemind.HiveMind;
import org.apache.tapestry.IAsset;
import org.apache.tapestry.IMarkupWriter;
import org.apache.tapestry.IPage;
import org.apache.tapestry.IRender;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.IScript;
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.annotations.Asset;
import org.apache.tapestry.annotations.ComponentClass;
import org.apache.tapestry.annotations.InjectObject;
import org.apache.tapestry.annotations.InjectScript;
import org.apache.tapestry.annotations.InjectState;
import org.apache.tapestry.annotations.Parameter;
import org.apache.tapestry.coerce.ObjectArrayToIteratorConverter;
import org.apache.tapestry.engine.ILink;
import org.apache.tapestry.html.Shell;
import org.apache.tapestry.json.IJSONWriter;
import org.apache.tapestry.spec.IApplicationSpecification;
import org.trails.component.blob.BlobDownloadService;
import org.trails.component.blob.TrailsBlobAsset;
import org.trails.demo.AdminLayout;
/**
* Background Usage...
*
* <html jwcid="@Shell" title="Trails" stylesheet="ognl:assets.stylesheet">
*
* The <html> tag is basically the shell to a page. It encompasses <head><body>
*
* @Shell is a tapestry component that intercepts <html> parameters and renders
* according to it's semantics. We can do whatever we like in
* @Shell according to it's defined parameters.
*
* This component is an extension to
* @Shell. We instrument additional features with the main purpose of rendering
* a custom <head>
*
* In short...This guy reaches into the database and applies logo, header and
* background to default css within the <html> shell. internally, tedius
* renderings will occur to override specific css-framework fragments and
* styles.
*
* @author kenneth.colassi [EMAIL PROTECTED]
*
*/
@ComponentClass(allowBody = true, allowInformalParameters = true)
public abstract class CustomHead extends Shell
{
@InjectState("adminLayout")
public abstract AdminLayout getLayout();
public abstract void setLayout(AdminLayout layout);
@InjectObject("service:trails.core.BlobService")
public abstract BlobDownloadService getDownloadService();
private static final String generatorContent = "Tapestry Application Framework,
version " + Tapestry.VERSION;
@Asset("/js/dojo-0.4.3/dojo.js")
public abstract IAsset getDefaultDojoSource();
@Asset("/dojo-0.4.3/")
public abstract IAsset getDefaultDojoPath();
@Asset("/tapestry/core.js")
public abstract IAsset getDefaultTapestrySource();
@Asset("/tapestry/")
public abstract IAsset getDefaultTapestryPath();
@Asset("/styles/tapestryskin/theme.css")
public abstract IAsset getTheme();
/**
* Injected via jwc - readonly, yes that means no setter
*/
public abstract IApplicationSpecification getApplicationSpecification();
/**
* Injected via jwc - readonly, yes that means no setter
*/
@InjectScript("CustomHead.script")
public abstract IScript getScript();
@Parameter(required = true, cache = true)
public abstract IAsset getStylesheet();
public abstract void setStylesheet(IAsset stylesheet);
@Parameter(required = true, cache = true)
public abstract String getTitle();
public abstract void setTitle(String title);
public abstract IRender getDelegate();
public abstract IRender getAjaxDelegate();
public void renderComponent(IJSONWriter writer, IRequestCycle cycle)
{
}
@Override
protected void prepareForRender(IRequestCycle cycle)
{
getLayout();
super.prepareForRender(cycle);
}
@Override
protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
{
long startTime = 0;
boolean rewinding = cycle.isRewinding();
if (!rewinding)
{
startTime = System.currentTimeMillis();
writeDocType(writer, cycle);
IPage page = getPage();
writer.comment("Application: " +
getApplicationSpecification().getName());
writer.comment("Page: " + page.getPageName());
writer.comment("Generated: " + new Date());
writer.begin("html");
renderInformalParameters(writer, cycle);
writer.println();
writer.begin("head");
writer.println();
writer.beginEmpty("meta");
writer.attribute("name", "generator");
writer.attribute("content", generatorContent);
writer.println();
if (getRenderContentType())
{
/**
* This should not be necessary (the HTTP content type should be
* sufficient), but some browsers require it for some reason
*/
writer.beginEmpty("meta");
writer.attribute("http-equiv", "Content-Type");
writer.attribute("content", writer.getContentType());
writer.println();
}
if (getLayout() != null)
{
writer.begin("title");
writer.print(getLayout().getTitle());
writer.end(); // title
writer.println();
}
IAsset stylesheet = getStylesheet();
if (stylesheet != null)
{
writeStylesheetLink(writer, cycle, stylesheet.buildURL());
}
ObjectArrayToIteratorConverter conv = new
ObjectArrayToIteratorConverter();
if (getStylesheets() != null)
{
Iterator i = (Iterator) conv.convertValue((Object[])
getStylesheets());
if (i != null)
{
while (i.hasNext())
{
stylesheet = (IAsset) i.next();
writeStylesheetLink(writer, cycle,
stylesheet.buildURL());
}
}
}
writeRefresh(writer, cycle);
if (getLayout() != null &&
getLayout().getBackground().getFileName() != null)
{
writeStyleOverride(writer, cycle);
}
writer.end();
writer.flush();
}
// Render the body, the actual page content
renderBody(writer, cycle);
if (!rewinding)
{
writer.end(); // html
writer.println();
long endTime = System.currentTimeMillis();
writer.comment("Render time: ~ " + (endTime - startTime) + "ms");
}
}
private void writeDocType(IMarkupWriter writer, IRequestCycle cycle)
{
String doctype = getDoctype();
if (HiveMind.isNonBlank(doctype))
{
writer.printRaw("<!DOCTYPE " + doctype + ">");
writer.println();
}
}
private void writeRefresh(IMarkupWriter writer, IRequestCycle cycle)
{
int refresh = getRefresh();
if (refresh <= 0)
{
return;
}
// Here comes the tricky part ... have to assemble a complete URL
// for the current page.
String pageName = cycle.getPage().getPageName();
ILink link = getPageService().getLink(false, new String[] { pageName });
StringBuffer buffer = new StringBuffer();
buffer.append(refresh);
buffer.append("; URL=");
buffer.append(link.getAbsoluteURL());
// Write out the <meta> tag
writer.println();
writer.println();
writer.beginEmpty("meta");
writer.attribute("http-equiv", "Refresh");
writer.attribute("content", buffer.toString());
writer.println();
writer.println();
}
private void writeStylesheetLink(IMarkupWriter writer, IRequestCycle cycle,
String stylesheetBase)
{
writer.beginEmpty("link");
writer.attribute("rel", "stylesheet");
writer.attribute("type", "text/css");
writer.attribute("title", "don't select");
String sessionStrippedURL = getTheme().buildURL();
if (sessionStrippedURL.contains(";"))
sessionStrippedURL = sessionStrippedURL.substring(0,
sessionStrippedURL.indexOf(";"));
writer.attribute("href", sessionStrippedURL);
writer.println();
writer.println();
}
private void writeStyleOverride(IMarkupWriter writer, IRequestCycle cycle)
{
writer.begin("style");
writer.attribute("type", "text/css");
writer.println();
writer.comment("Checkout these Custom <HEAD> widget...Style Overrides");
doBodyOverride(writer, cycle);
doMainOverride(writer, cycle);
doSplashOverride(writer, cycle);
doPageOverride(writer, cycle);
writer.end(); // style
writer.println();
writer.println();
}
private void writeJavaScript(IMarkupWriter writer, IRequestCycle cycle,
IAsset javascript)
{
writer.beginEmpty("script");
writer.attribute("type", "text/javascript");
writer.attribute("src", javascript.buildURL());
writer.closeTag();
writer.println();
writer.println();
}
private void doBodyOverride(IMarkupWriter writer, IRequestCycle cycle)
{
writer.println();
writer.printRaw("\tbody {");
writer.println();
writer.printRaw("\t\tpadding: 5;");
writer.println();
writer.printRaw("\t\tmargin: 5;");
writer.println();
String blobRenderString = "/BlobService.svc?class=" +
getLayout().getClass().getCanonicalName()
+ "&contentType=" + getLayout().getBackground().getContentType().toString() +
"&fileName="
+ getLayout().getBackground().getFileName().toString() + "&id="
+ getLayout().getId().toString()
+ "&property=background";
writer.printRaw("\t\tbackground: #fff url( " + blobRenderString + " ) top
left repeat;");
writer.println();
writer.printRaw("\t}");
writer.println();
}
private void doSplashOverride(IMarkupWriter writer, IRequestCycle cycle)
{
writer.println();
writer.printRaw("\tdiv#splash {");
writer.println();
String blobRenderString = "/BlobService.svc?class=" +
getLayout().getClass().getCanonicalName()
+ "&contentType=" + getLayout().getSplash().getContentType().toString() +
"&fileName="
+ getLayout().getSplash().getFileName().toString() + "&id=" +
getLayout().getId().toString()
+ "&property=splash";
writer.printRaw("\t\tbackground: #fff url( " + blobRenderString + " ) top
left no-repeat;");
writer.println();
writer.printRaw("\t}");
writer.println();
}
private void doMainOverride(IMarkupWriter writer, IRequestCycle cycle)
{
writer.println();
writer.printRaw("\tdiv#main {");
writer.println();
writer.printRaw("\t}");
writer.println();
}
private void doPageOverride(IMarkupWriter writer, IRequestCycle cycle)
{
writer.println();
writer.printRaw("\tdiv#page {");
writer.println();
writer.println();
String blobRenderString = "/BlobService.svc?class=" +
getLayout().getClass().getCanonicalName()
+ "&contentType=" + getLayout().getBackground().getContentType().toString() +
"&fileName="
+ getLayout().getBackground().getFileName().toString() + "&id="
+ getLayout().getId().toString()
+ "&property=background";
writer.printRaw("\t}");
writer.println();
}
private void doHeaderOverride(IMarkupWriter writer, IRequestCycle cycle)
{
writer.println();
writer.printRaw("\tdiv#header {");
writer.println();
writer.printRaw("\t\theight: 94px;");
writer.println();
writer.printRaw("\t\twidth: 740px;");
writer.println();
String blobRenderString = "/BlobService.svc?class=" +
getLayout().getClass().getCanonicalName()
+ "&contentType=" + getLayout().getHeader().getContentType().toString() +
"&fileName="
+ getLayout().getHeader().getFileName().toString() + "&id=" +
getLayout().getId().toString()
+ "&property=header";
writer.printRaw("\t\tbackground: #fff url( " + blobRenderString + " ) top
left no-repeat;");
writer.println();
writer.printRaw("\t}");
writer.println();
}
private void doHeaderImgOverride(IMarkupWriter writer, IRequestCycle cycle)
{
writer.println();
writer.printRaw("\tdiv#header img background {");
writer.println();
writer.printRaw("\t\twidth: 740px;");
writer.println();
writer.printRaw("\t\theight: 94px;");
writer.println();
writer.printRaw("\t}");
writer.println();
}
public IAsset getHeaderAsset()
{
String contentType = getLayout().getHeader().getContentType();
String fileName = getLayout().getHeader().getFileName();
return new TrailsBlobAsset(getDownloadService(),
AdminLayout.class.getName(),
getLayout().getId().toString(),
"header", contentType,
fileName);
}
public IAsset getLogoAsset()
{
String contentType = getLayout().getLogo().getContentType();
String fileName = getLayout().getLogo().getFileName();
return new TrailsBlobAsset(getDownloadService(),
AdminLayout.class.getName(),
getLayout().getId().toString(),
"logo", contentType,
fileName);
}
}
CustomHead.jwc
-------------------------------------
<!DOCTYPE component-specification PUBLIC "-//Apache Software Foundation//Tapestry Specification
4.1//EN" "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_1.dtd">
<component-specification class="org.trails.demo.components.CustomHead"
allow-body="yes"
allow-informal-parameters="no">
<inject property="applicationSpecification"
object="infrastructure:applicationSpecification"/>
</component-specification>
CustomHead.html
-------------------------------------
<span jwcid="$content$">
<span jwcid="customhead"/>
</span>
Border.html (shows custom head usage)
-------------------------------------
<span jwcid="@ScriptIncludes" />
<html
jwcid="[EMAIL PROTECTED]:CustomHead"
title="ognl:layout.title"
stylesheet="ognl:assets.stylesheet" >
<body jwcid="@Body">
.... snip...
Windows Live Hotmail and Microsoft Office Outlook – together at last. Get it
now!
_________________________________________________________________
Climb to the top of the charts! Play Star Shuffle: the word scramble
challenge with star power.
http://club.live.com/star_shuffle.aspx?icid=starshuffle_wlmailtextlink_oct