1 29 30 package nextapp.echo2.webcontainer.syncpeer; 31 32 import java.util.HashSet ; 33 import java.util.Set ; 34 35 import org.w3c.dom.Document ; 36 import org.w3c.dom.DocumentFragment ; 37 import org.w3c.dom.Element ; 38 import org.w3c.dom.Node ; 39 40 import nextapp.echo2.app.Border; 41 import nextapp.echo2.app.Component; 42 import nextapp.echo2.app.Extent; 43 import nextapp.echo2.app.Grid; 44 import nextapp.echo2.app.ImageReference; 45 import nextapp.echo2.app.Insets; 46 import nextapp.echo2.app.LayoutData; 47 import nextapp.echo2.app.layout.GridLayoutData; 48 import nextapp.echo2.app.update.ServerComponentUpdate; 49 import nextapp.echo2.webcontainer.ContainerInstance; 50 import nextapp.echo2.webcontainer.DomUpdateSupport; 51 import nextapp.echo2.webcontainer.RenderContext; 52 import nextapp.echo2.webcontainer.ComponentSynchronizePeer; 53 import nextapp.echo2.webcontainer.SynchronizePeerFactory; 54 import nextapp.echo2.webcontainer.image.ImageRenderSupport; 55 import nextapp.echo2.webcontainer.propertyrender.BorderRender; 56 import nextapp.echo2.webcontainer.propertyrender.CellLayoutDataRender; 57 import nextapp.echo2.webcontainer.propertyrender.ColorRender; 58 import nextapp.echo2.webcontainer.propertyrender.ExtentRender; 59 import nextapp.echo2.webcontainer.propertyrender.FontRender; 60 import nextapp.echo2.webcontainer.propertyrender.InsetsRender; 61 import nextapp.echo2.webrender.ClientProperties; 62 import nextapp.echo2.webrender.output.CssStyle; 63 import nextapp.echo2.webrender.servermessage.DomUpdate; 64 65 71 public class GridPeer 72 implements ComponentSynchronizePeer, DomUpdateSupport, ImageRenderSupport { 73 74 77 private static final String SIZING_DOTS = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . " 78 + ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "; 79 80 83 public String getContainerId(Component child) { 84 return ContainerInstance.getElementId(child.getParent()) + "_td_" 85 + ContainerInstance.getElementId(child); 86 } 87 88 91 public ImageReference getImage(Component component, String imageId) { 92 return CellLayoutDataRender.getCellLayoutDataBackgroundImage(component, imageId); 95 } 96 97 106 private GridLayoutData getLayoutData(Component child) { 107 LayoutData layoutData = (LayoutData) child.getRenderProperty(Component.PROPERTY_LAYOUT_DATA); 108 if (layoutData == null) { 109 return null; 110 } else if (layoutData instanceof GridLayoutData) { 111 return (GridLayoutData) layoutData; 112 } else { 113 throw new RuntimeException ("Invalid LayoutData for Grid Child: " + layoutData.getClass().getName()); 114 } 115 } 116 117 121 public void renderAdd(RenderContext rc, ServerComponentUpdate update, String targetId, Component component) { 122 Element domAddElement = DomUpdate.renderElementAdd(rc.getServerMessage()); 123 DocumentFragment htmlFragment = rc.getServerMessage().getDocument().createDocumentFragment(); 124 renderHtml(rc, update, htmlFragment, component); 125 DomUpdate.renderElementAddContent(rc.getServerMessage(), domAddElement, targetId, htmlFragment); 126 } 127 128 136 private void renderAddChild(RenderContext rc, ServerComponentUpdate update, Element parentElement, Component child) { 137 ComponentSynchronizePeer syncPeer = SynchronizePeerFactory.getPeerForComponent(child.getClass()); 138 if (syncPeer instanceof DomUpdateSupport) { 139 ((DomUpdateSupport) syncPeer).renderHtml(rc, update, parentElement, child); 140 } else { 141 syncPeer.renderAdd(rc, update, getContainerId(child), child); 142 } 143 } 144 145 149 public void renderDispose(RenderContext rc, ServerComponentUpdate update, Component component) { } 150 151 155 public void renderHtml(RenderContext rc, ServerComponentUpdate update, Node parentNode, Component component) { 156 Document document = parentNode.getOwnerDocument(); 157 Grid grid = (Grid) component; 158 Border border = (Border) grid.getRenderProperty(Grid.PROPERTY_BORDER); 159 String elementId = ContainerInstance.getElementId(grid); 160 GridProcessor gridProcessor = new GridProcessor(grid); 161 int columnCount = gridProcessor.getColumnCount(); 162 int rowCount = gridProcessor.getRowCount(); 163 164 Element tableElement = document.createElement("table"); 165 tableElement.setAttribute("id", elementId); 166 167 CssStyle tableCssStyle = new CssStyle(); 168 tableCssStyle.setAttribute("border-collapse", "collapse"); 169 170 Insets gridInsets = (Insets) grid.getRenderProperty(Grid.PROPERTY_INSETS); 171 String defaultInsetsAttributeValue = gridInsets == null 172 ? "0px" : InsetsRender.renderCssAttributeValue(gridInsets); 173 174 ColorRender.renderToStyle(tableCssStyle, component); 175 FontRender.renderToStyle(tableCssStyle, component); 176 BorderRender.renderToStyle(tableCssStyle, border); 177 ExtentRender.renderToStyle(tableCssStyle, "height", (Extent) grid.getRenderProperty(Grid.PROPERTY_HEIGHT)); 178 179 Extent width = (Extent) grid.getRenderProperty(Grid.PROPERTY_WIDTH); 180 boolean render100PercentWidthWorkaround = false; 181 if (rc.getContainerInstance().getClientProperties().getBoolean( 182 ClientProperties.QUIRK_IE_TABLE_PERCENT_WIDTH_SCROLLBAR_ERROR)) { 183 if (width != null && width.getUnits() == Extent.PERCENT && width.getValue() == 100) { 184 width = null; 185 render100PercentWidthWorkaround = true; 186 } 187 } 188 ExtentRender.renderToStyle(tableCssStyle, "width", width); 189 190 Extent borderSize = border == null ? null : border.getSize(); 191 if (borderSize != null) { 192 if (!rc.getContainerInstance().getClientProperties().getBoolean(ClientProperties.QUIRK_CSS_BORDER_COLLAPSE_INSIDE)) { 193 tableCssStyle.setAttribute("margin", ExtentRender.renderCssAttributeValueHalf(borderSize)); 194 } 195 } 196 197 tableElement.setAttribute("style", tableCssStyle.renderInline()); 198 199 parentNode.appendChild(tableElement); 200 201 boolean someColumnsHaveWidths = false; 202 for (int i = 0; i < columnCount; ++i) { 203 if (gridProcessor.getColumnWidth(i) != null) { 204 someColumnsHaveWidths = true; 205 } 206 } 207 if (someColumnsHaveWidths) { 208 Element colGroupElement = document.createElement("colgroup"); 209 tableElement.appendChild(colGroupElement); 210 211 for (int i = 0; i < columnCount; ++i) { 212 Element colElement = document.createElement("col"); 213 Extent columnWidth = gridProcessor.getColumnWidth(i); 214 if (columnWidth != null) { 215 colElement.setAttribute("style", "width:" + ExtentRender.renderCssAttributeValue(columnWidth)); 216 } 217 colGroupElement.appendChild(colElement); 218 } 219 } 220 221 Element tbodyElement = document.createElement("tbody"); 222 tbodyElement.setAttribute("id", elementId + "_tbody"); 223 tableElement.appendChild(tbodyElement); 224 225 Set renderedCells = new HashSet (); 226 227 for (int rowIndex = 0; rowIndex < rowCount; ++rowIndex) { 228 Element trElement = document.createElement("tr"); 229 trElement.setAttribute("id", elementId + "_tr_" + rowIndex); 230 if (gridProcessor.getRowHeight(rowIndex) != null) { 231 trElement.setAttribute("style", "height:" + ExtentRender.renderCssAttributeValue(gridProcessor.getRowHeight(rowIndex))); 232 } 233 tbodyElement.appendChild(trElement); 234 235 for (int columnIndex = 0; columnIndex < columnCount; ++columnIndex) { 236 Component cell = gridProcessor.getContent(columnIndex, rowIndex); 237 if (cell == null) { 238 Element tdElement = document.createElement("td"); 239 trElement.appendChild(tdElement); 240 continue; 241 } 242 if (renderedCells.contains(cell)) { 243 continue; 245 } 246 renderedCells.add(cell); 247 248 Element tdElement = document.createElement("td"); 249 tdElement.setAttribute("id", elementId + "_td_" + ContainerInstance.getElementId(cell)); 250 trElement.appendChild(tdElement); 251 252 int columnSpan = gridProcessor.getColumnSpan(columnIndex, rowIndex); 253 if (columnSpan > 1) { 254 tdElement.setAttribute("colspan", Integer.toString(columnSpan)); 255 } 256 257 int rowSpan = gridProcessor.getRowSpan(columnIndex, rowIndex); 258 if (rowSpan > 1) { 259 tdElement.setAttribute("rowspan", Integer.toString(rowSpan)); 260 } 261 262 CssStyle tdCssStyle = new CssStyle(); 263 BorderRender.renderToStyle(tdCssStyle, (Border) grid.getRenderProperty(Grid.PROPERTY_BORDER)); 264 CellLayoutDataRender.renderToElementAndStyle(tdElement, tdCssStyle, cell, getLayoutData(cell), 265 defaultInsetsAttributeValue); 266 CellLayoutDataRender.renderBackgroundImageToStyle(tdCssStyle, rc, this, grid, cell); 267 tdElement.setAttribute("style", tdCssStyle.renderInline()); 268 269 if (rowIndex == 0 && render100PercentWidthWorkaround) { 270 Element sizingDivElement = document.createElement("div"); 272 sizingDivElement.setAttribute("style", "font-size:50px;height:0px;overflow:hidden;"); 273 sizingDivElement.appendChild(document.createTextNode(SIZING_DOTS)); 274 tdElement.appendChild(sizingDivElement); 275 } 276 277 renderAddChild(rc, update, tdElement, cell); 278 } 279 } 280 } 281 282 286 public boolean renderUpdate(RenderContext rc, ServerComponentUpdate update, String targetId) { 287 String parentId = ContainerInstance.getElementId(update.getParent()); 288 DomUpdate.renderElementRemove(rc.getServerMessage(), parentId); 289 renderAdd(rc, update, targetId, update.getParent()); 290 return true; 291 } 292 } 293 | Popular Tags |