KickJava   Java API By Example, From Geeks To Geeks.

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


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 nextapp.echo2.app.FillImage;
33 import nextapp.echo2.app.Color;
34 import nextapp.echo2.app.Component;
35 import nextapp.echo2.app.Extent;
36 import nextapp.echo2.app.Font;
37 import nextapp.echo2.app.ImageReference;
38 import nextapp.echo2.app.LayoutData;
39 import nextapp.echo2.app.LayoutDirection;
40 import nextapp.echo2.app.Pane;
41 import nextapp.echo2.app.SplitPane;
42 import nextapp.echo2.app.layout.SplitPaneLayoutData;
43 import nextapp.echo2.app.update.ServerComponentUpdate;
44 import nextapp.echo2.webcontainer.ContainerInstance;
45 import nextapp.echo2.webcontainer.PartialUpdateManager;
46 import nextapp.echo2.webcontainer.PartialUpdateParticipant;
47 import nextapp.echo2.webcontainer.PropertyUpdateProcessor;
48 import nextapp.echo2.webcontainer.RenderContext;
49 import nextapp.echo2.webcontainer.ComponentSynchronizePeer;
50 import nextapp.echo2.webcontainer.RenderState;
51 import nextapp.echo2.webcontainer.SynchronizePeerFactory;
52 import nextapp.echo2.webcontainer.image.ImageRenderSupport;
53 import nextapp.echo2.webcontainer.propertyrender.AlignmentRender;
54 import nextapp.echo2.webcontainer.propertyrender.ColorRender;
55 import nextapp.echo2.webcontainer.propertyrender.ExtentRender;
56 import nextapp.echo2.webcontainer.propertyrender.FillImageRender;
57 import nextapp.echo2.webcontainer.propertyrender.FontRender;
58 import nextapp.echo2.webcontainer.propertyrender.InsetsRender;
59 import nextapp.echo2.webrender.ServerMessage;
60 import nextapp.echo2.webrender.Service;
61 import nextapp.echo2.webrender.WebRenderServlet;
62 import nextapp.echo2.webrender.output.CssStyle;
63 import nextapp.echo2.webrender.servermessage.DomUpdate;
64 import nextapp.echo2.webrender.service.JavaScriptService;
65
66 import org.w3c.dom.Element JavaDoc;
67
68 /**
69  * Synchronization peer for <code>nextapp.echo2.app.SplitPane</code> components.
70  * <p>
71  * This class should not be extended or used by classes outside of the
72  * Echo framework.
73  */

74 public class SplitPanePeer
75 implements ImageRenderSupport, PropertyUpdateProcessor, ComponentSynchronizePeer {
76     
77     //TODO: Performance can be improved by implementing PartialUpdateManagers.
78

79     private static final String JavaDoc IMAGE_ID_HORIZONTAL_SEPARATOR = "horizontalSeparator";
80     private static final String JavaDoc IMAGE_ID_PANE_0_BACKGROUND = "pane0Background";
81     private static final String JavaDoc IMAGE_ID_PANE_1_BACKGROUND = "pane1Background";
82     private static final String JavaDoc IMAGE_ID_VERTICAL_SEPARATOR = "verticalSeparator";
83     
84     private static final Extent DEFAULT_SEPARATOR_POSITION = new Extent(100);
85
86     /**
87      * <code>RenderState</code> implementation.
88      */

89     static class RenderStateImpl
90     implements RenderState {
91         
92         /**
93          * The pane which was rendered at index 0.
94          */

95         private String JavaDoc pane0;
96
97         /**
98          * The pane which was rendered at index 1.
99          */

100         private String JavaDoc pane1;
101
102         /**
103          * Creates a new <code>RenderState</code> based on the state of the
104          * given <code>splitPane</code>.
105          *
106          * @param splitPane the split pane
107          */

108         private RenderStateImpl(SplitPane splitPane) {
109             int componentCount = splitPane.getVisibleComponentCount();
110             pane0 = (componentCount < 1 || splitPane.getVisibleComponent(0) == null)
111                         ? null : ContainerInstance.getElementId(splitPane.getVisibleComponent(0));
112             pane1 = (componentCount < 2 || splitPane.getVisibleComponent(1) == null)
113                         ? null : ContainerInstance.getElementId(splitPane.getVisibleComponent(1));
114         }
115     }
116
117     /**
118      * Service to provide supporting JavaScript library.
119      */

120     private static final Service SPLIT_PANE_SERVICE = JavaScriptService.forResource("Echo.SplitPane",
121             "/nextapp/echo2/webcontainer/resource/js/SplitPane.js");
122
123     static {
124         WebRenderServlet.getServiceRegistry().add(SPLIT_PANE_SERVICE);
125     }
126     
127     /**
128      * Utility method to evaluate equality of objects in a null-safe fashion.
129      */

130     private static final boolean equal(Object JavaDoc a, Object JavaDoc b) {
131         return a == b || (a != null && a.equals(b));
132     }
133
134     /**
135      * <code>PartialUpdateParticipant</code> to update position of separator.
136      */

137     private PartialUpdateParticipant separatorPositionUpdate = new PartialUpdateParticipant() {
138     
139         /**
140          * @see nextapp.echo2.webcontainer.PartialUpdateParticipant#renderProperty(nextapp.echo2.webcontainer.RenderContext, nextapp.echo2.app.update.ServerComponentUpdate)
141          */

142         public void renderProperty(RenderContext rc, ServerComponentUpdate update) {
143             SplitPane splitPane = (SplitPane) update.getParent();
144             renderSetSeparatorPositionDirective(rc, splitPane);
145         }
146     
147         /**
148          * @see nextapp.echo2.webcontainer.PartialUpdateParticipant#canRenderProperty(nextapp.echo2.webcontainer.RenderContext, nextapp.echo2.app.update.ServerComponentUpdate)
149          */

150         public boolean canRenderProperty(RenderContext rc, ServerComponentUpdate update) {
151             return true;
152         }
153     
154     };
155     
156     private PartialUpdateManager partialUpdateManager;
157
158     /**
159      * Default constructor.
160      */

161     public SplitPanePeer() {
162         super();
163         partialUpdateManager = new PartialUpdateManager();
164         partialUpdateManager.add(SplitPane.PROPERTY_SEPARATOR_POSITION, separatorPositionUpdate);
165     }
166     
167     /**
168      * Calculates the pixel size of the separator.
169      *
170      * @param splitPane the <code>SplitPane</code> to evaluate
171      * @return the size of the separator in pixels
172      */

173     private int calculateSeparatorSize(SplitPane splitPane) {
174         Boolean JavaDoc booleanValue = (Boolean JavaDoc) splitPane.getRenderProperty(SplitPane.PROPERTY_RESIZABLE);
175         boolean resizable = booleanValue == null ? false : booleanValue.booleanValue();
176         boolean verticalOrientation = isOrientationVertical(splitPane);
177         if (resizable) {
178             return ExtentRender.toPixels((Extent) splitPane.getRenderProperty(
179                     verticalOrientation ? SplitPane.PROPERTY_SEPARATOR_HEIGHT : SplitPane.PROPERTY_SEPARATOR_WIDTH), 4);
180         } else {
181             return ExtentRender.toPixels((Extent) splitPane.getRenderProperty(
182                     verticalOrientation ? SplitPane.PROPERTY_SEPARATOR_HEIGHT : SplitPane.PROPERTY_SEPARATOR_WIDTH), 0);
183         }
184     }
185
186     /**
187      * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#getContainerId(nextapp.echo2.app.Component)
188      */

189     public String JavaDoc getContainerId(Component child) {
190         return ContainerInstance.getElementId(child.getParent()) + "_pane" + child.getParent().visibleIndexOf(child);
191     }
192     
193     /**
194      * @see nextapp.echo2.webcontainer.image.ImageRenderSupport#getImage(nextapp.echo2.app.Component, java.lang.String)
195      */

196     public ImageReference getImage(Component component, String JavaDoc imageId) {
197         if (IMAGE_ID_PANE_0_BACKGROUND.equals(imageId)) {
198             return getPaneBackgroundImage(component.getVisibleComponent(0));
199         } else if (IMAGE_ID_PANE_1_BACKGROUND.equals(imageId)) {
200             return getPaneBackgroundImage(component.getVisibleComponent(1));
201         } else if (IMAGE_ID_HORIZONTAL_SEPARATOR.equals(imageId)) {
202             FillImage fillImage = (FillImage) component.getRenderProperty(SplitPane.PROPERTY_SEPARATOR_HORIZONTAL_IMAGE);
203             return fillImage == null ? null : fillImage.getImage();
204         } else if (IMAGE_ID_VERTICAL_SEPARATOR.equals(imageId)) {
205             FillImage fillImage = (FillImage) component.getRenderProperty(SplitPane.PROPERTY_SEPARATOR_VERTICAL_IMAGE);
206             return fillImage == null ? null : fillImage.getImage();
207         } else {
208             return null;
209         }
210     }
211
212     /**
213      * Retrieves the <code>ImageReference</code> of the background image
214      * defined in the layout data of the specified component (pane).
215      * Returns null if the image cannot be retrieved for any reason.
216      *
217      * @param component the child pane component
218      * @return the background image
219      */

220     private ImageReference getPaneBackgroundImage(Component component) {
221         LayoutData layoutData = (LayoutData) component.getRenderProperty(SplitPane.PROPERTY_LAYOUT_DATA);
222         //TODO. Investigate use of instanceof here.
223
if (!(layoutData instanceof SplitPaneLayoutData)) {
224             return null;
225         }
226         FillImage backgroundImage = ((SplitPaneLayoutData) layoutData).getBackgroundImage();
227         if (backgroundImage == null) {
228             return null;
229         }
230         return backgroundImage.getImage();
231     }
232
233     private int getRenderOrientation(SplitPane splitPane) {
234         Integer JavaDoc orientationValue = (Integer JavaDoc) splitPane.getRenderProperty(SplitPane.PROPERTY_ORIENTATION);
235         int orientation = orientationValue == null ? SplitPane.ORIENTATION_HORIZONTAL_LEADING_TRAILING
236                 : orientationValue.intValue();
237         if (orientation == SplitPane.ORIENTATION_HORIZONTAL_LEADING_TRAILING
238                 || orientation == SplitPane.ORIENTATION_HORIZONTAL_TRAILING_LEADING) {
239             LayoutDirection layoutDirection = splitPane.getRenderLayoutDirection();
240             if (orientation == SplitPane.ORIENTATION_HORIZONTAL_LEADING_TRAILING) {
241                 orientation = layoutDirection.isLeftToRight() ? SplitPane.ORIENTATION_HORIZONTAL_LEFT_RIGHT
242                         : SplitPane.ORIENTATION_HORIZONTAL_RIGHT_LEFT;
243             } else {
244                 orientation = layoutDirection.isLeftToRight() ? SplitPane.ORIENTATION_HORIZONTAL_RIGHT_LEFT
245                         : SplitPane.ORIENTATION_HORIZONTAL_LEFT_RIGHT;
246             }
247         }
248         return orientation;
249     }
250
251     /**
252      * Determines if the orientation of a <code>SplitPane</code> is horizontal
253      * or vertical.
254      *
255      * @param splitPane the <code>SplitPane</code> to analyze
256      * @return true if the orientation is vertical, false if it is horizontal
257      */

258     private boolean isOrientationVertical(SplitPane splitPane) {
259         Integer JavaDoc orientationValue = (Integer JavaDoc) splitPane.getRenderProperty(SplitPane.PROPERTY_ORIENTATION);
260         int orientation = orientationValue == null ? SplitPane.ORIENTATION_HORIZONTAL : orientationValue.intValue();
261         return orientation == SplitPane.ORIENTATION_VERTICAL_TOP_BOTTOM ||
262                 orientation == SplitPane.ORIENTATION_VERTICAL_BOTTOM_TOP;
263     }
264     
265     /**
266      * @see nextapp.echo2.webcontainer.PropertyUpdateProcessor#processPropertyUpdate(
267      * nextapp.echo2.webcontainer.ContainerInstance, nextapp.echo2.app.Component, org.w3c.dom.Element)
268      */

269     public void processPropertyUpdate(ContainerInstance ci, Component component, Element JavaDoc propertyElement) {
270         if ("separatorPosition".equals(propertyElement.getAttribute(PropertyUpdateProcessor.PROPERTY_NAME))) {
271             Extent newValue = ExtentRender.toExtent(propertyElement.getAttribute(PropertyUpdateProcessor.PROPERTY_VALUE));
272             ci.getUpdateManager().getClientUpdateManager().setComponentProperty(component,
273                     SplitPane.PROPERTY_SEPARATOR_POSITION, newValue);
274         }
275     }
276
277     /**
278      * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#renderAdd(nextapp.echo2.webcontainer.RenderContext,
279      * nextapp.echo2.app.update.ServerComponentUpdate, java.lang.String, nextapp.echo2.app.Component)
280      */

281     public void renderAdd(RenderContext rc, ServerComponentUpdate update, String JavaDoc targetId, Component component) {
282         ServerMessage serverMessage = rc.getServerMessage();
283         serverMessage.addLibrary(SPLIT_PANE_SERVICE.getId());
284         SplitPane splitPane = (SplitPane) component;
285         renderInitDirective(rc, splitPane, targetId);
286         Component[] children = splitPane.getVisibleComponents();
287         for (int i = 0; i < children.length; ++i) {
288             renderChild(rc, update, splitPane, children[i]);
289         }
290         updateRenderState(rc, splitPane);
291     }
292     
293     private void renderAddChildDirective(RenderContext rc, ServerComponentUpdate update, SplitPane splitPane, int index) {
294         String JavaDoc elementId = ContainerInstance.getElementId(splitPane);
295         ServerMessage serverMessage = rc.getServerMessage();
296         Element JavaDoc partElement = serverMessage.addPart(ServerMessage.GROUP_ID_UPDATE, "EchoSplitPane.MessageProcessor");
297         Element JavaDoc addChildElement = serverMessage.getDocument().createElement("add-child");
298         addChildElement.setAttribute("eid", elementId);
299         addChildElement.setAttribute("index", Integer.toString(index));
300         Component child = splitPane.getVisibleComponent(index);
301         renderLayoutData(rc, addChildElement, child, index);
302         partElement.appendChild(addChildElement);
303         renderChild(rc, update, splitPane, child);
304     }
305     
306     /**
307      * Renders child components which were added to a
308      * <code>SplitPane</code>, as described in the provided
309      * <code>ServerComponentUpdate</code>.
310      *
311      * @param rc the relevant <code>RenderContext</code>
312      * @param update the update
313      */

314     private void renderAddChildren(RenderContext rc, ServerComponentUpdate update) {
315         ContainerInstance ci = rc.getContainerInstance();
316         SplitPane splitPane = (SplitPane) update.getParent();
317         
318         RenderStateImpl previousRenderState = (RenderStateImpl) ci.getRenderState(splitPane);
319         RenderStateImpl currentRenderState = new RenderStateImpl(splitPane);
320         if (!equal(previousRenderState.pane0, currentRenderState.pane0)) {
321             if (currentRenderState.pane0 != null) {
322                 renderAddChildDirective(rc, update, splitPane, 0);
323             }
324         }
325         if (!equal(previousRenderState.pane1, currentRenderState.pane1)) {
326             if (currentRenderState.pane1 != null) {
327                 renderAddChildDirective(rc, update, splitPane, 1);
328             }
329         }
330     }
331     
332     /**
333      * Renders an individual child component of the <code>SplitPane</code>.
334      *
335      * @param rc the relevant <code>RenderContext</code>
336      * @param update the <code>ServerComponentUpdate</code> being performed
337      * @param child The child <code>Component</code> to be rendered
338      */

339     private void renderChild(RenderContext rc, ServerComponentUpdate update, SplitPane splitPane, Component child) {
340         ComponentSynchronizePeer syncPeer = SynchronizePeerFactory.getPeerForComponent(child.getClass());
341         syncPeer.renderAdd(rc, update, getContainerId(child), child);
342     }
343
344     /**
345      * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#renderDispose(nextapp.echo2.webcontainer.RenderContext,
346      * nextapp.echo2.app.update.ServerComponentUpdate, nextapp.echo2.app.Component)
347      */

348     public void renderDispose(RenderContext rc, ServerComponentUpdate update, Component component) {
349         ServerMessage serverMessage = rc.getServerMessage();
350         serverMessage.addLibrary(SPLIT_PANE_SERVICE.getId());
351         renderDisposeDirective(rc, (SplitPane) component);
352
353 //BUGBUG. Temporarily removed, pending confirmation that fix is no longer relevant with new client-rendered SplitPane arch.
354
// // Performance Hack for Mozilla/Firefox Browsers:
355
// if (rc.getContainerInstance().getClientProperties()
356
// .getBoolean(ClientProperties.QUIRK_MOZILLA_PERFORMANCE_LARGE_DOM_REMOVE)) {
357
// String elementId = ContainerInstance.getElementId(component);
358
// if (!update.hasRemovedChild(component)) {
359
// DomUpdate.renderElementRemove(rc.getServerMessage(), elementId);
360
// }
361
// }
362
}
363
364     /**
365      * Renders a directive to the outgoing <code>ServerMessage</code> to
366      * dispose the state of a <code>SplitPane</code>, performing tasks such as
367      * unregistering event listeners on the client.
368      *
369      * @param rc the relevant <code>RenderContext</code>
370      * @param splitPane the <code>SplitPane</code>
371      */

372     private void renderDisposeDirective(RenderContext rc, SplitPane splitPane) {
373         String JavaDoc elementId = ContainerInstance.getElementId(splitPane);
374         ServerMessage serverMessage = rc.getServerMessage();
375         Element JavaDoc initElement = serverMessage.appendPartDirective(ServerMessage.GROUP_ID_PREREMOVE,
376                 "EchoSplitPane.MessageProcessor", "dispose");
377         initElement.setAttribute("eid", elementId);
378     }
379
380     private int getSeparatorPosition(SplitPane splitPane) {
381         Extent separatorPosition = (Extent) splitPane.getRenderProperty(SplitPane.PROPERTY_SEPARATOR_POSITION,
382                 DEFAULT_SEPARATOR_POSITION);
383         return ExtentRender.toPixels(separatorPosition, 100);
384     }
385     
386     /**
387      * Renders a directive to the outgoing <code>ServerMessage</code> to
388      * render a <code>SplitPane</code>.
389      *
390      * @param rc the relevant <code>RenderContext</code>
391      * @param splitPane the <code>SplitPane</code>
392      * @param targetId the id of the container element
393      */

394     private void renderInitDirective(RenderContext rc, SplitPane splitPane, String JavaDoc targetId) {
395         String JavaDoc elementId = ContainerInstance.getElementId(splitPane);
396         boolean vertical = isOrientationVertical(splitPane);
397         ServerMessage serverMessage = rc.getServerMessage();
398         Element JavaDoc partElement = serverMessage.addPart(ServerMessage.GROUP_ID_UPDATE, "EchoSplitPane.MessageProcessor");
399         Element JavaDoc initElement = serverMessage.getDocument().createElement("init");
400         initElement.setAttribute("container-eid", targetId);
401         initElement.setAttribute("eid", elementId);
402
403         initElement.setAttribute("position", Integer.toString(getSeparatorPosition(splitPane)));
404         
405         int orientation = getRenderOrientation(splitPane);
406         switch (orientation) {
407         case SplitPane.ORIENTATION_HORIZONTAL_LEFT_RIGHT:
408             initElement.setAttribute("orientation", "l-r");
409             break;
410         case SplitPane.ORIENTATION_HORIZONTAL_RIGHT_LEFT:
411             initElement.setAttribute("orientation", "r-l");
412             break;
413         case SplitPane.ORIENTATION_VERTICAL_TOP_BOTTOM:
414             initElement.setAttribute("orientation", "t-b");
415             break;
416         case SplitPane.ORIENTATION_VERTICAL_BOTTOM_TOP:
417             initElement.setAttribute("orientation", "b-t");
418             break;
419         default:
420             throw new IllegalStateException JavaDoc("Invalid orientation: " + orientation);
421         }
422         
423         if (!splitPane.isRenderEnabled()) {
424             initElement.setAttribute("enabled", "false");
425         }
426         Color background = (Color) splitPane.getRenderProperty(SplitPane.PROPERTY_BACKGROUND);
427         if (background != null) {
428             initElement.setAttribute("background", ColorRender.renderCssAttributeValue(background));
429         }
430         Color foreground = (Color) splitPane.getRenderProperty(SplitPane.PROPERTY_FOREGROUND);
431         if (foreground != null) {
432             initElement.setAttribute("foreground", ColorRender.renderCssAttributeValue(foreground));
433         }
434         Font font = (Font) splitPane.getRenderProperty(SplitPane.PROPERTY_FONT);
435         if (font != null) {
436             CssStyle fontCssStyle = new CssStyle();
437             FontRender.renderToStyle(fontCssStyle, font);
438             initElement.setAttribute("font", fontCssStyle.renderInline());
439         }
440
441         Boolean JavaDoc booleanValue = (Boolean JavaDoc) splitPane.getRenderProperty(SplitPane.PROPERTY_RESIZABLE);
442         boolean resizable = booleanValue == null ? false : booleanValue.booleanValue();
443         initElement.setAttribute("resizable", resizable ? "true" : "false");
444         
445         initElement.setAttribute("separator-size", Integer.toString(calculateSeparatorSize(splitPane)));
446         
447         Color separatorColor = (Color) splitPane.getRenderProperty(SplitPane.PROPERTY_SEPARATOR_COLOR);
448         if (separatorColor != null) {
449             initElement.setAttribute("separator-color", ColorRender.renderCssAttributeValue(separatorColor));
450         }
451         
452         FillImage separatorImage = vertical
453                 ? (FillImage) splitPane.getRenderProperty(SplitPane.PROPERTY_SEPARATOR_VERTICAL_IMAGE)
454                 : (FillImage) splitPane.getRenderProperty(SplitPane.PROPERTY_SEPARATOR_HORIZONTAL_IMAGE);
455         if (separatorImage != null) {
456             CssStyle fillImageCssStyle = new CssStyle();
457             FillImageRender.renderToStyle(fillImageCssStyle, rc, this, splitPane,
458                     vertical ? IMAGE_ID_VERTICAL_SEPARATOR : IMAGE_ID_HORIZONTAL_SEPARATOR, separatorImage, 0);
459             initElement.setAttribute("separator-image", fillImageCssStyle.renderInline());
460         }
461         
462         Component[] children = splitPane.getVisibleComponents();
463         for (int i = 0; i < children.length; ++i) {
464             renderLayoutData(rc, initElement, children[i], i);
465         }
466
467         partElement.appendChild(initElement);
468     }
469     
470     private void renderLayoutData(RenderContext rc, Element JavaDoc containerElement, Component component, int index) {
471         SplitPaneLayoutData layoutData = (SplitPaneLayoutData) component.getRenderProperty(SplitPane.PROPERTY_LAYOUT_DATA);
472         if (layoutData == null) {
473             return;
474         }
475         Element JavaDoc layoutDataElement = rc.getServerMessage().getDocument().createElement("layout-data");
476         layoutDataElement.setAttribute("index", Integer.toString(index));
477         if (layoutData.getAlignment() != null) {
478             CssStyle alignmentStyle = new CssStyle();
479             AlignmentRender.renderToStyle(alignmentStyle, layoutData.getAlignment(), component);
480             layoutDataElement.setAttribute("alignment", alignmentStyle.renderInline());
481         }
482         if (layoutData.getBackground() != null) {
483             layoutDataElement.setAttribute("background", ColorRender.renderCssAttributeValue(layoutData.getBackground()));
484         }
485         if (layoutData.getBackgroundImage() != null) {
486             CssStyle backgroundImageStyle = new CssStyle();
487             FillImageRender.renderToStyle(backgroundImageStyle, rc, this, component.getParent(),
488                     index == 0 ? IMAGE_ID_PANE_0_BACKGROUND : IMAGE_ID_PANE_1_BACKGROUND, layoutData.getBackgroundImage(), 0);
489             layoutDataElement.setAttribute("background-image", backgroundImageStyle.renderInline());
490         }
491         if (!(component instanceof Pane) && layoutData.getInsets() != null) {
492             layoutDataElement.setAttribute("insets", InsetsRender.renderCssAttributeValue(layoutData.getInsets()));
493         }
494         switch (layoutData.getOverflow()) {
495         case SplitPaneLayoutData.OVERFLOW_AUTO:
496             layoutDataElement.setAttribute("overflow", "auto");
497             break;
498         case SplitPaneLayoutData.OVERFLOW_HIDDEN:
499             layoutDataElement.setAttribute("overflow", "hidden");
500             break;
501         case SplitPaneLayoutData.OVERFLOW_SCROLL:
502             layoutDataElement.setAttribute("overflow", "scroll");
503             break;
504         }
505         if (layoutData.getMinimumSize() != null) {
506             layoutDataElement.setAttribute("min-size", Integer.toString(ExtentRender.toPixels(layoutData.getMinimumSize(), -1)));
507         }
508         if (layoutData.getMaximumSize() != null) {
509             layoutDataElement.setAttribute("max-size", Integer.toString(ExtentRender.toPixels(layoutData.getMaximumSize(), -1)));
510         }
511         
512         containerElement.appendChild(layoutDataElement);
513     }
514     
515     private void renderRemoveChildren(RenderContext rc, ServerComponentUpdate update) {
516         ContainerInstance ci = rc.getContainerInstance();
517         SplitPane splitPane = (SplitPane) update.getParent();
518         RenderStateImpl previousRenderState = (RenderStateImpl) ci.getRenderState(splitPane);
519         
520         RenderStateImpl currentRenderState = new RenderStateImpl(splitPane);
521
522         if (!equal(previousRenderState.pane0, currentRenderState.pane0)) {
523             if (previousRenderState.pane0 != null) {
524                 renderRemoveChildDirective(rc, (SplitPane) splitPane, 0);
525             }
526         }
527         if (!equal(previousRenderState.pane1, currentRenderState.pane1)) {
528             if (previousRenderState.pane1 != null) {
529                 renderRemoveChildDirective(rc, (SplitPane) splitPane, 1);
530             }
531         }
532     }
533     
534     private void renderRemoveChildDirective(RenderContext rc, SplitPane splitPane, int index) {
535         String JavaDoc elementId = ContainerInstance.getElementId(splitPane);
536         ServerMessage serverMessage = rc.getServerMessage();
537         Element JavaDoc partElement = serverMessage.addPart(ServerMessage.GROUP_ID_REMOVE, "EchoSplitPane.MessageProcessor");
538         Element JavaDoc removeChildElement = serverMessage.getDocument().createElement("remove-child");
539         removeChildElement.setAttribute("eid", elementId);
540         removeChildElement.setAttribute("index", Integer.toString(index));
541         partElement.appendChild(removeChildElement);
542     }
543
544     private void renderSetSeparatorPositionDirective(RenderContext rc, SplitPane splitPane) {
545         String JavaDoc elementId = ContainerInstance.getElementId(splitPane);
546         ServerMessage serverMessage = rc.getServerMessage();
547         Element JavaDoc partElement = serverMessage.addPart(ServerMessage.GROUP_ID_REMOVE, "EchoSplitPane.MessageProcessor");
548         Element JavaDoc setSeparatorPositionElement = serverMessage.getDocument().createElement("set-separator-position");
549         setSeparatorPositionElement.setAttribute("eid", elementId);
550         setSeparatorPositionElement.setAttribute("position", Integer.toString(getSeparatorPosition(splitPane)));
551         partElement.appendChild(setSeparatorPositionElement);
552     }
553
554     /**
555      * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#renderUpdate(nextapp.echo2.webcontainer.RenderContext,
556      * nextapp.echo2.app.update.ServerComponentUpdate, java.lang.String)
557      */

558     public boolean renderUpdate(RenderContext rc, ServerComponentUpdate update, String JavaDoc targetId) {
559         boolean fullReplace = false;
560         if (update.hasUpdatedLayoutDataChildren()) {
561             fullReplace = true;
562         } else if (update.hasUpdatedProperties()) {
563             if (!partialUpdateManager.canProcess(rc, update)) {
564                 fullReplace = true;
565             }
566         }
567         
568         if (fullReplace) {
569             // Perform full update.
570
renderDisposeDirective(rc, (SplitPane) update.getParent());
571             DomUpdate.renderElementRemove(rc.getServerMessage(), ContainerInstance.getElementId(update.getParent()));
572             renderAdd(rc, update, targetId, update.getParent());
573         } else {
574             partialUpdateManager.process(rc, update);
575             if (update.hasAddedChildren() || update.hasRemovedChildren()) {
576                 renderRemoveChildren(rc, update);
577                 renderAddChildren(rc, update);
578             }
579         }
580         
581         updateRenderState(rc, (SplitPane) update.getParent());
582         return fullReplace;
583     }
584     
585     /**
586      * Update the stored <code>RenderState</code>.
587      *
588      * @param rc the relevant <code>RenderContext</code>
589      * @param splitPane the <code>SplitPane</code> component
590      */

591     private void updateRenderState(RenderContext rc, SplitPane splitPane) {
592         rc.getContainerInstance().setRenderState(splitPane, new RenderStateImpl(splitPane));
593     }
594 }
595
Popular Tags