1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.tobago.internal.renderkit.renderer;
21
22 import org.apache.myfaces.tobago.component.Attributes;
23 import org.apache.myfaces.tobago.component.LabelLayout;
24 import org.apache.myfaces.tobago.component.SupportsAccessKey;
25 import org.apache.myfaces.tobago.component.SupportsLabelLayout;
26 import org.apache.myfaces.tobago.context.Markup;
27 import org.apache.myfaces.tobago.internal.component.AbstractUIStyle;
28 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
29 import org.apache.myfaces.tobago.internal.util.StringUtils;
30 import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
31 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
32 import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
33 import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
34 import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
35 import org.apache.myfaces.tobago.util.ComponentUtils;
36 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
37
38 import javax.faces.component.UIComponent;
39 import javax.faces.context.FacesContext;
40 import java.io.IOException;
41 import java.util.List;
42
43
44
45
46
47 public abstract class LabelLayoutRendererBase<T extends UIComponent & SupportsLabelLayout>
48 extends DecodingInputRendererBase<T> {
49
50 public abstract HtmlElements getComponentTag();
51
52 @Override
53 public void encodeBeginInternal(final FacesContext facesContext, final T component) throws IOException {
54
55 encodeBeginSurroundingLabel(facesContext, component);
56
57 if (component.isNextToRenderIsLabel()) {
58
59 } else {
60 encodeBeginMessageField(facesContext, component);
61 }
62 }
63
64 @Override
65 public void encodeEndInternal(final FacesContext facesContext, final T component) throws IOException {
66
67 if (component.isNextToRenderIsLabel()) {
68
69 } else {
70 encodeEndMessageField(facesContext, component);
71 }
72
73
74 if (component.getRendersChildren()) {
75 final List<AbstractUIStyle> children = ComponentUtils.findDescendantList(component, AbstractUIStyle.class);
76 for (final AbstractUIStyle child : children) {
77 child.encodeAll(facesContext);
78 }
79 }
80
81 encodeEndSurroundingLabel(facesContext, component);
82 }
83
84 protected void encodeAttributes(final FacesContext facesContext, final T component) throws IOException {
85 }
86
87 @Override
88 public void encodeChildrenInternal(final FacesContext context, final T component) throws IOException {
89 if (component.getChildCount() > 0) {
90 for (int i = 0, childCount = component.getChildCount(); i < childCount; i++) {
91 final UIComponent child = component.getChildren().get(i);
92 if (!child.isRendered()) {
93 continue;
94 }
95 if (child instanceof AbstractUIStyle) {
96
97 continue;
98 }
99
100 child.encodeAll(context);
101 }
102 }
103 }
104
105 protected abstract void encodeBeginMessageField(FacesContext facesContext, T component) throws IOException;
106
107 protected abstract void encodeEndMessageField(FacesContext facesContext, T component) throws IOException;
108
109 protected void encodeBeginSurroundingLabel(final FacesContext facesContext, final T component)
110 throws IOException {
111
112 final TobagoResponseWriter writer = getResponseWriter(facesContext);
113 String clientId = component.getClientId(facesContext);
114 final Markup markup = (Markup) ComponentUtils.getAttribute(component, Attributes.markup);
115
116 final LabelLayout labelLayout = component.getLabelLayout();
117 final boolean nextToRenderIsLabel = component.isNextToRenderIsLabel();
118 final boolean flex;
119
120 switch (labelLayout) {
121 case flexLeft:
122 case flexRight:
123 flex = true;
124 break;
125 case segmentLeft:
126 case segmentRight:
127 if (nextToRenderIsLabel) {
128 clientId += ComponentUtils.SUB_SEPARATOR + "label";
129 }
130 flex = false;
131 break;
132 case flowLeft:
133 case gridLeft:
134 case gridRight:
135 case gridTop:
136 case gridBottom:
137 encodeLabel(facesContext, component, writer, labelLayout);
138 flex = false;
139 break;
140 case none:
141 case top:
142 case flowRight:
143 default:
144 flex = false;
145 }
146
147
148
149
150
151
152 if (nextToRenderIsLabel) {
153
154 } else {
155 writer.startElement(getComponentTag());
156 writer.writeIdAttribute(clientId);
157 encodeAttributes(facesContext, component);
158 writer.writeClassAttribute(
159 flex ? TobagoClass.FLEX_LAYOUT : null,
160 flex ? TobagoClass.LABEL__CONTAINER : null,
161 BootstrapClass.MB_3,
162 ComponentUtils.getBooleanAttribute(component, Attributes.required) ? TobagoClass.REQUIRED : null,
163 markup != null && markup.contains(Markup.SPREAD) ? TobagoClass.SPREAD : null);
164 }
165
166 switch (labelLayout) {
167 case none:
168 case flexRight:
169 case flowRight:
170 case flowLeft:
171 case gridLeft:
172 case gridRight:
173 case gridTop:
174 case gridBottom:
175 break;
176 case segmentLeft:
177 case segmentRight:
178 if (nextToRenderIsLabel) {
179 encodeLabel(facesContext, component, writer, labelLayout);
180 }
181 break;
182 default:
183 encodeLabel(facesContext, component, writer, labelLayout);
184 }
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203 }
204
205 protected void encodeEndSurroundingLabel(final FacesContext facesContext, final T component)
206 throws IOException {
207
208 final TobagoResponseWriter writer = getResponseWriter(facesContext);
209 final LabelLayout labelLayout = component.getLabelLayout();
210
211 if (labelLayout == LabelLayout.flexRight) {
212 encodeLabel(facesContext, component, writer, labelLayout);
213 }
214
215 final boolean nextToRenderIsLabel = component.isNextToRenderIsLabel();
216 if (!nextToRenderIsLabel) {
217 writer.endElement(getComponentTag());
218 }
219
220 if (labelLayout == LabelLayout.flowRight) {
221 encodeLabel(facesContext, component, writer, labelLayout);
222 }
223 }
224
225 protected void encodeLabel(final FacesContext facesContext, final T component,
226 final TobagoResponseWriter writer, final LabelLayout labelLayout)
227 throws IOException {
228
229 final String label = ComponentUtils.getStringAttribute(component, Attributes.label);
230 if (StringUtils.isNotBlank(label)) {
231 writer.startElement(HtmlElements.LABEL);
232 writer.writeAttribute(HtmlAttributes.FOR, getFieldId(facesContext, component), false);
233 writer.writeClassAttribute(BootstrapClass.COL_FORM_LABEL);
234 if (component instanceof SupportsAccessKey) {
235 final LabelWithAccessKey labelWithAccessKey = new LabelWithAccessKey((SupportsAccessKey) component);
236 HtmlRendererUtils.writeLabelWithAccessKey(writer, labelWithAccessKey);
237 } else {
238 writer.writeText(label);
239 }
240 writer.endElement(HtmlElements.LABEL);
241 }
242 }
243
244 protected abstract String getFieldId(final FacesContext facesContext, final T component);
245 }