/* * � Copyright IBM Corp. 2010, 2011 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ package com.ibm.xsp.extlib.renderkit.html_extended.data; import java.io.IOException; import javax.faces.component.NamingContainer; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.model.DataModel; import com.ibm.commons.util.StringUtil; import com.ibm.xsp.designer.context.XSPContext; import com.ibm.xsp.extlib.component.data.AbstractDataView; import com.ibm.xsp.extlib.component.data.UIDataView; import com.ibm.xsp.extlib.component.data.UIForumView; import com.ibm.xsp.extlib.util.ExtLibUtil; /** * */ public class ForumViewRenderer extends AbstractWebDataViewRenderer { protected static final int PROP_MAINLISTSTYLE = 200; protected static final int PROP_MAINLISTCLASS = 201; protected static final int PROP_CHILDLISTSTYLE = 202; protected static final int PROP_CHILDLISTCLASS = 203; protected static final int PROP_LISTITEMSTYLE = 204; protected static final int PROP_LISTITEMCLASS = 205; protected static final int PROP_COLLAPSIBLECONTENTSTYLE = 210; protected static final int PROP_COLLAPSIBLEDIVSTYLE = 211; @Override protected Object getProperty(int prop) { switch(prop) { } return super.getProperty(prop); } // ================================================================ // Runtime view definition object // ================================================================ @Override protected void initViewDefinition(FacesContext context, AbstractDataView _dataView, ViewDefinition viewDef) { UIForumView dataView = (UIForumView)_dataView; super.initViewDefinition(context, dataView, viewDef); // Define if the items must be rendered in a table, // Use a table for IE as CSS float is largely buggy - Hope IE9 fixes this... viewDef.viewforumRenderAsTable = XSPContext.getXSPContext(context).getUserAgent().isIE(0,8); // It is only one or the other, never both... viewDef.summaryOrDetailVisible = true; // Just to be sure... viewDef.collapsibleRows = false; } @Override protected void writeContent(FacesContext context, ResponseWriter w, AbstractDataView c, ViewDefinition viewDef) throws IOException { if(DEBUG) { w.writeComment("Start ForumView content"); // $NON-NLS-1$ newLine(w); } w.startElement("ul",c); // $NON-NLS-1$ w.writeAttribute("id", c.getAjaxContainerClientId(context), null); // $NON-NLS-1$ String style = (String)getProperty(PROP_MAINLISTSTYLE); if(StringUtil.isNotEmpty(style)) { w.writeAttribute("style", style, null); // $NON-NLS-1$ } String styleClass = (String)getProperty(PROP_MAINLISTCLASS); if(StringUtil.isNotEmpty(styleClass)) { w.writeAttribute("class", styleClass, null); // $NON-NLS-1$ } newLine(w); // And the rows int first = c.getFirst(); int count = c.getRows(); writeRows(context, w, c, viewDef, first, count); w.endElement("ul"); // $NON-NLS-1$ newLine(w); if(DEBUG) { w.writeComment("End ForumView content"); // $NON-NLS-1$ newLine(w); } } @Override protected void beforeRow(FacesContext context, ResponseWriter w, AbstractDataView c, ViewDefinition viewDef) throws IOException { super.beforeRow(context, w, c, viewDef); // In case of the first row, we generate the first indentation if(!viewDef.singleRowRefresh) { DataModel dm = viewDef.dataModel; if(dm.getRowIndex()==viewDef.first) { //int indent = (dm instanceof TabularDataModel) ? ((TabularDataModel)dm).getIndentLevel() : 0; int initialLevel = getColumnIndentLevel(context, c, viewDef); if(initialLevel>0) { startFirstRow(context, w, c, viewDef, initialLevel); viewDef.initialIndentLevel = initialLevel; } } } } @Override protected void afterRows(FacesContext context, ResponseWriter w, AbstractDataView c, ViewDefinition viewDef) throws IOException { super.afterRows(context, w, c, viewDef); if(!viewDef.singleRowRefresh) { if(!viewDef.singleRowRefresh) { int levelToClose = viewDef.indentLevel-viewDef.initialIndentLevel; if(levelToClose>0) { for(int i=0; i<levelToClose; i++ ) { endChildren(context, w, c, viewDef); } } } if(viewDef.initialIndentLevel>0) { endFirstRow(context, w, c, viewDef, viewDef.initialIndentLevel); } } } @Override protected void writeRow(FacesContext context, ResponseWriter w, AbstractDataView c, ViewDefinition viewDef) throws IOException { if(isCategoryRow(context, c, viewDef)) { // Not valid... } else if(isTotalRow(context, c, viewDef)) { // Not valid... } else { // Standard row writeStandardRow(context, w, c, viewDef); } } protected void writeStandardRow(FacesContext context, ResponseWriter w, AbstractDataView c, ViewDefinition viewDef) throws IOException { if(!viewDef.singleRowRefresh) { int indent = getColumnIndentLevel(context, c, viewDef); // Fix the indentation if(indent<viewDef.indentLevel) { int limit = viewDef.indentLevel-indent; for(int i=0; i<limit; i++ ) { endChildren(context, w, c, viewDef); endItem(context, w, c, viewDef); viewDef.indentLevel--; } } else if(indent>viewDef.indentLevel) { int limit = indent-viewDef.indentLevel; for(int i=0; i<limit; i++ ) { startItem(context, w, c, viewDef, false); startChildren(context, w, c, viewDef); viewDef.indentLevel++; } } } // Start the new item to be displayed startItem(context, w, c, viewDef, true); // Use a table for IE as CSS float is largely buggy - Hope IE9 fixes this... if(viewDef.viewforumRenderAsTable) { w.startElement("table",c); // $NON-NLS-1$ w.writeAttribute("style", "margin: 0; padding:0; border-width: 0; width: 100%", null); // $NON-NLS-1$ $NON-NLS-2$ w.writeAttribute("role", "presentation", null); // $NON-NLS-1$ $NON-NLS-2$ w.startElement("tr",c); // $NON-NLS-1$ // Encode the row content w.startElement("td",c); // $NON-NLS-1$ w.writeAttribute("style", "width: 100%", null); // $NON-NLS-1$ $NON-NLS-2$ writeStandardContent(context, w, c, viewDef); w.endElement("td"); // $NON-NLS-1$ // Encode the expand/collapse details icon if(viewDef.collapsibleDetails) { w.startElement("td",c); // $NON-NLS-1$ w.writeAttribute("valign", "top", null); // $NON-NLS-1$ $NON-NLS-2$ //w.writeAttribute("style", "padding: -7px; width: 100%", null); writeShowHideDetailContent(context, w, c, viewDef); w.endElement("td"); // $NON-NLS-1$ } // And close the item... w.endElement("tr"); // $NON-NLS-1$ w.endElement("table"); // $NON-NLS-1$ } else { // When display a forum view, then we need to create a first enclosing div // that sets the global margin to 7px (for OneUI). Else, an enclosing forumPost // won't render properly here. Then, this also serve for the positioning of the // expand/collapse icon which is using a float: left style. Without this div, it // will position relative to a div upper in the hierarchy w.startElement("div",c); // $NON-NLS-1$ String st1 = (String)getProperty(PROP_COLLAPSIBLECONTENTSTYLE); if(StringUtil.isNotEmpty(st1)) { w.writeAttribute("style", st1, null); // $NON-NLS-1$ } // Encode the expand/collapse details icon if(viewDef.collapsibleDetails) { writeCollapsibleContent(context, w, c, viewDef); } // Encode the row content writeStandardContent(context, w, c, viewDef); // Main div... w.endElement("div"); // $NON-NLS-1$ } endItem(context, w, c, viewDef); } protected void writeCollapsibleContent(FacesContext context, ResponseWriter w, AbstractDataView c, ViewDefinition viewDef) throws IOException { // The style here is ensuring a float: left positioning w.startElement("div",c); // $NON-NLS-1$ String st2 = (String)getProperty(PROP_COLLAPSIBLEDIVSTYLE); if(StringUtil.isNotEmpty(st2)) { w.writeAttribute("style", st2, null); // $NON-NLS-1$ } writeShowHideDetailContent(context, w, c, viewDef); w.endElement("div"); // $NON-NLS-1$ } protected void writeStandardContent(FacesContext context, ResponseWriter w, AbstractDataView c, ViewDefinition viewDef) throws IOException { // If both the summary and the detail have to be in the client, we render them here writeSummary(context, w, c, viewDef); writeDetail(context, w, c, viewDef); } protected void startFirstRow(FacesContext context, ResponseWriter w, AbstractDataView c, ViewDefinition viewDef, int indentLevel) throws IOException { for(int i=0; i<indentLevel; i++) { startItem(context, w, c, viewDef, false); startChildren(context, w, c, viewDef); } } protected void endFirstRow(FacesContext context, ResponseWriter w, AbstractDataView c, ViewDefinition viewDef, int indentLevel) throws IOException { for(int i=0; i<indentLevel; i++) { endChildren(context, w, c, viewDef); endItem(context, w, c, viewDef); } } protected void startChildren(FacesContext context, ResponseWriter w, AbstractDataView c, ViewDefinition viewDef) throws IOException { w.startElement("ul",c); // $NON-NLS-1$ String style = (String)getProperty(PROP_CHILDLISTSTYLE); if(StringUtil.isNotEmpty(style)) { w.writeAttribute("style", style, null); // $NON-NLS-1$ } String styleClass = (String)getProperty(PROP_CHILDLISTCLASS); if(StringUtil.isNotEmpty(styleClass)) { w.writeAttribute("class", styleClass, null); // $NON-NLS-1$ } newLine(w); } protected void endChildren(FacesContext context, ResponseWriter w, AbstractDataView c, ViewDefinition viewDef) throws IOException { w.endElement("ul"); // $NON-NLS-1$ newLine(w); } protected void startItem(FacesContext context, ResponseWriter w, AbstractDataView c, ViewDefinition viewDef, boolean emitId) throws IOException { w.startElement("li",c); // $NON-NLS-1$ if(emitId) { String id = viewDef.dataView.getClientId(context)+NamingContainer.SEPARATOR_CHAR+UIDataView.ROW_ID; w.writeAttribute("id", id, null); // $NON-NLS-1$ } String style = (String)getProperty(PROP_LISTITEMSTYLE); // In case we do not render as a table, we should also fix the margin if(!viewDef.viewforumRenderAsTable) { // In case of a table, the margin are auto computed and not null // In case of div, they're just null so we should fix them style = ExtLibUtil.concatStyles(style, "margin: 7px 7px 7px 0;"); // $NON-NLS-1$ } if(StringUtil.isNotEmpty(style)) { w.writeAttribute("style", style, null); // $NON-NLS-1$ } String styleClass = (String)getProperty(PROP_LISTITEMCLASS); if(StringUtil.isNotEmpty(styleClass)) { w.writeAttribute("class", styleClass, null); // $NON-NLS-1$ } newLine(w); } protected void endItem(FacesContext context, ResponseWriter w, AbstractDataView c, ViewDefinition viewDef) throws IOException { w.endElement("li"); // $NON-NLS-1$ newLine(w); } }