KickJava   Java API By Example, From Geeks To Geeks.

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


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 org.w3c.dom.DocumentFragment JavaDoc;
33 import org.w3c.dom.Element JavaDoc;
34
35 import nextapp.echo2.app.Alignment;
36 import nextapp.echo2.app.FillImage;
37 import nextapp.echo2.app.Border;
38 import nextapp.echo2.app.Color;
39 import nextapp.echo2.app.Component;
40 import nextapp.echo2.app.Extent;
41 import nextapp.echo2.app.Font;
42 import nextapp.echo2.app.ImageReference;
43 import nextapp.echo2.app.Insets;
44 import nextapp.echo2.app.TextArea;
45 import nextapp.echo2.app.text.TextComponent;
46 import nextapp.echo2.app.update.ServerComponentUpdate;
47 import nextapp.echo2.webcontainer.ActionProcessor;
48 import nextapp.echo2.webcontainer.ContainerInstance;
49 import nextapp.echo2.webcontainer.DomUpdateSupport;
50 import nextapp.echo2.webcontainer.FocusSupport;
51 import nextapp.echo2.webcontainer.PartialUpdateManager;
52 import nextapp.echo2.webcontainer.PartialUpdateParticipant;
53 import nextapp.echo2.webcontainer.PropertyUpdateProcessor;
54 import nextapp.echo2.webcontainer.RenderContext;
55 import nextapp.echo2.webcontainer.ComponentSynchronizePeer;
56 import nextapp.echo2.webcontainer.image.ImageRenderSupport;
57 import nextapp.echo2.webcontainer.partialupdate.BorderUpdate;
58 import nextapp.echo2.webcontainer.partialupdate.ColorUpdate;
59 import nextapp.echo2.webcontainer.partialupdate.InsetsUpdate;
60 import nextapp.echo2.webcontainer.propertyrender.AlignmentRender;
61 import nextapp.echo2.webcontainer.propertyrender.FillImageRender;
62 import nextapp.echo2.webcontainer.propertyrender.BorderRender;
63 import nextapp.echo2.webcontainer.propertyrender.ColorRender;
64 import nextapp.echo2.webcontainer.propertyrender.ExtentRender;
65 import nextapp.echo2.webcontainer.propertyrender.FontRender;
66 import nextapp.echo2.webcontainer.propertyrender.InsetsRender;
67 import nextapp.echo2.webcontainer.propertyrender.LayoutDirectionRender;
68 import nextapp.echo2.webrender.ClientProperties;
69 import nextapp.echo2.webrender.ServerMessage;
70 import nextapp.echo2.webrender.Service;
71 import nextapp.echo2.webrender.WebRenderServlet;
72 import nextapp.echo2.webrender.output.CssStyle;
73 import nextapp.echo2.webrender.servermessage.DomUpdate;
74 import nextapp.echo2.webrender.servermessage.WindowUpdate;
75 import nextapp.echo2.webrender.service.JavaScriptService;
76 import nextapp.echo2.webrender.util.DomUtil;
77
78 /**
79  * Abstract base synchronization peer for the built-in
80  * <code>nextapp.echo2.app.text.TextComponent</code> -derived components.
81  * <p>
82  * This class should not be extended or used by classes outside of the Echo
83  * framework.
84  */

85 public abstract class TextComponentPeer
86 implements ActionProcessor, ComponentSynchronizePeer, DomUpdateSupport, FocusSupport, ImageRenderSupport, PropertyUpdateProcessor {
87
88     private static final String JavaDoc IMAGE_ID_BACKGROUND = "background";
89
90     /**
91      * Service to provide supporting JavaScript library.
92      */

93     static final Service TEXT_COMPONENT_SERVICE = JavaScriptService.forResource("Echo.TextComponent",
94             "/nextapp/echo2/webcontainer/resource/js/TextComponent.js");
95
96     static {
97         WebRenderServlet.getServiceRegistry().add(TEXT_COMPONENT_SERVICE);
98     }
99     
100     /**
101      * A <code>PartialUpdateParticipant</code> to update the text of
102      * a text component.
103      */

104     private class TextUpdate
105     implements PartialUpdateParticipant {
106     
107         /**
108          * @see nextapp.echo2.webcontainer.PartialUpdateParticipant#canRenderProperty(nextapp.echo2.webcontainer.RenderContext,
109          * nextapp.echo2.app.update.ServerComponentUpdate)
110          */

111         public boolean canRenderProperty(RenderContext rc, ServerComponentUpdate update) {
112             return true;
113         }
114     
115         /**
116          * @see nextapp.echo2.webcontainer.PartialUpdateParticipant#renderProperty(
117          * nextapp.echo2.webcontainer.RenderContext, nextapp.echo2.app.update.ServerComponentUpdate)
118          */

119         public void renderProperty(RenderContext rc, ServerComponentUpdate update) {
120             TextComponent textComponent = (TextComponent) update.getParent();
121             String JavaDoc elementId = ContainerInstance.getElementId(textComponent);
122             ServerMessage serverMessage = rc.getServerMessage();
123             Element JavaDoc itemizedUpdateElement = serverMessage.getItemizedDirective(ServerMessage.GROUP_ID_POSTUPDATE,
124                     "EchoTextComponent.MessageProcessor", "set-text", new String JavaDoc[0], new String JavaDoc[0]);
125             Element JavaDoc itemElement = serverMessage.getDocument().createElement("item");
126             itemElement.setAttribute("eid", elementId);
127             itemElement.setAttribute("text", textComponent.getText());
128             itemizedUpdateElement.appendChild(itemElement);
129             
130         }
131     }
132
133     private PartialUpdateManager partialUpdateManager;
134
135     /**
136      * Default constructor.
137      */

138     public TextComponentPeer() {
139         partialUpdateManager = new PartialUpdateManager();
140         partialUpdateManager.add(TextComponent.PROPERTY_FOREGROUND,
141                 new ColorUpdate(TextComponent.PROPERTY_FOREGROUND, null, ColorUpdate.CSS_COLOR));
142         partialUpdateManager.add(TextComponent.PROPERTY_BACKGROUND,
143                 new ColorUpdate(TextComponent.PROPERTY_BACKGROUND, null, ColorUpdate.CSS_BACKGROUND_COLOR));
144         partialUpdateManager.add(TextComponent.PROPERTY_BORDER,
145                 new BorderUpdate(TextComponent.PROPERTY_BORDER, null, BorderUpdate.CSS_BORDER));
146         partialUpdateManager.add(TextComponent.PROPERTY_INSETS,
147                 new InsetsUpdate(TextComponent.PROPERTY_INSETS, null, InsetsUpdate.CSS_PADDING));
148         partialUpdateManager.add(TextComponent.TEXT_CHANGED_PROPERTY, new TextUpdate());
149     }
150
151     /**
152      * Creates a base <code>CssStyle</code> for properties common to text
153      * components.
154      *
155      * @param rc the relevant <code>RenderContext</code>
156      * @param textComponent the text component
157      * @return the style
158      */

159     protected CssStyle createBaseCssStyle(RenderContext rc, TextComponent textComponent) {
160         CssStyle cssStyle = new CssStyle();
161
162         boolean renderEnabled = textComponent.isRenderEnabled();
163
164         Border border;
165         Color foreground, background;
166         Font font;
167         FillImage backgroundImage;
168         if (!renderEnabled) {
169             // Retrieve disabled style information.
170
background = (Color) textComponent.getRenderProperty(TextComponent.PROPERTY_DISABLED_BACKGROUND);
171             backgroundImage = (FillImage) textComponent.getRenderProperty(TextComponent.PROPERTY_DISABLED_BACKGROUND_IMAGE);
172             border = (Border) textComponent.getRenderProperty(TextComponent.PROPERTY_DISABLED_BORDER);
173             font = (Font) textComponent.getRenderProperty(TextComponent.PROPERTY_DISABLED_FONT);
174             foreground = (Color) textComponent.getRenderProperty(TextComponent.PROPERTY_DISABLED_FOREGROUND);
175
176             // Fallback to normal styles.
177
if (background == null) {
178                 background = (Color) textComponent.getRenderProperty(TextComponent.PROPERTY_BACKGROUND);
179                 if (backgroundImage == null) {
180                     // Special case:
181
// Disabled background without disabled background image will render disabled background instead of
182
// normal background image.
183
backgroundImage = (FillImage) textComponent.getRenderProperty(TextComponent.PROPERTY_BACKGROUND_IMAGE);
184                 }
185             }
186             if (border == null) {
187                 border = (Border) textComponent.getRenderProperty(TextComponent.PROPERTY_BORDER);
188             }
189             if (font == null) {
190                 font = (Font) textComponent.getRenderProperty(TextComponent.PROPERTY_FONT);
191             }
192             if (foreground == null) {
193                 foreground = (Color) textComponent.getRenderProperty(TextComponent.PROPERTY_FOREGROUND);
194             }
195         } else {
196             border = (Border) textComponent.getRenderProperty(TextComponent.PROPERTY_BORDER);
197             foreground = (Color) textComponent.getRenderProperty(TextComponent.PROPERTY_FOREGROUND);
198             background = (Color) textComponent.getRenderProperty(TextComponent.PROPERTY_BACKGROUND);
199             font = (Font) textComponent.getRenderProperty(TextComponent.PROPERTY_FONT);
200             backgroundImage = (FillImage) textComponent.getRenderProperty(TextComponent.PROPERTY_BACKGROUND_IMAGE);
201         }
202         
203         Alignment alignment = (Alignment) textComponent.getRenderProperty(TextComponent.PROPERTY_ALIGNMENT);
204         if (alignment != null) {
205             int horizontalAlignment = AlignmentRender.getRenderedHorizontal(alignment, textComponent);
206             switch (horizontalAlignment) {
207             case Alignment.LEFT:
208                 cssStyle.setAttribute("text-align", "left");
209                 break;
210             case Alignment.CENTER:
211                 cssStyle.setAttribute("text-align", "center");
212                 break;
213             case Alignment.RIGHT:
214                 cssStyle.setAttribute("text-align", "right");
215                 break;
216             }
217         }
218         
219         LayoutDirectionRender.renderToStyle(cssStyle, textComponent.getLayoutDirection(), textComponent.getLocale());
220         BorderRender.renderToStyle(cssStyle, border);
221         ColorRender.renderToStyle(cssStyle, foreground, background);
222         FontRender.renderToStyle(cssStyle, font);
223         FillImageRender.renderToStyle(cssStyle, rc, this, textComponent, IMAGE_ID_BACKGROUND, backgroundImage,
224                 FillImageRender.FLAG_DISABLE_FIXED_MODE);
225         
226         InsetsRender.renderToStyle(cssStyle, "padding", (Insets) textComponent.getRenderProperty(TextComponent.PROPERTY_INSETS));
227         
228         Extent width = (Extent) textComponent.getRenderProperty(TextComponent.PROPERTY_WIDTH);
229         Extent height = (Extent) textComponent.getRenderProperty(TextComponent.PROPERTY_HEIGHT);
230
231         if (width != null) {
232             cssStyle.setAttribute("width", ExtentRender.renderCssAttributeValue(width));
233         }
234
235         if (height != null) {
236             cssStyle.setAttribute("height", ExtentRender.renderCssAttributeValue(height));
237         }
238         return cssStyle;
239     }
240
241     /**
242      * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#getContainerId(nextapp.echo2.app.Component)
243      */

244     public String JavaDoc getContainerId(Component child) {
245         throw new UnsupportedOperationException JavaDoc("Component does not support children.");
246     }
247
248     /**
249      * @see nextapp.echo2.webcontainer.image.ImageRenderSupport#getImage(nextapp.echo2.app.Component,
250      * java.lang.String)
251      */

252     public ImageReference getImage(Component component, String JavaDoc imageId) {
253         if (IMAGE_ID_BACKGROUND.equals(imageId)) {
254             FillImage backgroundImage;
255             if (component.isRenderEnabled()) {
256                 backgroundImage = (FillImage) component.getRenderProperty(TextComponent.PROPERTY_BACKGROUND_IMAGE);
257             } else {
258                 backgroundImage = (FillImage) component.getRenderProperty(TextComponent.PROPERTY_DISABLED_BACKGROUND_IMAGE);
259                 if (backgroundImage == null) {
260                     backgroundImage = (FillImage) component.getRenderProperty(TextComponent.PROPERTY_BACKGROUND_IMAGE);
261                 }
262             }
263             if (backgroundImage == null) {
264                 return null;
265             } else {
266                 return backgroundImage.getImage();
267             }
268         } else {
269             return null;
270         }
271     }
272
273     /**
274      * @see nextapp.echo2.webcontainer.ActionProcessor#processAction(nextapp.echo2.webcontainer.ContainerInstance,
275      * nextapp.echo2.app.Component, org.w3c.dom.Element)
276      */

277     public void processAction(ContainerInstance ci, Component component, Element JavaDoc actionElement) {
278         ci.getUpdateManager().getClientUpdateManager().setComponentAction(component, TextComponent.INPUT_ACTION, null);
279     }
280
281     /**
282      * @see nextapp.echo2.webcontainer.PropertyUpdateProcessor#processPropertyUpdate(
283      * nextapp.echo2.webcontainer.ContainerInstance,
284      * nextapp.echo2.app.Component, org.w3c.dom.Element)
285      */

286     public void processPropertyUpdate(ContainerInstance ci, Component component, Element JavaDoc propertyElement) {
287         String JavaDoc propertyName = propertyElement.getAttribute(PropertyUpdateProcessor.PROPERTY_NAME);
288         if (TextComponent.TEXT_CHANGED_PROPERTY.equals(propertyName)) {
289             String JavaDoc propertyValue = DomUtil.getElementText(propertyElement);
290             ci.getUpdateManager().getClientUpdateManager().setComponentProperty(component,
291                     TextComponent.TEXT_CHANGED_PROPERTY, propertyValue);
292         } else if (TextComponent.PROPERTY_HORIZONTAL_SCROLL.equals(propertyName)) {
293             Extent propertyValue = new Extent(Integer.parseInt(
294                     propertyElement.getAttribute(PropertyUpdateProcessor.PROPERTY_VALUE)));
295             ci.getUpdateManager().getClientUpdateManager().setComponentProperty(component,
296                     TextComponent.PROPERTY_HORIZONTAL_SCROLL, propertyValue);
297         } else if (TextComponent.PROPERTY_VERTICAL_SCROLL.equals(propertyName)) {
298             Extent propertyValue = new Extent(Integer.parseInt(
299                     propertyElement.getAttribute(PropertyUpdateProcessor.PROPERTY_VALUE)));
300             ci.getUpdateManager().getClientUpdateManager().setComponentProperty(component,
301                     TextComponent.PROPERTY_VERTICAL_SCROLL, propertyValue);
302         }
303     }
304
305     /**
306      * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#renderAdd(nextapp.echo2.webcontainer.RenderContext,
307      * nextapp.echo2.app.update.ServerComponentUpdate, java.lang.String,
308      * nextapp.echo2.app.Component)
309      */

310     public void renderAdd(RenderContext rc, ServerComponentUpdate update, String JavaDoc targetId, Component component) {
311         Element JavaDoc domAddElement = DomUpdate.renderElementAdd(rc.getServerMessage());
312         DocumentFragment JavaDoc htmlFragment = rc.getServerMessage().getDocument().createDocumentFragment();
313         renderHtml(rc, update, htmlFragment, component);
314         DomUpdate.renderElementAddContent(rc.getServerMessage(), domAddElement, targetId, htmlFragment);
315     }
316
317     /**
318      * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#renderDispose(nextapp.echo2.webcontainer.RenderContext,
319      * nextapp.echo2.app.update.ServerComponentUpdate,
320      * nextapp.echo2.app.Component)
321      */

322     public void renderDispose(RenderContext rc, ServerComponentUpdate update, Component component) {
323         rc.getServerMessage().addLibrary(TEXT_COMPONENT_SERVICE.getId());
324         renderDisposeDirective(rc, (TextComponent) component);
325     }
326
327     /**
328      * Renders a directive to the outgoing <code>ServerMessage</code> to
329      * dispose the state of a text component, performing tasks such as
330      * registering event listeners on the client.
331      *
332      * @param rc the relevant <code>RenderContext</code>
333      * @param textComponent the <code>TextComponent<code>
334      */

335     public void renderDisposeDirective(RenderContext rc, TextComponent textComponent) {
336         String JavaDoc elementId = ContainerInstance.getElementId(textComponent);
337         ServerMessage serverMessage = rc.getServerMessage();
338         Element JavaDoc itemizedUpdateElement = serverMessage.getItemizedDirective(ServerMessage.GROUP_ID_PREREMOVE,
339                 "EchoTextComponent.MessageProcessor", "dispose", new String JavaDoc[0], new String JavaDoc[0]);
340         Element JavaDoc itemElement = serverMessage.getDocument().createElement("item");
341         itemElement.setAttribute("eid", elementId);
342         itemizedUpdateElement.appendChild(itemElement);
343     }
344
345     /**
346      * Renders a directive to the outgoing <code>ServerMessage</code> to
347      * initialize the state of a text component, performing tasks such as
348      * registering event listeners on the client.
349      *
350      * @param rc the relevant <code>RenderContext</code>
351      * @param textComponent the <code>TextComponent<code>
352      */

353     public void renderInitDirective(RenderContext rc, TextComponent textComponent) {
354         Extent horizontalScroll = (Extent) textComponent.getRenderProperty(TextComponent.PROPERTY_HORIZONTAL_SCROLL);
355         Extent verticalScroll = (Extent) textComponent.getRenderProperty(TextComponent.PROPERTY_VERTICAL_SCROLL);
356         String JavaDoc elementId = ContainerInstance.getElementId(textComponent);
357         ServerMessage serverMessage = rc.getServerMessage();
358
359         Element JavaDoc itemizedUpdateElement = serverMessage.getItemizedDirective(ServerMessage.GROUP_ID_POSTUPDATE,
360                 "EchoTextComponent.MessageProcessor", "init", new String JavaDoc[0], new String JavaDoc[0]);
361         Element JavaDoc itemElement = serverMessage.getDocument().createElement("item");
362         itemElement.setAttribute("eid", elementId);
363         if (horizontalScroll != null && horizontalScroll.getValue() != 0) {
364             itemElement.setAttribute("horizontal-scroll", ExtentRender.renderCssAttributePixelValue(horizontalScroll, "0"));
365         }
366         if (verticalScroll != null && verticalScroll.getValue() != 0) {
367             itemElement.setAttribute("vertical-scroll", ExtentRender.renderCssAttributePixelValue(verticalScroll, "0"));
368         }
369         if (textComponent instanceof TextArea) {
370             Integer JavaDoc maximumLength = (Integer JavaDoc) textComponent.getProperty(TextComponent.PROPERTY_MAXIMUM_LENGTH);
371             if (maximumLength != null) {
372                 itemElement.setAttribute("maximum-length", maximumLength.toString());
373             }
374         }
375         if (textComponent instanceof TextArea && rc.getContainerInstance().getClientProperties().getBoolean(
376                 ClientProperties.QUIRK_TEXTAREA_CONTENT)) {
377             String JavaDoc value = textComponent.getText();
378             if (value != null) {
379                 itemElement.setAttribute("text", value);
380             }
381         }
382         if (!textComponent.isRenderEnabled()) {
383             itemElement.setAttribute("enabled", "false");
384         }
385         if (textComponent.hasActionListeners()) {
386             itemElement.setAttribute("server-notify", "true");
387         }
388
389         itemizedUpdateElement.appendChild(itemElement);
390     }
391
392     /**
393      * @see nextapp.echo2.webcontainer.FocusSupport#renderSetFocus(nextapp.echo2.webcontainer.RenderContext,
394      * nextapp.echo2.app.Component)
395      */

396     public void renderSetFocus(RenderContext rc, Component component) {
397         WindowUpdate.renderSetFocus(rc.getServerMessage(), ContainerInstance.getElementId(component));
398     }
399
400     /**
401      * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#renderUpdate(nextapp.echo2.webcontainer.RenderContext,
402      * nextapp.echo2.app.update.ServerComponentUpdate, java.lang.String)
403      */

404     public boolean renderUpdate(RenderContext rc, ServerComponentUpdate update, String JavaDoc targetId) {
405         boolean fullReplace = false;
406         if (update.hasUpdatedProperties()) {
407             if (!partialUpdateManager.canProcess(rc, update)) {
408                 fullReplace = true;
409             }
410         }
411
412         if (fullReplace) {
413             // Perform full update.
414
DomUpdate.renderElementRemove(rc.getServerMessage(), ContainerInstance.getElementId(update.getParent()));
415             renderAdd(rc, update, targetId, update.getParent());
416         } else {
417             partialUpdateManager.process(rc, update);
418         }
419
420         return false;
421     }
422 }
Popular Tags