1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.shared.renderkit.html;
20
21 import java.io.IOException;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.logging.Level;
25 import java.util.logging.Logger;
26
27 import javax.faces.application.ProjectStage;
28 import javax.faces.component.UIComponent;
29 import javax.faces.component.UIPanel;
30 import javax.faces.component.behavior.ClientBehavior;
31 import javax.faces.component.behavior.ClientBehaviorHolder;
32 import javax.faces.component.html.HtmlPanelGrid;
33 import javax.faces.context.FacesContext;
34 import javax.faces.context.ResponseWriter;
35
36 import org.apache.myfaces.shared.renderkit.JSFAttr;
37 import org.apache.myfaces.shared.renderkit.RendererUtils;
38 import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
39 import org.apache.myfaces.shared.util.ArrayUtils;
40 import org.apache.myfaces.shared.util.StringUtils;
41
42
43 public class HtmlGridRendererBase
44 extends HtmlRenderer
45 {
46
47 private static final Logger log = Logger.getLogger(HtmlGridRendererBase.class.getName());
48
49 private static final Integer[] ZERO_INT_ARRAY = new Integer[]{0};
50
51 public boolean getRendersChildren()
52 {
53 return true;
54 }
55
56 @Override
57 public void decode(FacesContext context, UIComponent component)
58 {
59
60 super.decode(context, component);
61
62 HtmlRendererUtils.decodeClientBehaviors(context, component);
63 }
64
65 public void encodeBegin(FacesContext facesContext, UIComponent component)
66 throws IOException
67 {
68
69 }
70
71 public void encodeChildren(FacesContext context, UIComponent component)
72 throws IOException
73 {
74
75 }
76
77 public void encodeEnd(FacesContext facesContext, UIComponent component)
78 throws IOException
79 {
80 RendererUtils.checkParamValidity(facesContext, component, UIPanel.class);
81
82 int columns;
83 if (component instanceof HtmlPanelGrid)
84 {
85 columns = ((HtmlPanelGrid)component).getColumns();
86 }
87 else
88 {
89 Integer i = (Integer)component.getAttributes().get(
90 org.apache.myfaces.shared.renderkit.JSFAttr.COLUMNS_ATTR);
91 columns = i != null ? i.intValue() : 0;
92 }
93
94 if (columns <= 0)
95 {
96 if (log.isLoggable(Level.SEVERE))
97 {
98 log.severe("Wrong columns attribute for PanelGrid " +
99 component.getClientId(facesContext) + ": " + columns);
100 }
101 columns = 1;
102 }
103
104 ResponseWriter writer = facesContext.getResponseWriter();
105 Map<String, List<ClientBehavior>> behaviors = null;
106 if (component instanceof ClientBehaviorHolder)
107 {
108 behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
109 }
110
111 if (behaviors != null && !behaviors.isEmpty())
112 {
113 ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, writer);
114 }
115
116 writer.startElement(HTML.TABLE_ELEM, component);
117
118 if (component instanceof ClientBehaviorHolder)
119 {
120 if (!behaviors.isEmpty())
121 {
122 HtmlRendererUtils.writeIdAndName(writer, component, facesContext);
123 }
124 else
125 {
126 HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
127 }
128 long commonPropertiesMarked = 0L;
129 if (isCommonPropertiesOptimizationEnabled(facesContext))
130 {
131 commonPropertiesMarked = CommonPropertyUtils.getCommonPropertiesMarked(component);
132 }
133 if (behaviors.isEmpty() && isCommonPropertiesOptimizationEnabled(facesContext))
134 {
135 CommonPropertyUtils.renderEventProperties(writer,
136 commonPropertiesMarked, component);
137 }
138 else
139 {
140 if (isCommonEventsOptimizationEnabled(facesContext))
141 {
142 CommonEventUtils.renderBehaviorizedEventHandlers(facesContext, writer,
143 commonPropertiesMarked,
144 CommonEventUtils.getCommonEventsMarked(component), component, behaviors);
145 }
146 else
147 {
148 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, component, behaviors);
149 }
150 }
151 if (isCommonPropertiesOptimizationEnabled(facesContext))
152 {
153 HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.TABLE_ATTRIBUTES);
154 CommonPropertyUtils.renderCommonPassthroughPropertiesWithoutEvents(writer,
155 commonPropertiesMarked, component);
156 }
157 else
158 {
159 HtmlRendererUtils.renderHTMLAttributes(writer, component,
160 HTML.TABLE_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
161 }
162 }
163 else
164 {
165 HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
166 if (isCommonPropertiesOptimizationEnabled(facesContext))
167 {
168 HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.TABLE_ATTRIBUTES);
169 CommonPropertyUtils.renderCommonPassthroughProperties(writer,
170 CommonPropertyUtils.getCommonPropertiesMarked(component), component);
171 }
172 else
173 {
174 HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.TABLE_PASSTHROUGH_ATTRIBUTES);
175 }
176 }
177
178 writer.flush();
179
180 HtmlRendererUtils.renderTableCaption(facesContext, writer, component);
181
182
183 renderHeaderOrFooter(facesContext, writer, component, columns, true);
184 renderHeaderOrFooter(facesContext, writer, component, columns, false);
185
186 renderChildren(facesContext, writer, component, columns);
187
188 writer.endElement(HTML.TABLE_ELEM);
189 }
190
191
192
193 protected void renderHeaderOrFooter(FacesContext context,
194 ResponseWriter writer,
195 UIComponent component,
196 int columns,
197 boolean header)
198 throws IOException
199 {
200 UIComponent facet = component.getFacet(header ? "header" : "footer");
201 if (facet == null)
202 {
203 return;
204 }
205
206 writer.startElement(
207 header ? org.apache.myfaces.shared.renderkit.html.HTML.THEAD_ELEM : HTML.TFOOT_ELEM, null);
208
209 writer.startElement(HTML.TR_ELEM, null);
210 writer.startElement(header ? HTML.TH_ELEM : HTML.TD_ELEM, null);
211
212 String styleClass = (component instanceof HtmlPanelGrid)
213 ? (header ?
214 ((HtmlPanelGrid)component).getHeaderClass() :
215 ((HtmlPanelGrid)component).getFooterClass())
216 : (header ?
217 (String)component.getAttributes().get(JSFAttr.HEADER_CLASS_ATTR) :
218 (String)component.getAttributes().get(
219 org.apache.myfaces.shared.renderkit.JSFAttr.FOOTER_CLASS_ATTR));
220 if (styleClass != null)
221 {
222 writer.writeAttribute(HTML.CLASS_ATTR, styleClass,
223 header ? JSFAttr.HEADER_CLASS_ATTR :
224 org.apache.myfaces.shared.renderkit.JSFAttr.FOOTER_CLASS_ATTR);
225 }
226
227 if (header)
228 {
229 writer.writeAttribute(HTML.SCOPE_ATTR, HTML.SCOPE_COLGROUP_VALUE, null);
230 }
231
232 writer.writeAttribute(HTML.COLSPAN_ATTR, Integer.toString(columns), null);
233
234
235 facet.encodeAll(context);
236
237 writer.endElement(header ? HTML.TH_ELEM : HTML.TD_ELEM);
238 writer.endElement(HTML.TR_ELEM);
239 writer.endElement(header ? HTML.THEAD_ELEM : HTML.TFOOT_ELEM);
240 }
241
242 protected int childAttributes(FacesContext context,
243 ResponseWriter writer,
244 UIComponent component,
245 int columnIndex)
246 throws IOException
247 {
248
249 return columnIndex;
250 }
251
252 protected void renderChildren(FacesContext context,
253 ResponseWriter writer,
254 UIComponent component,
255 int columns)
256 throws IOException
257 {
258 String columnClasses;
259 String rowClasses;
260 if (component instanceof HtmlPanelGrid)
261 {
262 columnClasses = ((HtmlPanelGrid)component).getColumnClasses();
263 rowClasses = ((HtmlPanelGrid)component).getRowClasses();
264 }
265 else
266 {
267 columnClasses = (String)component.getAttributes().get(
268 org.apache.myfaces.shared.renderkit.JSFAttr.COLUMN_CLASSES_ATTR);
269 rowClasses = (String)component.getAttributes().get(JSFAttr.ROW_CLASSES_ATTR);
270 }
271
272 String[] columnClassesArray = (columnClasses == null)
273 ? ArrayUtils.EMPTY_STRING_ARRAY
274 : StringUtils.trim(StringUtils.splitShortString(columnClasses, ','));
275 int columnClassesCount = columnClassesArray.length;
276
277 String[] rowClassesArray = (rowClasses == null)
278 ? org.apache.myfaces.shared.util.ArrayUtils.EMPTY_STRING_ARRAY
279 : StringUtils.trim(StringUtils.splitShortString(rowClasses, ','));
280 int rowClassesCount = rowClassesArray.length;
281
282 int childCount = getChildCount(component);
283 if (childCount > 0)
284 {
285
286 Integer[] bodyrows = null;
287 String bodyrowsAttr = (String) component.getAttributes().get(JSFAttr.BODYROWS_ATTR);
288 if(bodyrowsAttr != null && !"".equals(bodyrowsAttr))
289 {
290 String[] bodyrowsString = StringUtils.trim(StringUtils.splitShortString(bodyrowsAttr, ','));
291
292
293 bodyrows = new Integer[bodyrowsString.length];
294 for(int i = 0; i < bodyrowsString.length; i++)
295 {
296 bodyrows[i] = Integer.valueOf(bodyrowsString[i]);
297 }
298
299 }
300 else
301 {
302 bodyrows = ZERO_INT_ARRAY;
303 }
304 int bodyrowsCount = 0;
305 int rowIndex = -1;
306 int columnIndex = 0;
307 int rowClassIndex = 0;
308 boolean rowStarted = false;
309 for (int i = 0, size = component.getChildCount(); i < size; i++)
310 {
311 UIComponent child = component.getChildren().get(i);
312 if (child.isRendered())
313 {
314 if (columnIndex == 0)
315 {
316 rowIndex++;
317
318 if (rowStarted)
319 {
320
321 writer.endElement(HTML.TR_ELEM);
322 }
323
324
325 if(ArrayUtils.contains(bodyrows, rowIndex))
326 {
327
328 if(bodyrowsCount != 0)
329 {
330 writer.endElement(HTML.TBODY_ELEM);
331 }
332 writer.startElement(HTML.TBODY_ELEM, null);
333 bodyrowsCount++;
334 }
335
336
337 writer.startElement(HTML.TR_ELEM, null);
338 if (rowClassIndex < rowClassesCount)
339 {
340 writer.writeAttribute(HTML.CLASS_ATTR, rowClassesArray[rowClassIndex], null);
341 }
342 rowStarted = true;
343 rowClassIndex++;
344 if (rowClassIndex == rowClassesCount)
345 {
346 rowClassIndex = 0;
347 }
348 }
349
350 writer.startElement(HTML.TD_ELEM, null);
351 if (columnIndex < columnClassesCount)
352 {
353 writer.writeAttribute(HTML.CLASS_ATTR, columnClassesArray[columnIndex], null);
354 }
355 columnIndex = childAttributes(context, writer, child, columnIndex);
356
357 child.encodeAll(context);
358 writer.endElement(HTML.TD_ELEM);
359
360 columnIndex++;
361 if (columnIndex >= columns)
362 {
363 columnIndex = 0;
364 }
365 }
366 }
367
368 if (rowStarted)
369 {
370 if (columnIndex > 0)
371 {
372 Level level = context.isProjectStage(ProjectStage.Production) ? Level.FINE : Level.WARNING;
373 if (log.isLoggable(level))
374 {
375 log.log(level, "PanelGrid " + RendererUtils.getPathToComponent(component)
376 + " has not enough children. Child count should be a "
377 + "multiple of the columns attribute.");
378 }
379
380 for ( ; columnIndex < columns; columnIndex++)
381 {
382 writer.startElement(HTML.TD_ELEM, null);
383 if (columnIndex < columnClassesCount)
384 {
385 writer.writeAttribute(HTML.CLASS_ATTR, columnClassesArray[columnIndex], null);
386 }
387 writer.endElement(HTML.TD_ELEM);
388 }
389 }
390 writer.endElement(HTML.TR_ELEM);
391
392
393 if(bodyrowsCount != 0)
394 {
395 writer.endElement(HTML.TBODY_ELEM);
396 }
397 }
398 }
399 }
400
401 }