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