View Javadoc

1   // Copyright 2008 Thiago H. de Paula Figueiredo
2   //
3   // Licensed under the Apache License, Version 2.0 (the "License");
4   // you may not use this file except in compliance with the License.
5   // You may obtain a copy of the License at
6   //
7   //     http://www.apache.org/licenses/LICENSE-2.0
8   //
9   // 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 br.com.arsmachina.tapestrycrud.components;
16  
17  
18  import org.apache.tapestry5.BindingConstants;
19  import org.apache.tapestry5.ComponentResources;
20  import org.apache.tapestry5.Field;
21  import org.apache.tapestry5.MarkupWriter;
22  import org.apache.tapestry5.ValidationDecorator;
23  import org.apache.tapestry5.annotations.AfterRender;
24  import org.apache.tapestry5.annotations.BeginRender;
25  import org.apache.tapestry5.annotations.Environmental;
26  import org.apache.tapestry5.annotations.IncludeStylesheet;
27  import org.apache.tapestry5.annotations.Mixin;
28  import org.apache.tapestry5.annotations.Parameter;
29  import org.apache.tapestry5.annotations.SupportsInformalParameters;
30  import org.apache.tapestry5.corelib.components.Label;
31  import org.apache.tapestry5.corelib.mixins.DiscardBody;
32  import org.apache.tapestry5.dom.Element;
33  import org.apache.tapestry5.ioc.annotations.Inject;
34  import org.apache.tapestry5.services.Heartbeat;
35  
36  import br.com.arsmachina.tapestrycrud.Constants;
37  
38  /**
39   * <p>
40   * {@link Label} subclass that always ignores its body and generates the label name from the
41   * corresponding field id.
42   * </p>
43   * <p>
44   * This class' code was initially copied from {@link Label}, as one of its methods (<code>afterRender</code>)
45   * has package visibility and thus cannot be overriden.
46   * </p>
47   * 
48   * @author Thiago H. de Paula Figueiredo
49   */
50  @SupportsInformalParameters
51  @IncludeStylesheet(Constants.TAPESTRY_CRUD_CSS_ASSET)
52  public class ImprovedLabel {
53  
54  	/**
55  	 * Discards the body of this class.
56  	 */
57  	@SuppressWarnings("unused")
58  	@Mixin
59  	private DiscardBody discardBody;
60  
61  	/**
62  	 * The for parameter is used to identify the {@link Field} linked to this label (it is named
63  	 * this way because it results in the for attribute of the label element).
64  	 */
65  	@Parameter(name = "for", required = true, defaultPrefix = BindingConstants.COMPONENT)
66  	private Field field;
67  
68  	@Environmental
69  	private Heartbeat heartbeat;
70  
71  	@Environmental
72  	private ValidationDecorator decorator;
73  
74  	@Inject
75  	private ComponentResources resources;
76  
77  	private Element labelElement;
78  
79  	@BeginRender
80  	void begin(MarkupWriter writer) {
81  		final Field field = this.field;
82  
83  		decorator.beforeLabel(field);
84  
85  		labelElement = writer.element("label");
86  
87  		resources.renderInformalParameters(writer);
88  
89  		// Since we don't know if the field has rendered yet, we need to defer writing the for and
90  		// id
91  		// attributes until we know the field has rendered (and set its clientId property). That's
92  		// exactly what Heartbeat is for.
93  
94  		Runnable command = new Runnable() {
95  
96  			public void run() {
97  				String fieldId = field.getClientId();
98  
99  				labelElement.forceAttributes("for", fieldId, "id", fieldId + ":label");
100 
101 				decorator.insideLabel(field, labelElement);
102 			}
103 		};
104 
105 		heartbeat.defer(command);
106 	}
107 
108 	@AfterRender
109 	void after(MarkupWriter writer) {
110 		// If the Label element has a body that renders some non-blank output, that takes
111 		// precendence
112 		// over the label string provided by the field.
113 
114 		// removed code from label. the rest was not modified.
115 
116 		// boolean bodyIsBlank = InternalUtils.isBlank(labelElement.getChildMarkup());
117 		//
118 		// if (bodyIsBlank)
119 		// writer.write(field.getLabel());
120 
121 		writer.write(field.getLabel());
122 
123 		writer.end(); // label
124 
125 		decorator.afterLabel(field);
126 
127 	}
128 }