01: // Copyright 2006, 2007 The Apache Software Foundation
02: //
03: // Licensed under the Apache License, Version 2.0 (the "License");
04: // you may not use this file except in compliance with the License.
05: // You may obtain a copy of the License at
06: //
07: // http://www.apache.org/licenses/LICENSE-2.0
08: //
09: // Unless required by applicable law or agreed to in writing, software
10: // distributed under the License is distributed on an "AS IS" BASIS,
11: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12: // See the License for the specific language governing permissions and
13: // limitations under the License.
14:
15: package org.apache.tapestry.corelib.components;
16:
17: import org.apache.tapestry.ComponentResources;
18: import org.apache.tapestry.Field;
19: import org.apache.tapestry.MarkupWriter;
20: import org.apache.tapestry.ValidationDecorator;
21: import org.apache.tapestry.annotations.AfterRender;
22: import org.apache.tapestry.annotations.BeforeRenderBody;
23: import org.apache.tapestry.annotations.BeginRender;
24: import org.apache.tapestry.annotations.Environmental;
25: import org.apache.tapestry.annotations.Inject;
26: import org.apache.tapestry.annotations.Parameter;
27: import org.apache.tapestry.annotations.SupportsInformalParameters;
28: import org.apache.tapestry.dom.Element;
29: import org.apache.tapestry.services.Heartbeat;
30:
31: /** Generates a <label> element for a particular field. */
32: @SupportsInformalParameters
33: public class Label {
34: /**
35: * The for parameter is used to identify the {@link Field} linked to this label (it is named
36: * this way because it results in the for attribute of the label element).
37: */
38: @Parameter(name="for",required=true,defaultPrefix="component")
39: private Field _field;
40:
41: @Environmental
42: private Heartbeat _heartbeat;
43:
44: @Environmental
45: private ValidationDecorator _decorator;
46:
47: @Inject
48: private ComponentResources _resources;
49:
50: @BeginRender
51: void begin(MarkupWriter writer) {
52: final Field field = _field;
53:
54: final Element element = writer.element("label");
55:
56: _resources.renderInformalParameters(writer);
57:
58: // Uh oh! Referencing a private field (that happens to get instrumented up the wazoo) from
59: // a inner class causes a java.lang.Verify error (Unable to pop operand off an empty stack).
60: // Perhaps this is a Javassist error? Shouldn't the inner class be going through a synthetic
61: // accessor method of some kind? Resolved by assigning to a local variable and referencing
62: // that. Layers on layers, oh my!
63:
64: final ValidationDecorator decorator = _decorator;
65:
66: // Since we don't know if the field has rendered yet, we need to defer writing the for
67: // attribute until we know the field has rendered (and set its clientId property). That's
68: // exactly what Heartbeat is for.
69:
70: Runnable command = new Runnable() {
71: public void run() {
72: String fieldId = field.getClientId();
73:
74: element.forceAttributes("for", fieldId, "id", fieldId
75: + ":label");
76:
77: decorator.insideLabel(field, element);
78: }
79: };
80:
81: _heartbeat.defer(command);
82: }
83:
84: @BeforeRenderBody
85: boolean renderBody() {
86: // Don't render the body of the component even if there is one.
87:
88: return false;
89: }
90:
91: @AfterRender
92: void after(MarkupWriter writer) {
93: writer.write(_field.getLabel());
94:
95: writer.end(); // label
96: }
97: }
|