KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > nextapp > echo2 > webcontainer > syncpeer > ListComponentPeer


1 /*
2  * This file is part of the Echo Web Application Framework (hereinafter "Echo").
3  * Copyright (C) 2002-2005 NextApp, Inc.
4  *
5  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * Alternatively, the contents of this file may be used under the terms of
18  * either the GNU General Public License Version 2 or later (the "GPL"), or
19  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20  * in which case the provisions of the GPL or the LGPL are applicable instead
21  * of those above. If you wish to allow use of your version of this file only
22  * under the terms of either the GPL or the LGPL, and not to allow others to
23  * use your version of this file under the terms of the MPL, indicate your
24  * decision by deleting the provisions above and replace them with the notice
25  * and other provisions required by the GPL or the LGPL. If you do not delete
26  * the provisions above, a recipient may use your version of this file under
27  * the terms of any one of the MPL, the GPL or the LGPL.
28  */

29
30 package nextapp.echo2.webcontainer.syncpeer;
31
32 import java.util.HashMap JavaDoc;
33 import java.util.Map JavaDoc;
34
35 import org.w3c.dom.Document JavaDoc;
36 import org.w3c.dom.Element JavaDoc;
37
38 import nextapp.echo2.app.Border;
39 import nextapp.echo2.app.Color;
40 import nextapp.echo2.app.Component;
41 import nextapp.echo2.app.Extent;
42 import nextapp.echo2.app.Font;
43 import nextapp.echo2.app.Insets;
44 import nextapp.echo2.app.ListBox;
45 import nextapp.echo2.app.list.AbstractListComponent;
46 import nextapp.echo2.app.list.ListCellRenderer;
47 import nextapp.echo2.app.list.ListModel;
48 import nextapp.echo2.app.list.ListSelectionModel;
49 import nextapp.echo2.app.list.StyledListCell;
50 import nextapp.echo2.app.update.ServerComponentUpdate;
51 import nextapp.echo2.webcontainer.ActionProcessor;
52 import nextapp.echo2.webcontainer.ComponentSynchronizePeer;
53 import nextapp.echo2.webcontainer.ContainerInstance;
54 import nextapp.echo2.webcontainer.FocusSupport;
55 import nextapp.echo2.webcontainer.PartialUpdateManager;
56 import nextapp.echo2.webcontainer.PropertyUpdateProcessor;
57 import nextapp.echo2.webcontainer.RenderContext;
58 import nextapp.echo2.webcontainer.propertyrender.BorderRender;
59 import nextapp.echo2.webcontainer.propertyrender.ColorRender;
60 import nextapp.echo2.webcontainer.propertyrender.ExtentRender;
61 import nextapp.echo2.webcontainer.propertyrender.FontRender;
62 import nextapp.echo2.webcontainer.propertyrender.InsetsRender;
63 import nextapp.echo2.webrender.ClientProperties;
64 import nextapp.echo2.webrender.ServerMessage;
65 import nextapp.echo2.webrender.Service;
66 import nextapp.echo2.webrender.WebRenderServlet;
67 import nextapp.echo2.webrender.output.CssStyle;
68 import nextapp.echo2.webrender.servermessage.DomUpdate;
69 import nextapp.echo2.webrender.servermessage.WindowUpdate;
70 import nextapp.echo2.webrender.service.JavaScriptService;
71 import nextapp.echo2.webrender.util.DomUtil;
72
73 /**
74  * <code>ComponentSynchronizePeer</code> implementation for
75  * <code>AbstractListComponent</code>-based components.
76  * <p>
77  * This peer renders the content of list components in the
78  * <code>ServerMessage</code>'s initialization section
79  * (<code>ServerMessage.GROUP_ID_INIT</code>) such that a single
80  * rendering of content may be used by multiple list components
81  * if possible.
82  * <p>
83  * This class should not be extended or used by classes outside of the
84  * Echo framework.
85  */

86 public class ListComponentPeer
87 implements ActionProcessor, ComponentSynchronizePeer, FocusSupport, PropertyUpdateProcessor {
88
89     /**
90      * Service to provide supporting JavaScript library.
91      */

92     public static final Service LIST_COMPONENT_SERVICE = JavaScriptService.forResource("Echo.ListComponent",
93             "/nextapp/echo2/webcontainer/resource/js/ListComponent.js");
94
95     static {
96         WebRenderServlet.getServiceRegistry().add(LIST_COMPONENT_SERVICE);
97     }
98     
99     private static final String JavaDoc PROPERTY_SELECTION = "selection";
100     
101     // Default Colors
102
private static final Color DEFAULT_BACKGROUND = Color.WHITE;
103     private static final Color DEFAULT_FOREGROUND = Color.BLACK;
104
105     // Default Sizes
106
private static final Extent DEFAULT_WIDTH = new Extent(100, Extent.PERCENT);
107     private static final Insets DEFAULT_INSETS = new Insets(new Extent(0), new Extent(0));
108
109     /**
110      * Key for <code>Connection</code> property containing a <code>Map</code> which maps
111      * RenderedModelData instances to ids.
112      */

113     private static final String JavaDoc RENDERED_MODEL_MAP_KEY
114             = "nextapp.echo2.webcontainer.syncpeer.ListComponentPeer.RenderedModelMap";
115
116     private PartialUpdateManager partialUpdateManager;
117     
118     /**
119      * A representation of the content of a list component, i.e., the
120      * contents of the <code>ListModel</code> after having been run through a
121      * <code>ListCellRenderer</code>.
122      */

123     private class RenderedModelData {
124         
125         /**
126          * An array containing the String values of the list component.
127          */

128         private String JavaDoc[] values;
129         
130         /**
131          * An array containing the CSS style values of the list component.
132          * May be null, or contain nulls representing list items without style.
133          */

134         private String JavaDoc[] styles;
135         
136         /**
137          * Cached hash code.
138          */

139         private int hashCode;
140
141         /**
142          * Creates a new <code>RenderedModelData</code> instance.
143          *
144          * @param model the <code>ListModel</code>
145          * @param renderer the <code>ListCellRenderer</code>
146          */

147         private RenderedModelData(AbstractListComponent listComponent) {
148             ListModel model = listComponent.getModel();
149             ListCellRenderer renderer = listComponent.getCellRenderer();
150             
151             int size = model.size();
152             values = new String JavaDoc[size];
153             for (int i = 0; i < values.length; ++i) {
154                 Object JavaDoc renderedValue = renderer.getListCellRendererComponent(listComponent, model.get(i), i);
155                 values[i] = renderedValue.toString();
156                 
157                 if (renderedValue instanceof StyledListCell) {
158                     StyledListCell styledListCell = (StyledListCell) renderedValue;
159                     CssStyle itemStyle = new CssStyle();
160                     ColorRender.renderToStyle(itemStyle, styledListCell.getForeground(), styledListCell.getBackground());
161                     FontRender.renderToStyle(itemStyle, styledListCell.getFont());
162                     if (itemStyle.hasAttributes()) {
163                         if (styles == null) {
164                             styles = new String JavaDoc[size];
165                         }
166                         styles[i] = itemStyle.renderInline();
167                     }
168                 }
169             }
170         }
171         
172         /**
173          * @see java.lang.Object#hashCode()
174          */

175         public int hashCode() {
176             if (hashCode == 0) {
177                 hashCode = values.length;
178                 for (int i = 0; i < values.length; ++i) {
179                     if (values[i] != null) {
180                         hashCode ^= values[i].hashCode();
181                     }
182                 }
183                 if (hashCode == 0) {
184                     hashCode = 1;
185                 }
186             }
187             return hashCode;
188         }
189         
190         /**
191          * @see java.lang.Object#equals(java.lang.Object)
192          */

193         public boolean equals(Object JavaDoc o) {
194             if (!(o instanceof RenderedModelData)) {
195                 return false;
196             }
197             RenderedModelData that = (RenderedModelData) o;
198             if (this.values.length != that.values.length) {
199                 return false;
200             }
201             for (int i = 0; i < this.values.length; ++i) {
202                 if (!(this.values[i] == that.values[i] || (this.values[i] != null && this.values[i].equals(that.values[i])))) {
203                     return false;
204                 }
205             }
206             if (this.styles != null || that.styles != null) {
207                 if (this.styles == null || that.styles == null) {
208                     return false;
209                 }
210                 for (int i = 0; i < this.styles.length; ++i) {
211                     if (!(this.styles[i] == that.styles[i] || (this.styles[i] != null && this.styles[i].equals(that.styles[i])))) {
212                         return false;
213                     }
214                 }
215             }
216             return true;
217         }
218     }
219
220     /**
221      * Default constructor.
222      */

223     public ListComponentPeer() {
224         super();
225         partialUpdateManager = new PartialUpdateManager();
226     }
227
228     /**
229      * Appends the base style to the given style based off of properties on the
230      * given <code>nextapp.echo2.app.AbstractListComponent</code>
231      *
232      * @param rc the relevant <code>RenderContext</code>
233      * @param listComponent the <code>nextapp.echo2.app.AbstractListComponent</code>
234      */

235     private CssStyle createListComponentCssStyle(RenderContext rc, AbstractListComponent listComponent) {
236         CssStyle cssStyle = new CssStyle();
237
238         boolean renderEnabled = listComponent.isRenderEnabled();
239
240         Border border;
241         Color foreground, background;
242         Font font;
243         if (!renderEnabled) {
244             // Retrieve disabled style information.
245
background = (Color) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_DISABLED_BACKGROUND);
246             border = (Border) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_DISABLED_BORDER);
247             font = (Font) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_DISABLED_FONT);
248             foreground = (Color) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_DISABLED_FOREGROUND);
249
250             // Fallback to normal styles.
251
if (background == null) {
252                 background = (Color) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_BACKGROUND,
253                         DEFAULT_BACKGROUND);
254             }
255             if (border == null) {
256                 border = (Border) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_BORDER);
257             }
258             if (font == null) {
259                 font = (Font) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_FONT);
260             }
261             if (foreground == null) {
262                 foreground = (Color) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_FOREGROUND,
263                         DEFAULT_FOREGROUND);
264             }
265         } else {
266             border = (Border) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_BORDER);
267             foreground = (Color) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_FOREGROUND, DEFAULT_FOREGROUND);
268             background = (Color) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_BACKGROUND, DEFAULT_BACKGROUND);
269             font = (Font) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_FONT);
270         }
271         
272         BorderRender.renderToStyle(cssStyle, border);
273         ColorRender.renderToStyle(cssStyle, foreground, background);
274         FontRender.renderToStyle(cssStyle, font);
275         
276         Extent width = (Extent) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_WIDTH, DEFAULT_WIDTH);
277         if (rc.getContainerInstance().getClientProperties().getBoolean(ClientProperties.QUIRK_IE_SELECT_PERCENT_WIDTH)
278                 && width.getUnits() == Extent.PERCENT) {
279             // Render default width.
280
width = null;
281         }
282         Extent height = (Extent) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_HEIGHT);
283         Insets insets = (Insets) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_INSETS, DEFAULT_INSETS);
284
285         InsetsRender.renderToStyle(cssStyle, "padding", insets);
286         ExtentRender.renderToStyle(cssStyle, "width", width);
287         ExtentRender.renderToStyle(cssStyle, "height", height);
288         cssStyle.setAttribute("position", "relative");
289
290         return cssStyle;
291     }
292     
293     /**
294      * Creates the rollover style based off of properties on the given
295      * <code>nextapp.echo2.app.AbstractListComponent</code>
296      *
297      * @param listComponent the <code>AbstractListComponent</code> instance
298      * @return the style
299      */

300     private CssStyle createRolloverCssStyle(AbstractListComponent listComponent) {
301         CssStyle style = new CssStyle();
302         Color rolloverForeground = (Color) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_ROLLOVER_FOREGROUND);
303         Color rolloverBackground = (Color) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_ROLLOVER_BACKGROUND);
304         ColorRender.renderToStyle(style, rolloverForeground, rolloverBackground);
305         FontRender.renderToStyle(style, (Font) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_ROLLOVER_FONT));
306         return style;
307     }
308     
309     /**
310      * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#getContainerId(nextapp.echo2.app.Component)
311      */

312     public String JavaDoc getContainerId(Component child) {
313         throw new UnsupportedOperationException JavaDoc("Component does not support children.");
314     }
315
316     /**
317      * @see nextapp.echo2.webcontainer.ActionProcessor#processAction(nextapp.echo2.webcontainer.ContainerInstance,
318      * nextapp.echo2.app.Component, org.w3c.dom.Element)
319      */

320     public void processAction(ContainerInstance ci, Component component, Element JavaDoc actionElement) {
321         ci.getUpdateManager().getClientUpdateManager().setComponentAction(component, AbstractListComponent.INPUT_ACTION, null);
322     }
323
324     /**
325      * @see nextapp.echo2.webcontainer.PropertyUpdateProcessor#processPropertyUpdate(nextapp.echo2.webcontainer.ContainerInstance,
326      * nextapp.echo2.app.Component, org.w3c.dom.Element)
327      */

328     public void processPropertyUpdate(ContainerInstance ci, Component component, Element JavaDoc propertyElement) {
329         String JavaDoc propertyName = propertyElement.getAttribute(PropertyUpdateProcessor.PROPERTY_NAME);
330         if (PROPERTY_SELECTION.equals(propertyName)) {
331             Element JavaDoc[] itemElements = DomUtil.getChildElementsByTagName(propertyElement, "item");
332             int[] selectedIndices = new int[itemElements.length];
333             for (int i = 0; i < itemElements.length; ++i) {
334                 selectedIndices[i] = Integer.parseInt(itemElements[i].getAttribute("index"));
335             }
336             ci.getUpdateManager().getClientUpdateManager().setComponentProperty(component,
337                     AbstractListComponent.SELECTION_CHANGED_PROPERTY, selectedIndices);
338         }
339     }
340
341     /**
342      * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#renderAdd(
343      * nextapp.echo2.webcontainer.RenderContext, nextapp.echo2.app.update.ServerComponentUpdate,
344      * java.lang.String, nextapp.echo2.app.Component)
345      */

346     public void renderAdd(RenderContext rc, ServerComponentUpdate update, String JavaDoc targetId, Component component) {
347         ServerMessage serverMessage = rc.getServerMessage();
348         serverMessage.addLibrary(LIST_COMPONENT_SERVICE.getId());
349         AbstractListComponent listComponent = (AbstractListComponent) component;
350         renderInitDirective(rc, listComponent, targetId);
351     }
352
353     /**
354      * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#renderDispose(nextapp.echo2.webcontainer.RenderContext,
355      * nextapp.echo2.app.update.ServerComponentUpdate, nextapp.echo2.app.Component)
356      */

357     public void renderDispose(RenderContext rc, ServerComponentUpdate update, Component component) {
358         ServerMessage serverMessage = rc.getServerMessage();
359         serverMessage.addLibrary(LIST_COMPONENT_SERVICE.getId());
360         renderDisposeDirective(rc, (AbstractListComponent) component);
361     }
362     
363     /**
364      * Renders a directive to the outgoing <code>ServerMessage</code> to
365      * dispose the state of the <code>AbstractListComponent</code>, performing
366      * tasks such as unregistering event listeners on the client.
367      *
368      * @param rc the relevant <code>RenderContext</code>
369      * @param listComponent the <code>AbstractListComponent</code>
370      */

371     private void renderDisposeDirective(RenderContext rc, AbstractListComponent listComponent) {
372         String JavaDoc elementId = ContainerInstance.getElementId(listComponent);
373         ServerMessage serverMessage = rc.getServerMessage();
374         Element JavaDoc initElement = serverMessage.appendPartDirective(ServerMessage.GROUP_ID_PREREMOVE,
375                 "EchoListComponent.MessageProcessor", "dispose");
376         initElement.setAttribute("eid", elementId);
377     }
378
379     /**
380      * Renders content for an <code>AbstractListComponent</code> (if necessary);
381      * returns the content id.
382      *
383      * @param rc the relevant <code>RenderContext</code>
384      * @param listComponent the <code>AbstractListComponent</code>
385      * @return the content id
386      */

387     private String JavaDoc renderContent(RenderContext rc, AbstractListComponent listComponent) {
388         RenderedModelData renderedModelData = new RenderedModelData(listComponent);
389         
390         Map JavaDoc renderedModelDataToIdMap = (Map JavaDoc) rc.getConnection().getProperty(RENDERED_MODEL_MAP_KEY);
391         if (renderedModelDataToIdMap == null) {
392             renderedModelDataToIdMap = new HashMap JavaDoc();
393             rc.getConnection().setProperty(RENDERED_MODEL_MAP_KEY, renderedModelDataToIdMap);
394         }
395         String JavaDoc contentId = (String JavaDoc) renderedModelDataToIdMap.get(renderedModelData);
396         if (contentId == null) {
397             contentId = Integer.toString(renderedModelDataToIdMap.size());
398             renderedModelDataToIdMap.put(renderedModelData, contentId);
399             renderLoadContentDirective(rc, renderedModelData, contentId);
400         }
401         return contentId;
402     }
403     
404     /**
405      * Renders a directive to load the content (a rendered version of model)
406      * to the client.
407      *
408      * @param rc the relevant <code>RenderContext</code>
409      * @param renderedModelData the <code>RenderedModelData</code> object to render
410      * @param contentId the content id to associate with the rendered content
411      */

412     private void renderLoadContentDirective(RenderContext rc, RenderedModelData renderedModelData, String JavaDoc contentId) {
413         ServerMessage serverMessage = rc.getServerMessage();
414         Element JavaDoc partElement = serverMessage.appendPartDirective(ServerMessage.GROUP_ID_INIT,
415                 "EchoListComponent.MessageProcessor", "load-content");
416         partElement.setAttribute("content-id", contentId);
417         Document JavaDoc document = serverMessage.getDocument();
418         
419         if (renderedModelData.styles != null) {
420             partElement.setAttribute("styled", "true");
421         }
422
423         for (int i = 0; i < renderedModelData.values.length; ++i) {
424             Element JavaDoc itemElement = document.createElement("item");
425             itemElement.setAttribute("value", renderedModelData.values[i] == null
426                     ? "" : renderedModelData.values[i].toString());
427             if (renderedModelData.styles != null) {
428                 itemElement.setAttribute("style", renderedModelData.styles[i] == null
429                         ? "" : renderedModelData.styles[i].toString());
430             }
431             
432             partElement.appendChild(itemElement);
433         }
434     }
435     
436     /**
437      * Renders a directive to the outgoing <code>ServerMessage</code> to
438      * render and intialize the state of a list component.
439      *
440      * @param rc the relevant <code>RenderContext</code>
441      * @param listComponent the component
442      * @param targetId the id of the container element
443      */

444     private void renderInitDirective(RenderContext rc, AbstractListComponent listComponent, String JavaDoc targetId) {
445         String JavaDoc contentId = renderContent(rc, listComponent);
446         String JavaDoc elementId = ContainerInstance.getElementId(listComponent);
447         ServerMessage serverMessage = rc.getServerMessage();
448         Document JavaDoc document = serverMessage.getDocument();
449
450         Element JavaDoc initElement = serverMessage.appendPartDirective(ServerMessage.GROUP_ID_UPDATE,
451                 "EchoListComponent.MessageProcessor", "init");
452         initElement.setAttribute("container-eid", targetId);
453         initElement.setAttribute("eid", elementId);
454         initElement.setAttribute("content-id", contentId);
455         
456         initElement.setAttribute("enabled", listComponent.isRenderEnabled() ? "true" : "false");
457     
458         if (listComponent.hasActionListeners()) {
459             initElement.setAttribute("server-notify", "true");
460         }
461         
462         CssStyle cssStyle = createListComponentCssStyle(rc, listComponent);
463         initElement.setAttribute("style", cssStyle.renderInline());
464
465         Boolean JavaDoc rolloverEnabled = (Boolean JavaDoc) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_ROLLOVER_ENABLED);
466         if (Boolean.TRUE.equals(rolloverEnabled)) {
467             CssStyle rolloverCssStyle = createRolloverCssStyle(listComponent);
468             initElement.setAttribute("rollover-style", rolloverCssStyle.renderInline());
469         }
470         
471         boolean multipleSelect = false;
472         if (listComponent instanceof ListBox) {
473             initElement.setAttribute("type", "list-box");
474             ListBox listBox = (ListBox) listComponent;
475             if (listBox.getSelectionMode() == ListSelectionModel.MULTIPLE_SELECTION) {
476                 initElement.setAttribute("multiple", "true");
477                 multipleSelect = true;
478             }
479         }
480
481         if (listComponent.isFocusTraversalParticipant()) {
482             initElement.setAttribute("tab-index", Integer.toString(listComponent.getFocusTraversalIndex()));
483         } else {
484             initElement.setAttribute("tab-index", "-1");
485         }
486         
487         String JavaDoc toolTipText = (String JavaDoc) listComponent.getRenderProperty(AbstractListComponent.PROPERTY_TOOL_TIP_TEXT);
488         if (toolTipText != null) {
489             initElement.setAttribute("tool-tip", toolTipText);
490         }
491         
492         // Render selection state.
493
ListSelectionModel selectionModel = listComponent.getSelectionModel();
494         int minIndex = selectionModel.getMinSelectedIndex();
495         if (minIndex >= 0) {
496             if (multipleSelect) {
497                 Element JavaDoc selectionElement = document.createElement("selection");
498                 int maxIndex = selectionModel.getMaxSelectedIndex();
499                 for (int i = minIndex; i <= maxIndex; ++i) {
500                     if (selectionModel.isSelectedIndex(i)) {
501                         Element JavaDoc itemElement = document.createElement("item");
502                         itemElement.setAttribute("index", Integer.toString(i));
503                         selectionElement.appendChild(itemElement);
504                     }
505                 }
506                 initElement.appendChild(selectionElement);
507             } else {
508                 initElement.setAttribute("selection-index", Integer.toString(minIndex));
509             }
510         }
511     }
512     
513     /**
514      * @see nextapp.echo2.webcontainer.FocusSupport#renderSetFocus(nextapp.echo2.webcontainer.RenderContext, nextapp.echo2.app.Component)
515      */

516     public void renderSetFocus(RenderContext rc, Component component) {
517         if (component.isEnabled()) {
518             WindowUpdate.renderSetFocus(rc.getServerMessage(), ContainerInstance.getElementId(component));
519         }
520     }
521
522     /**
523      * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#renderUpdate(
524      * nextapp.echo2.webcontainer.RenderContext, nextapp.echo2.app.update.ServerComponentUpdate, java.lang.String)
525      */

526     public boolean renderUpdate(RenderContext rc, ServerComponentUpdate update, String JavaDoc targetId) {
527         // Determine if fully replacing the component is required.
528
if (partialUpdateManager.canProcess(rc, update)) {
529             partialUpdateManager.process(rc, update);
530         } else {
531             // Perform full update.
532
DomUpdate.renderElementRemove(rc.getServerMessage(), ContainerInstance.getElementId(update.getParent()));
533             renderAdd(rc, update, targetId, update.getParent());
534         }
535         
536         return true;
537     }
538 }
539
Popular Tags