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