1 29 30 package nextapp.echo2.webcontainer.syncpeer; 31 32 import org.w3c.dom.Document ; 33 import org.w3c.dom.DocumentFragment ; 34 import org.w3c.dom.Element ; 35 import org.w3c.dom.Node ; 36 37 import nextapp.echo2.app.Color; 38 import nextapp.echo2.app.Component; 39 import nextapp.echo2.app.ContentPane; 40 import nextapp.echo2.app.Extent; 41 import nextapp.echo2.app.FillImage; 42 import nextapp.echo2.app.FloatingPane; 43 import nextapp.echo2.app.Font; 44 import nextapp.echo2.app.ImageReference; 45 import nextapp.echo2.app.Insets; 46 import nextapp.echo2.app.button.AbstractButton; 47 import nextapp.echo2.app.update.ServerComponentUpdate; 48 import nextapp.echo2.webcontainer.ContainerInstance; 49 import nextapp.echo2.webcontainer.DomUpdateSupport; 50 import nextapp.echo2.webcontainer.PartialUpdateManager; 51 import nextapp.echo2.webcontainer.PartialUpdateParticipant; 52 import nextapp.echo2.webcontainer.PropertyUpdateProcessor; 53 import nextapp.echo2.webcontainer.RenderContext; 54 import nextapp.echo2.webcontainer.ComponentSynchronizePeer; 55 import nextapp.echo2.webcontainer.SynchronizePeerFactory; 56 import nextapp.echo2.webcontainer.image.ImageRenderSupport; 57 import nextapp.echo2.webcontainer.propertyrender.ColorRender; 58 import nextapp.echo2.webcontainer.propertyrender.ExtentRender; 59 import nextapp.echo2.webcontainer.propertyrender.FillImageRender; 60 import nextapp.echo2.webcontainer.propertyrender.FontRender; 61 import nextapp.echo2.webrender.ServerMessage; 62 import nextapp.echo2.webrender.Service; 63 import nextapp.echo2.webrender.WebRenderServlet; 64 import nextapp.echo2.webrender.output.CssStyle; 65 import nextapp.echo2.webrender.servermessage.DomUpdate; 66 import nextapp.echo2.webrender.servermessage.VirtualPosition; 67 import nextapp.echo2.webrender.service.JavaScriptService; 68 69 75 public class ContentPanePeer 76 implements ComponentSynchronizePeer, DomUpdateSupport, ImageRenderSupport, PropertyUpdateProcessor { 77 78 81 private static final Extent EXTENT_0 = new Extent(0); 82 private static final Insets DEFAULT_INSETS = new Insets(EXTENT_0); 83 84 private static final String IMAGE_ID_BACKGROUND = "background"; 85 86 89 private static final Service CONTENT_PANE_SERVICE = JavaScriptService.forResource("Echo.ContentPane", 90 "/nextapp/echo2/webcontainer/resource/js/ContentPane.js"); 91 92 static { 93 WebRenderServlet.getServiceRegistry().add(CONTENT_PANE_SERVICE); 94 } 95 96 private PartialUpdateManager partialUpdateManager; 97 98 101 public ContentPanePeer() { 102 super(); 103 partialUpdateManager = new PartialUpdateManager(); 104 partialUpdateManager.add(ContentPane.PROPERTY_HORIZONTAL_SCROLL, new PartialUpdateParticipant() { 105 106 public void renderProperty(RenderContext rc, ServerComponentUpdate update) { 107 renderScrollDirective(rc, (ContentPane) update.getParent(), true); 108 } 109 110 public boolean canRenderProperty(RenderContext rc, ServerComponentUpdate update) { 111 return true; 112 } 113 }); 114 partialUpdateManager.add(ContentPane.PROPERTY_VERTICAL_SCROLL, new PartialUpdateParticipant() { 115 116 public void renderProperty(RenderContext rc, ServerComponentUpdate update) { 117 renderScrollDirective(rc, (ContentPane) update.getParent(), false); 118 } 119 120 public boolean canRenderProperty(RenderContext rc, ServerComponentUpdate update) { 121 return true; 122 } 123 }); 124 } 125 126 129 public String getContainerId(Component child) { 130 return getContainerId(child.getParent(), child); 131 } 132 133 private String getContainerId(Component parent, Component child) { 134 if (child instanceof FloatingPane) { 135 return ContainerInstance.getElementId(parent) + "_float_" + ContainerInstance.getElementId(child); 136 } else { 137 return ContainerInstance.getElementId(parent) + "_content_" + ContainerInstance.getElementId(child); 138 } 139 } 140 141 144 public ImageReference getImage(Component component, String imageId) { 145 if (IMAGE_ID_BACKGROUND.equals(imageId)) { 146 FillImage backgroundImage 147 = (FillImage) component.getRenderProperty(AbstractButton.PROPERTY_BACKGROUND_IMAGE); 148 if (backgroundImage == null) { 149 return null; 150 } else { 151 return backgroundImage.getImage(); 152 } 153 } else { 154 return null; 155 } 156 } 157 158 162 public void renderAdd(RenderContext rc, ServerComponentUpdate update, String targetId, Component component) { 163 Element domAddElement = DomUpdate.renderElementAdd(rc.getServerMessage()); 164 DocumentFragment htmlFragment = rc.getServerMessage().getDocument().createDocumentFragment(); 165 renderHtml(rc, update, htmlFragment, component); 166 DomUpdate.renderElementAddContent(rc.getServerMessage(), domAddElement, targetId, htmlFragment); 167 } 168 169 177 private void renderAddChildren(RenderContext rc, ServerComponentUpdate update) { 178 ContentPane contentPane = (ContentPane) update.getParent(); 179 String elementId = ContainerInstance.getElementId(contentPane); 180 Component[] components = update.getParent().getVisibleComponents(); 181 Component[] addedChildren = update.getAddedChildren(); 182 183 for (int componentIndex = components.length - 1; componentIndex >= 0; --componentIndex) { 184 boolean childFound = false; 185 for (int addedChildrenIndex = 0; !childFound && addedChildrenIndex < addedChildren.length; ++addedChildrenIndex) { 186 if (addedChildren[addedChildrenIndex] == components[componentIndex]) { 187 Element domAddElement = DomUpdate.renderElementAdd(rc.getServerMessage()); 188 DocumentFragment htmlFragment = rc.getServerMessage().getDocument().createDocumentFragment(); 189 renderChild(rc, update, htmlFragment, contentPane, components[componentIndex]); 190 191 if (componentIndex == components.length - 1) { 192 DomUpdate.renderElementAddContent(rc.getServerMessage(), domAddElement, elementId, htmlFragment); 193 } else { 194 DomUpdate.renderElementAddContent(rc.getServerMessage(), domAddElement, 195 elementId, getContainerId(components[componentIndex + 1]), htmlFragment); 196 } 197 198 childFound = true; 199 } 200 } 201 } 202 } 203 204 214 private void renderChild(RenderContext rc, ServerComponentUpdate update, Node parentNode, 215 ContentPane contentPane, Component child) { 216 Element containerDivElement = parentNode.getOwnerDocument().createElement("div"); 217 String containerId = getContainerId(child); 218 containerDivElement.setAttribute("id", containerId); 219 if (!(child instanceof FloatingPane)) { 220 CssStyle style = new CssStyle(); 221 style.setAttribute("position", "absolute"); 222 style.setAttribute("overflow", "auto"); 223 style.setAttribute("z-index", "0"); 224 Insets insets = (Insets) contentPane.getRenderProperty(ContentPane.PROPERTY_INSETS, DEFAULT_INSETS); 225 style.setAttribute("top", ExtentRender.renderCssAttributePixelValue(insets.getTop(), "0")); 226 style.setAttribute("left", ExtentRender.renderCssAttributePixelValue(insets.getLeft(), "0")); 227 style.setAttribute("right", ExtentRender.renderCssAttributePixelValue(insets.getRight(), "0")); 228 style.setAttribute("bottom", ExtentRender.renderCssAttributePixelValue(insets.getBottom(), "0")); 229 containerDivElement.setAttribute("style", style.renderInline()); 230 VirtualPosition.renderRegister(rc.getServerMessage(), containerId); 231 } 232 233 parentNode.appendChild(containerDivElement); 234 ComponentSynchronizePeer syncPeer = SynchronizePeerFactory.getPeerForComponent(child.getClass()); 235 if (syncPeer instanceof DomUpdateSupport) { 236 ((DomUpdateSupport) syncPeer).renderHtml(rc, update, containerDivElement, child); 237 } else { 238 syncPeer.renderAdd(rc, update, containerId, child); 239 } 240 } 241 242 246 public void renderDispose(RenderContext rc, ServerComponentUpdate update, Component component) { 247 rc.getServerMessage().addLibrary(CONTENT_PANE_SERVICE.getId()); 248 renderDisposeDirective(rc, (ContentPane) component); 249 } 250 251 259 private void renderDisposeDirective(RenderContext rc, ContentPane contentPane) { 260 ServerMessage serverMessage = rc.getServerMessage(); 261 Element itemizedUpdateElement = serverMessage.getItemizedDirective(ServerMessage.GROUP_ID_PREREMOVE, 262 "EchoContentPane.MessageProcessor", "dispose", new String [0], new String [0]); 263 Element itemElement = serverMessage.getDocument().createElement("item"); 264 itemElement.setAttribute("eid", ContainerInstance.getElementId(contentPane)); 265 itemizedUpdateElement.appendChild(itemElement); 266 } 267 268 272 public void renderHtml(RenderContext rc, ServerComponentUpdate update, Node parentNode, Component component) { 273 ContentPane contentPane = (ContentPane) component; 274 275 ServerMessage serverMessage = rc.getServerMessage(); 276 serverMessage.addLibrary(CONTENT_PANE_SERVICE.getId()); 277 278 Document document = parentNode.getOwnerDocument(); 279 Element divElement = document.createElement("div"); 280 divElement.setAttribute("id", ContainerInstance.getElementId(component)); 281 282 CssStyle cssStyle = new CssStyle(); 283 cssStyle.setAttribute("position", "absolute"); 284 cssStyle.setAttribute("width", "100%"); 285 cssStyle.setAttribute("height", "100%"); 286 cssStyle.setAttribute("overflow", "hidden"); 287 cssStyle.setAttribute("z-index", "0"); 288 ColorRender.renderToStyle(cssStyle, (Color) contentPane.getRenderProperty(ContentPane.PROPERTY_FOREGROUND), 289 (Color) contentPane.getRenderProperty(ContentPane.PROPERTY_BACKGROUND)); 290 FontRender.renderToStyle(cssStyle, (Font) contentPane.getRenderProperty(ContentPane.PROPERTY_FONT)); 291 FillImageRender.renderToStyle(cssStyle, rc, this, contentPane, IMAGE_ID_BACKGROUND, 292 (FillImage) contentPane.getRenderProperty(ContentPane.PROPERTY_BACKGROUND_IMAGE), 0); 293 divElement.setAttribute("style", cssStyle.renderInline()); 294 295 parentNode.appendChild(divElement); 296 297 renderInitDirective(rc, contentPane); 299 300 Component[] children = contentPane.getVisibleComponents(); 301 for (int i = 0; i < children.length; ++i) { 302 renderChild(rc, update, divElement, contentPane, children[i]); 303 } 304 } 305 306 314 private void renderInitDirective(RenderContext rc, ContentPane contentPane) { 315 String elementId = ContainerInstance.getElementId(contentPane); 316 ServerMessage serverMessage = rc.getServerMessage(); 317 318 Element itemizedUpdateElement = serverMessage.getItemizedDirective(ServerMessage.GROUP_ID_POSTUPDATE, 319 "EchoContentPane.MessageProcessor", "init", new String [0], new String [0]); 320 Element itemElement = serverMessage.getDocument().createElement("item"); 321 itemElement.setAttribute("eid", elementId); 322 Extent horizontalScroll = (Extent) contentPane.getRenderProperty(ContentPane.PROPERTY_HORIZONTAL_SCROLL); 323 if (horizontalScroll != null && horizontalScroll.getValue() != 0) { 324 itemElement.setAttribute("horizontal-scroll", ExtentRender.renderCssAttributeValue(horizontalScroll)); 325 } 326 Extent verticalScroll = (Extent) contentPane.getRenderProperty(ContentPane.PROPERTY_VERTICAL_SCROLL); 327 if (verticalScroll != null && verticalScroll.getValue() != 0) { 328 itemElement.setAttribute("vertical-scroll", ExtentRender.renderCssAttributeValue(verticalScroll)); 329 } 330 itemizedUpdateElement.appendChild(itemElement); 331 } 332 333 342 private void renderScrollDirective(RenderContext rc, ContentPane contentPane, boolean horizontal) { 343 ServerMessage serverMessage = rc.getServerMessage(); 344 Element scrollElement = 345 serverMessage.appendPartDirective(ServerMessage.GROUP_ID_POSTUPDATE, "EchoContentPane.MessageProcessor", 346 horizontal ? "scroll-horizontal" : "scroll-vertical"); 347 Extent position = (Extent) contentPane.getRenderProperty( 348 horizontal ? ContentPane.PROPERTY_HORIZONTAL_SCROLL : ContentPane.PROPERTY_VERTICAL_SCROLL, EXTENT_0); 349 scrollElement.setAttribute("eid", ContainerInstance.getElementId(contentPane)); 350 scrollElement.setAttribute("position", ExtentRender.renderCssAttributeValue(position)); 351 } 352 353 361 private void renderRemoveChildren(RenderContext rc, ServerComponentUpdate update) { 362 Component[] removedChildren = update.getRemovedChildren(); 363 for (int i = 0; i < removedChildren.length; ++i) { 364 DomUpdate.renderElementRemove(rc.getServerMessage(), getContainerId(update.getParent(), removedChildren[i])); 365 } 366 } 367 371 public boolean renderUpdate(RenderContext rc, ServerComponentUpdate update, String targetId) { 372 boolean fullReplace = false; 373 if (update.hasUpdatedLayoutDataChildren()) { 374 fullReplace = true; 375 } else if (update.hasUpdatedProperties()) { 376 if (!partialUpdateManager.canProcess(rc, update)) { 377 fullReplace = true; 378 } 379 } 380 381 if (fullReplace) { 382 DomUpdate.renderElementRemove(rc.getServerMessage(), 384 ContainerInstance.getElementId(update.getParent())); 385 renderAdd(rc, update, targetId, update.getParent()); 386 } else { 387 partialUpdateManager.process(rc, update); 388 if (update.hasAddedChildren() || update.hasRemovedChildren()) { 389 renderContentChange(rc, update); 390 } 391 } 392 return fullReplace; 393 } 394 395 406 private void renderContentChange(RenderContext rc, ServerComponentUpdate update) { 407 boolean primaryContentChanged = false; 408 Component[] addedChildren = update.getAddedChildren(); 409 for (int i = 0; i < addedChildren.length; ++i) { 410 if (!(addedChildren[i] instanceof FloatingPane)) { 411 primaryContentChanged = true; 412 break; 413 } 414 } 415 if (!primaryContentChanged) { 416 Component[] removedChildren = update.getRemovedChildren(); 417 for (int i = 0; i < removedChildren.length; ++i) { 418 if (!(removedChildren[i] instanceof FloatingPane)) { 419 primaryContentChanged = true; 420 break; 421 } 422 } 423 } 424 425 if (primaryContentChanged) { 426 renderDisposeDirective(rc, (ContentPane) update.getParent()); 427 } 428 429 renderRemoveChildren(rc, update); 430 renderAddChildren(rc, update); 431 432 if (primaryContentChanged) { 433 renderInitDirective(rc, (ContentPane) update.getParent()); 434 } 435 } 436 437 442 public void processPropertyUpdate(ContainerInstance ci, Component component, Element propertyElement) { 443 if ("horizontalScroll".equals(propertyElement.getAttribute(PropertyUpdateProcessor.PROPERTY_NAME))) { 444 Extent newValue = ExtentRender.toExtent(propertyElement.getAttribute(PropertyUpdateProcessor.PROPERTY_VALUE)); 445 ci.getUpdateManager().getClientUpdateManager().setComponentProperty(component, 446 ContentPane.PROPERTY_HORIZONTAL_SCROLL, newValue); 447 } else if ("verticalScroll".equals(propertyElement.getAttribute(PropertyUpdateProcessor.PROPERTY_NAME))) { 448 Extent newValue = ExtentRender.toExtent(propertyElement.getAttribute(PropertyUpdateProcessor.PROPERTY_VALUE)); 449 ci.getUpdateManager().getClientUpdateManager().setComponentProperty(component, 450 ContentPane.PROPERTY_VERTICAL_SCROLL, newValue); 451 } 452 } 453 } 454 | Popular Tags |