001: /*
002: * This file is part of the Echo Web Application Framework (hereinafter "Echo").
003: * Copyright (C) 2002-2005 NextApp, Inc.
004: *
005: * Version: MPL 1.1/GPL 2.0/LGPL 2.1
006: *
007: * The contents of this file are subject to the Mozilla Public License Version
008: * 1.1 (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: * http://www.mozilla.org/MPL/
011: *
012: * Software distributed under the License is distributed on an "AS IS" basis,
013: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
014: * for the specific language governing rights and limitations under the
015: * License.
016: *
017: * Alternatively, the contents of this file may be used under the terms of
018: * either the GNU General Public License Version 2 or later (the "GPL"), or
019: * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
020: * in which case the provisions of the GPL or the LGPL are applicable instead
021: * of those above. If you wish to allow use of your version of this file only
022: * under the terms of either the GPL or the LGPL, and not to allow others to
023: * use your version of this file under the terms of the MPL, indicate your
024: * decision by deleting the provisions above and replace them with the notice
025: * and other provisions required by the GPL or the LGPL. If you do not delete
026: * the provisions above, a recipient may use your version of this file under
027: * the terms of any one of the MPL, the GPL or the LGPL.
028: */
029:
030: package nextapp.echo2.webcontainer.syncpeer;
031:
032: import java.io.IOException;
033:
034: import org.w3c.dom.Element;
035:
036: import nextapp.echo2.app.Color;
037: import nextapp.echo2.app.Component;
038: import nextapp.echo2.app.Extent;
039: import nextapp.echo2.app.FillImage;
040: import nextapp.echo2.app.FillImageBorder;
041: import nextapp.echo2.app.Font;
042: import nextapp.echo2.app.ImageReference;
043: import nextapp.echo2.app.Insets;
044: import nextapp.echo2.app.ResourceImageReference;
045: import nextapp.echo2.app.WindowPane;
046: import nextapp.echo2.app.update.PropertyUpdate;
047: import nextapp.echo2.app.update.ServerComponentUpdate;
048: import nextapp.echo2.webcontainer.ActionProcessor;
049: import nextapp.echo2.webcontainer.ComponentSynchronizePeer;
050: import nextapp.echo2.webcontainer.ContainerInstance;
051: import nextapp.echo2.webcontainer.PartialUpdateManager;
052: import nextapp.echo2.webcontainer.PartialUpdateParticipant;
053: import nextapp.echo2.webcontainer.PropertyUpdateProcessor;
054: import nextapp.echo2.webcontainer.RenderContext;
055: import nextapp.echo2.webcontainer.SynchronizePeerFactory;
056: import nextapp.echo2.webcontainer.image.ImageRenderSupport;
057: import nextapp.echo2.webcontainer.image.ImageTools;
058: import nextapp.echo2.webcontainer.propertyrender.ColorRender;
059: import nextapp.echo2.webcontainer.propertyrender.ExtentRender;
060: import nextapp.echo2.webcontainer.propertyrender.FillImageRender;
061: import nextapp.echo2.webcontainer.propertyrender.FontRender;
062: import nextapp.echo2.webcontainer.propertyrender.InsetsRender;
063: import nextapp.echo2.webrender.Connection;
064: import nextapp.echo2.webrender.ContentType;
065: import nextapp.echo2.webrender.ServerMessage;
066: import nextapp.echo2.webrender.Service;
067: import nextapp.echo2.webrender.WebRenderServlet;
068: import nextapp.echo2.webrender.output.CssStyle;
069: import nextapp.echo2.webrender.servermessage.DomUpdate;
070: import nextapp.echo2.webrender.service.JavaScriptService;
071:
072: /**
073: * Synchronization peer for <code>nextapp.echo2.app.WindowPane</code>
074: * components.
075: * <p>
076: * This class should not be extended or used by classes outside of the Echo
077: * framework.
078: */
079: public class WindowPanePeer implements ActionProcessor,
080: ImageRenderSupport, PropertyUpdateProcessor,
081: ComponentSynchronizePeer {
082:
083: /**
084: * A boolean property which may be assigned to <code>WindowPane</code>s
085: * in order to enable the proprietary Internet Explorer transparent PNG
086: * alpha renderer for rendering the <code>border</code> property of the
087: * window pane.
088: */
089: public static final String PROPERTY_IE_ALPHA_RENDER_BORDER = "nextapp.echo2.webcontainer.syncpeer.WindowPanePeer.ieAlphaRenderBorder";
090:
091: private static final String IMAGE_ID_TITLE_BACKGROUND = "titleBackground";
092: private static final String IMAGE_ID_CLOSE_ICON = "close";
093: private static final String IMAGE_ID_ICON = "icon";
094: private static final String IMAGE_ID_BACKGROUND = "background";
095: private static final String IMAGE_ID_BORDER_TOP_LEFT = "borderTopLeft";
096: private static final String IMAGE_ID_BORDER_TOP = "borderTop";
097: private static final String IMAGE_ID_BORDER_TOP_RIGHT = "borderTopRight";
098: private static final String IMAGE_ID_BORDER_LEFT = "borderLeft";
099: private static final String IMAGE_ID_BORDER_RIGHT = "borderRight";
100: private static final String IMAGE_ID_BORDER_BOTTOM_LEFT = "borderBottomLeft";
101: private static final String IMAGE_ID_BORDER_BOTTOM = "borderBottom";
102: private static final String IMAGE_ID_BORDER_BOTTOM_RIGHT = "borderBottomRight";
103:
104: private static final ImageReference DEFAULT_CLOSE_ICON = new ResourceImageReference(
105: "/nextapp/echo2/webcontainer/resource/image/DefaultCloseButton.gif");
106:
107: private static final String[] FILL_IMAGE_NAMES = { "tl", "t", "tr",
108: "l", "r", "bl", "b", "br" };
109: private static final String[] FILL_IMAGE_IDS = {
110: IMAGE_ID_BORDER_TOP_LEFT, IMAGE_ID_BORDER_TOP,
111: IMAGE_ID_BORDER_TOP_RIGHT, IMAGE_ID_BORDER_LEFT,
112: IMAGE_ID_BORDER_RIGHT, IMAGE_ID_BORDER_BOTTOM_LEFT,
113: IMAGE_ID_BORDER_BOTTOM, IMAGE_ID_BORDER_BOTTOM_RIGHT };
114:
115: private static final String BLANK_HTML_STRING = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" "
116: + "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
117: + "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head><title></title><body></body></html>";
118:
119: private static final Service BLANK_HTML_SERVICE = new Service() {
120:
121: /**
122: * @see nextapp.echo2.webrender.Service#getId()
123: */
124: public String getId() {
125: return "Echo.WindowPane.IFrame";
126: }
127:
128: /**
129: * @see nextapp.echo2.webrender.Service#getVersion()
130: */
131: public int getVersion() {
132: return 0;
133: }
134:
135: /**
136: * @see nextapp.echo2.webrender.Service#service(nextapp.echo2.webrender.Connection)
137: */
138: public void service(Connection conn) throws IOException {
139: conn.setContentType(ContentType.TEXT_HTML);
140: conn.getWriter().write(BLANK_HTML_STRING);
141: }
142: };
143:
144: /**
145: * Service to provide supporting JavaScript library.
146: */
147: public static final Service WINDOW_PANE_SERVICE = JavaScriptService
148: .forResource("Echo.WindowPane",
149: "/nextapp/echo2/webcontainer/resource/js/WindowPane.js");
150:
151: static {
152: WebRenderServlet.getServiceRegistry().add(WINDOW_PANE_SERVICE);
153: WebRenderServlet.getServiceRegistry().add(BLANK_HTML_SERVICE);
154: }
155:
156: private static void renderPixelProperty(WindowPane windowPane,
157: String propertyName, Element element, String attributeName) {
158: String pixelValue;
159: Extent extent = (Extent) windowPane
160: .getRenderProperty(propertyName);
161: if (extent != null) {
162: pixelValue = ExtentRender
163: .renderCssAttributePixelValue(extent);
164: if (pixelValue != null) {
165: element.setAttribute(attributeName, pixelValue);
166: }
167: }
168: }
169:
170: private PartialUpdateParticipant placeHolder = new PartialUpdateParticipant() {
171:
172: public boolean canRenderProperty(RenderContext rc,
173: ServerComponentUpdate update) {
174: return true;
175: }
176:
177: public void renderProperty(RenderContext rc,
178: ServerComponentUpdate update) {
179: // Do nothing.
180: }
181: };
182:
183: private PartialUpdateManager partialUpdateManager;
184:
185: /**
186: * Default constructor.
187: */
188: public WindowPanePeer() {
189: super ();
190: partialUpdateManager = new PartialUpdateManager();
191: partialUpdateManager.add(WindowPane.PROPERTY_POSITION_X,
192: placeHolder);
193: partialUpdateManager.add(WindowPane.PROPERTY_POSITION_Y,
194: placeHolder);
195: partialUpdateManager
196: .add(WindowPane.PROPERTY_WIDTH, placeHolder);
197: partialUpdateManager.add(WindowPane.PROPERTY_HEIGHT,
198: placeHolder);
199: partialUpdateManager
200: .add(WindowPane.PROPERTY_TITLE, placeHolder);
201: }
202:
203: /**
204: * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#getContainerId(nextapp.echo2.app.Component)
205: */
206: public String getContainerId(Component child) {
207: return ContainerInstance.getElementId(child.getParent())
208: + "_content";
209: }
210:
211: /**
212: * @see nextapp.echo2.webcontainer.image.ImageRenderSupport#getImage(nextapp.echo2.app.Component,
213: * java.lang.String)
214: */
215: public ImageReference getImage(Component component, String imageId) {
216: if (IMAGE_ID_TITLE_BACKGROUND.equals(imageId)) {
217: FillImage backgroundImage = (FillImage) component
218: .getRenderProperty(WindowPane.PROPERTY_TITLE_BACKGROUND_IMAGE);
219: return backgroundImage == null ? null : backgroundImage
220: .getImage();
221: } else if (IMAGE_ID_BACKGROUND.equals(imageId)) {
222: FillImage backgroundImage = (FillImage) component
223: .getRenderProperty(WindowPane.PROPERTY_BACKGROUND_IMAGE);
224: return backgroundImage == null ? null : backgroundImage
225: .getImage();
226: } else if (IMAGE_ID_ICON.equals(imageId)) {
227: return (ImageReference) component
228: .getRenderProperty(WindowPane.PROPERTY_ICON);
229: } else if (IMAGE_ID_CLOSE_ICON.equals(imageId)) {
230: return (ImageReference) component.getRenderProperty(
231: WindowPane.PROPERTY_CLOSE_ICON, DEFAULT_CLOSE_ICON);
232: } else if (IMAGE_ID_BORDER_TOP_LEFT.equals(imageId)) {
233: FillImageBorder fillImageBorder = ((FillImageBorder) component
234: .getRenderProperty(WindowPane.PROPERTY_BORDER));
235: FillImage fillImage = fillImageBorder == null ? null
236: : fillImageBorder
237: .getFillImage(FillImageBorder.TOP_LEFT);
238: return fillImage == null ? null : fillImage.getImage();
239: } else if (IMAGE_ID_BORDER_TOP.equals(imageId)) {
240: FillImageBorder fillImageBorder = ((FillImageBorder) component
241: .getRenderProperty(WindowPane.PROPERTY_BORDER));
242: FillImage fillImage = fillImageBorder == null ? null
243: : fillImageBorder.getFillImage(FillImageBorder.TOP);
244: return fillImage == null ? null : fillImage.getImage();
245: } else if (IMAGE_ID_BORDER_TOP_RIGHT.equals(imageId)) {
246: FillImageBorder fillImageBorder = ((FillImageBorder) component
247: .getRenderProperty(WindowPane.PROPERTY_BORDER));
248: FillImage fillImage = fillImageBorder == null ? null
249: : fillImageBorder
250: .getFillImage(FillImageBorder.TOP_RIGHT);
251: return fillImage == null ? null : fillImage.getImage();
252: } else if (IMAGE_ID_BORDER_LEFT.equals(imageId)) {
253: FillImageBorder fillImageBorder = ((FillImageBorder) component
254: .getRenderProperty(WindowPane.PROPERTY_BORDER));
255: FillImage fillImage = fillImageBorder == null ? null
256: : fillImageBorder
257: .getFillImage(FillImageBorder.LEFT);
258: return fillImage == null ? null : fillImage.getImage();
259: } else if (IMAGE_ID_BORDER_RIGHT.equals(imageId)) {
260: FillImageBorder fillImageBorder = ((FillImageBorder) component
261: .getRenderProperty(WindowPane.PROPERTY_BORDER));
262: FillImage fillImage = fillImageBorder == null ? null
263: : fillImageBorder
264: .getFillImage(FillImageBorder.RIGHT);
265: return fillImage == null ? null : fillImage.getImage();
266: } else if (IMAGE_ID_BORDER_BOTTOM_LEFT.equals(imageId)) {
267: FillImageBorder fillImageBorder = ((FillImageBorder) component
268: .getRenderProperty(WindowPane.PROPERTY_BORDER));
269: FillImage fillImage = fillImageBorder == null ? null
270: : fillImageBorder
271: .getFillImage(FillImageBorder.BOTTOM_LEFT);
272: return fillImage == null ? null : fillImage.getImage();
273: } else if (IMAGE_ID_BORDER_BOTTOM.equals(imageId)) {
274: FillImageBorder fillImageBorder = ((FillImageBorder) component
275: .getRenderProperty(WindowPane.PROPERTY_BORDER));
276: FillImage fillImage = fillImageBorder == null ? null
277: : fillImageBorder
278: .getFillImage(FillImageBorder.BOTTOM);
279: return fillImage == null ? null : fillImage.getImage();
280: } else if (IMAGE_ID_BORDER_BOTTOM_RIGHT.equals(imageId)) {
281: FillImageBorder fillImageBorder = ((FillImageBorder) component
282: .getRenderProperty(WindowPane.PROPERTY_BORDER));
283: FillImage fillImage = fillImageBorder == null ? null
284: : fillImageBorder
285: .getFillImage(FillImageBorder.BOTTOM_RIGHT);
286: return fillImage == null ? null : fillImage.getImage();
287: } else {
288: return null;
289: }
290: }
291:
292: /**
293: * @see nextapp.echo2.webcontainer.ActionProcessor#processAction(nextapp.echo2.webcontainer.ContainerInstance,
294: * nextapp.echo2.app.Component, org.w3c.dom.Element)
295: */
296: public void processAction(ContainerInstance ci,
297: Component component, Element actionElement) {
298: WindowPane windowPane = (WindowPane) component;
299: boolean closable = ((Boolean) windowPane.getRenderProperty(
300: WindowPane.PROPERTY_CLOSABLE, Boolean.TRUE))
301: .booleanValue();
302: if (closable) {
303: ci.getUpdateManager().getClientUpdateManager()
304: .setComponentAction(component,
305: WindowPane.INPUT_CLOSE, null);
306: }
307: }
308:
309: /**
310: * @see nextapp.echo2.webcontainer.PropertyUpdateProcessor#processPropertyUpdate(
311: * nextapp.echo2.webcontainer.ContainerInstance,
312: * nextapp.echo2.app.Component, org.w3c.dom.Element)
313: */
314: public void processPropertyUpdate(ContainerInstance ci,
315: Component component, Element propertyElement) {
316: String propertyName = propertyElement
317: .getAttribute(PropertyUpdateProcessor.PROPERTY_NAME);
318: WindowPane windowPane = (WindowPane) component;
319: boolean movable = ((Boolean) windowPane.getRenderProperty(
320: WindowPane.PROPERTY_MOVABLE, Boolean.TRUE))
321: .booleanValue();
322: boolean resizable = ((Boolean) windowPane.getRenderProperty(
323: WindowPane.PROPERTY_RESIZABLE, Boolean.TRUE))
324: .booleanValue();
325: if (WindowPane.PROPERTY_POSITION_X.equals(propertyName)) {
326: if (movable) {
327: ci
328: .getUpdateManager()
329: .getClientUpdateManager()
330: .setComponentProperty(
331: component,
332: WindowPane.PROPERTY_POSITION_X,
333: ExtentRender
334: .toExtent(propertyElement
335: .getAttribute(PropertyUpdateProcessor.PROPERTY_VALUE)));
336: }
337: } else if (WindowPane.PROPERTY_POSITION_Y.equals(propertyName)) {
338: if (movable) {
339: ci
340: .getUpdateManager()
341: .getClientUpdateManager()
342: .setComponentProperty(
343: component,
344: WindowPane.PROPERTY_POSITION_Y,
345: ExtentRender
346: .toExtent(propertyElement
347: .getAttribute(PropertyUpdateProcessor.PROPERTY_VALUE)));
348: }
349: } else if (WindowPane.PROPERTY_WIDTH.equals(propertyName)) {
350: if (resizable) {
351: ci
352: .getUpdateManager()
353: .getClientUpdateManager()
354: .setComponentProperty(
355: component,
356: WindowPane.PROPERTY_WIDTH,
357: ExtentRender
358: .toExtent(propertyElement
359: .getAttribute(PropertyUpdateProcessor.PROPERTY_VALUE)));
360: }
361: } else if (WindowPane.PROPERTY_HEIGHT.equals(propertyName)) {
362: if (resizable) {
363: ci
364: .getUpdateManager()
365: .getClientUpdateManager()
366: .setComponentProperty(
367: component,
368: WindowPane.PROPERTY_HEIGHT,
369: ExtentRender
370: .toExtent(propertyElement
371: .getAttribute(PropertyUpdateProcessor.PROPERTY_VALUE)));
372: }
373: } else if (WindowPane.Z_INDEX_CHANGED_PROPERTY
374: .equals(propertyName)) {
375: ci
376: .getUpdateManager()
377: .getClientUpdateManager()
378: .setComponentProperty(
379: component,
380: WindowPane.Z_INDEX_CHANGED_PROPERTY,
381: new Integer(
382: propertyElement
383: .getAttribute(PropertyUpdateProcessor.PROPERTY_VALUE)));
384: }
385: }
386:
387: /**
388: * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#renderAdd(nextapp.echo2.webcontainer.RenderContext,
389: * nextapp.echo2.app.update.ServerComponentUpdate, java.lang.String,
390: * nextapp.echo2.app.Component)
391: */
392: public void renderAdd(RenderContext rc,
393: ServerComponentUpdate update, String targetId,
394: Component component) {
395: ServerMessage serverMessage = rc.getServerMessage();
396: serverMessage.addLibrary(WINDOW_PANE_SERVICE.getId());
397: WindowPane windowPane = (WindowPane) component;
398: renderInitDirective(rc, windowPane, targetId);
399: Component[] children = windowPane.getVisibleComponents();
400: if (children.length != 0) {
401: ComponentSynchronizePeer syncPeer = SynchronizePeerFactory
402: .getPeerForComponent(children[0].getClass());
403: syncPeer.renderAdd(rc, update, getContainerId(children[0]),
404: children[0]);
405: }
406: }
407:
408: /**
409: * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#renderDispose(nextapp.echo2.webcontainer.RenderContext,
410: * nextapp.echo2.app.update.ServerComponentUpdate,
411: * nextapp.echo2.app.Component)
412: */
413: public void renderDispose(RenderContext rc,
414: ServerComponentUpdate update, Component component) {
415: ServerMessage serverMessage = rc.getServerMessage();
416: serverMessage.addLibrary(WINDOW_PANE_SERVICE.getId());
417: renderDisposeDirective(rc, (WindowPane) component);
418: }
419:
420: /**
421: * Renders a directive to the outgoing <code>ServerMessage</code> to
422: * dispose the state of a <code>WindowPane</code>, performing tasks such as
423: * unregistering event listeners on the client.
424: *
425: * @param rc the relevant <code>RenderContext</code>
426: * @param windowPane the <code>WindowPane</code>
427: */
428: private void renderDisposeDirective(RenderContext rc,
429: WindowPane windowPane) {
430: String elementId = ContainerInstance.getElementId(windowPane);
431: ServerMessage serverMessage = rc.getServerMessage();
432: Element initElement = serverMessage.appendPartDirective(
433: ServerMessage.GROUP_ID_PREREMOVE,
434: "EchoWindowPane.MessageProcessor", "dispose");
435: initElement.setAttribute("eid", elementId);
436: }
437:
438: /**
439: * Renders a directive to the outgoing <code>ServerMessage</code> to
440: * render and intialize the state of a <code>WindowPane</code>.
441: *
442: * @param rc the relevant <code>RenderContext</code>
443: * @param windowPane the <code>WindowPane</code>
444: * @param targetId the id of the container element
445: */
446: private void renderInitDirective(RenderContext rc,
447: WindowPane windowPane, String targetId) {
448: String elementId = ContainerInstance.getElementId(windowPane);
449: ServerMessage serverMessage = rc.getServerMessage();
450: Element partElement = serverMessage.addPart(
451: ServerMessage.GROUP_ID_UPDATE,
452: "EchoWindowPane.MessageProcessor");
453: Element initElement = serverMessage.getDocument()
454: .createElement("init");
455: initElement.setAttribute("container-eid", targetId);
456: initElement.setAttribute("eid", elementId);
457:
458: if (!windowPane.isRenderEnabled()) {
459: initElement.setAttribute("enabled", "false");
460: }
461: if (windowPane.getZIndex() != 0) {
462: initElement.setAttribute("z-index", Integer
463: .toString(windowPane.getZIndex()));
464: }
465:
466: // Content Appearance
467: Insets insets = (Insets) windowPane
468: .getRenderProperty(WindowPane.PROPERTY_INSETS);
469: if (insets != null) {
470: initElement.setAttribute("insets", InsetsRender
471: .renderCssAttributeValue(insets));
472: }
473: Color background = (Color) windowPane
474: .getRenderProperty(WindowPane.PROPERTY_BACKGROUND);
475: if (background != null) {
476: initElement.setAttribute("background", ColorRender
477: .renderCssAttributeValue(background));
478: }
479: FillImage backgroundImage = (FillImage) windowPane
480: .getRenderProperty(WindowPane.PROPERTY_BACKGROUND_IMAGE);
481: if (backgroundImage != null) {
482: CssStyle backgroundImageCssStyle = new CssStyle();
483: FillImageRender.renderToStyle(backgroundImageCssStyle, rc,
484: this , windowPane, IMAGE_ID_BACKGROUND,
485: backgroundImage, 0);
486: initElement.setAttribute("background-image",
487: backgroundImageCssStyle.renderInline());
488: }
489: Color foreground = (Color) windowPane
490: .getRenderProperty(WindowPane.PROPERTY_FOREGROUND);
491: if (foreground != null) {
492: initElement.setAttribute("foreground", ColorRender
493: .renderCssAttributeValue(foreground));
494: }
495: Font font = (Font) windowPane
496: .getRenderProperty(WindowPane.PROPERTY_FONT);
497: if (font != null) {
498: CssStyle fontCssStyle = new CssStyle();
499: FontRender.renderToStyle(fontCssStyle, font);
500: initElement.setAttribute("font", fontCssStyle
501: .renderInline());
502: }
503:
504: // Positioning
505: renderPixelProperty(windowPane, WindowPane.PROPERTY_POSITION_X,
506: initElement, "position-x");
507: renderPixelProperty(windowPane, WindowPane.PROPERTY_POSITION_Y,
508: initElement, "position-y");
509: renderPixelProperty(windowPane, WindowPane.PROPERTY_WIDTH,
510: initElement, "width");
511: renderPixelProperty(windowPane, WindowPane.PROPERTY_HEIGHT,
512: initElement, "height");
513: renderPixelProperty(windowPane,
514: WindowPane.PROPERTY_MINIMUM_WIDTH, initElement,
515: "minimum-width");
516: renderPixelProperty(windowPane,
517: WindowPane.PROPERTY_MINIMUM_HEIGHT, initElement,
518: "minimum-height");
519: renderPixelProperty(windowPane,
520: WindowPane.PROPERTY_MAXIMUM_WIDTH, initElement,
521: "maximum-width");
522: renderPixelProperty(windowPane,
523: WindowPane.PROPERTY_MAXIMUM_HEIGHT, initElement,
524: "maximum-height");
525:
526: int fillImageRenderFlags = ((Boolean) windowPane
527: .getRenderProperty(PROPERTY_IE_ALPHA_RENDER_BORDER,
528: Boolean.FALSE)).booleanValue() ? FillImageRender.FLAG_ENABLE_IE_PNG_ALPHA_FILTER
529: : 0;
530:
531: // Title-related
532: if (windowPane.getRenderProperty(WindowPane.PROPERTY_ICON) != null) {
533: initElement.setAttribute("icon", ImageTools.getUri(rc,
534: this , windowPane, IMAGE_ID_ICON));
535: Insets iconInsets = (Insets) windowPane
536: .getRenderProperty(WindowPane.PROPERTY_ICON_INSETS);
537: if (iconInsets != null) {
538: initElement.setAttribute("icon-insets", InsetsRender
539: .renderCssAttributeValue(iconInsets));
540: }
541: }
542: String title = (String) windowPane
543: .getRenderProperty(WindowPane.PROPERTY_TITLE);
544: if (title != null) {
545: initElement.setAttribute("title", title);
546: Insets titleInsets = (Insets) windowPane
547: .getRenderProperty(WindowPane.PROPERTY_TITLE_INSETS);
548: Color titleForeground = (Color) windowPane
549: .getRenderProperty(WindowPane.PROPERTY_TITLE_FOREGROUND);
550: if (titleForeground != null) {
551: initElement
552: .setAttribute(
553: "title-foreground",
554: ColorRender
555: .renderCssAttributeValue(titleForeground));
556: }
557: if (titleInsets != null) {
558: initElement.setAttribute("title-insets", InsetsRender
559: .renderCssAttributeValue(titleInsets));
560: }
561: Font titleFont = (Font) windowPane
562: .getRenderProperty(WindowPane.PROPERTY_TITLE_FONT);
563: if (titleFont != null) {
564: CssStyle fontCssStyle = new CssStyle();
565: FontRender.renderToStyle(fontCssStyle, titleFont);
566: initElement.setAttribute("title-font", fontCssStyle
567: .renderInline());
568: }
569: }
570: Insets titleBarInsets = (Insets) windowPane
571: .getRenderProperty(WindowPane.PROPERTY_TITLE_BAR_INSETS);
572: if (titleBarInsets != null) {
573: initElement.setAttribute("title-bar-insets", InsetsRender
574: .renderCssAttributeValue(titleBarInsets));
575: }
576: renderPixelProperty(windowPane,
577: WindowPane.PROPERTY_TITLE_HEIGHT, initElement,
578: "title-height");
579: Color titleBackground = (Color) windowPane
580: .getRenderProperty(WindowPane.PROPERTY_TITLE_BACKGROUND);
581: if (titleBackground != null) {
582: initElement.setAttribute("title-background", ColorRender
583: .renderCssAttributeValue(titleBackground));
584: }
585: FillImage titleBackgroundImage = (FillImage) windowPane
586: .getRenderProperty(WindowPane.PROPERTY_TITLE_BACKGROUND_IMAGE);
587: if (titleBackgroundImage != null) {
588: CssStyle titleBackgroundImageCssStyle = new CssStyle();
589: FillImageRender.renderToStyle(titleBackgroundImageCssStyle,
590: rc, this , windowPane, IMAGE_ID_TITLE_BACKGROUND,
591: titleBackgroundImage, fillImageRenderFlags);
592: initElement.setAttribute("title-background-image",
593: titleBackgroundImageCssStyle.renderInline());
594: }
595:
596: // Move/Close/Resize
597: Boolean resizableBoolean = (Boolean) windowPane
598: .getRenderProperty(WindowPane.PROPERTY_RESIZABLE);
599: boolean resizable = resizableBoolean == null ? true
600: : resizableBoolean.booleanValue();
601: initElement.setAttribute("resizable", resizable ? "true"
602: : "false");
603: Boolean closableBoolean = (Boolean) windowPane
604: .getRenderProperty(WindowPane.PROPERTY_CLOSABLE);
605: boolean closable = closableBoolean == null ? true
606: : closableBoolean.booleanValue();
607: initElement.setAttribute("closable", closable ? "true"
608: : "false");
609: if (closable) {
610: if (getImage(windowPane, IMAGE_ID_CLOSE_ICON) != null) {
611: initElement.setAttribute("close-icon", ImageTools
612: .getUri(rc, this , windowPane,
613: IMAGE_ID_CLOSE_ICON));
614: Insets closeIconInsets = (Insets) windowPane
615: .getRenderProperty(WindowPane.PROPERTY_CLOSE_ICON_INSETS);
616: if (closeIconInsets != null) {
617: initElement
618: .setAttribute(
619: "close-icon-insets",
620: InsetsRender
621: .renderCssAttributeValue(closeIconInsets));
622: }
623: }
624: }
625: Boolean movableBoolean = (Boolean) windowPane
626: .getRenderProperty(WindowPane.PROPERTY_MOVABLE);
627: boolean movable = movableBoolean == null ? true
628: : movableBoolean.booleanValue();
629: initElement.setAttribute("movable", movable ? "true" : "false");
630:
631: // Border
632: FillImageBorder border = (FillImageBorder) windowPane
633: .getRenderProperty(WindowPane.PROPERTY_BORDER);
634: if (border != null && border.getBorderInsets() != null
635: && border.getContentInsets() != null) {
636: Element borderElement = serverMessage.getDocument()
637: .createElement("border");
638: if (border.getColor() != null) {
639: borderElement.setAttribute("color", ColorRender
640: .renderCssAttributeValue(border.getColor()));
641: }
642: borderElement.setAttribute("border-insets", InsetsRender
643: .renderCssAttributeValue(border.getBorderInsets()));
644: borderElement
645: .setAttribute("content-insets", InsetsRender
646: .renderCssAttributeValue(border
647: .getContentInsets()));
648: for (int i = 0; i < 8; ++i) {
649: FillImage fillImage = border.getFillImage(i);
650: if (fillImage != null) {
651: Element imageElement = serverMessage.getDocument()
652: .createElement("image");
653: imageElement.setAttribute("name",
654: FILL_IMAGE_NAMES[i]);
655: CssStyle fillImageCssStyle = new CssStyle();
656: FillImageRender.renderToStyle(fillImageCssStyle,
657: rc, this , windowPane, FILL_IMAGE_IDS[i],
658: fillImage, fillImageRenderFlags);
659: imageElement.setAttribute("value",
660: fillImageCssStyle.renderInline());
661: borderElement.appendChild(imageElement);
662: }
663: }
664: initElement.appendChild(borderElement);
665: }
666:
667: partElement.appendChild(initElement);
668: }
669:
670: private void renderSetContent(RenderContext rc,
671: ServerComponentUpdate update) {
672: //TODO. implement
673: }
674:
675: /**
676: * @see nextapp.echo2.webcontainer.ComponentSynchronizePeer#renderUpdate(nextapp.echo2.webcontainer.RenderContext,
677: * nextapp.echo2.app.update.ServerComponentUpdate, java.lang.String)
678: */
679: public boolean renderUpdate(RenderContext rc,
680: ServerComponentUpdate update, String targetId) {
681: boolean fullReplace = false;
682: if (update.hasUpdatedLayoutDataChildren()) {
683: fullReplace = true;
684: } else if (update.hasUpdatedProperties()) {
685: if (partialUpdateManager.canProcess(rc, update)) {
686: renderUpdateDirective(rc, update);
687: } else {
688: fullReplace = true;
689: }
690: }
691:
692: if (update.hasAddedChildren() || update.hasRemovedChildren()
693: || update.hasUpdatedLayoutDataChildren()) {
694: //TODO. temporary, renderSetContent needs impl
695: fullReplace = true;
696: }
697:
698: if (fullReplace) {
699: // Perform full update.
700: renderDisposeDirective(rc, (WindowPane) update.getParent());
701: DomUpdate.renderElementRemove(rc.getServerMessage(),
702: ContainerInstance.getElementId(update.getParent()));
703: renderAdd(rc, update, targetId, update.getParent());
704: } else {
705: partialUpdateManager.process(rc, update);
706: if (update.hasAddedChildren()
707: || update.hasRemovedChildren()) {
708: renderSetContent(rc, update);
709: }
710: }
711:
712: return fullReplace;
713: }
714:
715: private void renderUpdateDirective(RenderContext rc,
716: ServerComponentUpdate update) {
717: WindowPane windowPane = (WindowPane) update.getParent();
718:
719: Element updateElement = rc.getServerMessage()
720: .appendPartDirective(ServerMessage.GROUP_ID_PREREMOVE,
721: "EchoWindowPane.MessageProcessor", "update");
722: String elementId = ContainerInstance.getElementId(windowPane);
723: updateElement.setAttribute("eid", elementId);
724:
725: PropertyUpdate positionX = update
726: .getUpdatedProperty(WindowPane.PROPERTY_POSITION_X);
727: if (positionX != null) {
728: renderPixelProperty(windowPane,
729: WindowPane.PROPERTY_POSITION_X, updateElement,
730: "position-x");
731: }
732:
733: PropertyUpdate positionY = update
734: .getUpdatedProperty(WindowPane.PROPERTY_POSITION_Y);
735: if (positionY != null) {
736: renderPixelProperty(windowPane,
737: WindowPane.PROPERTY_POSITION_Y, updateElement,
738: "position-y");
739: }
740:
741: PropertyUpdate width = update
742: .getUpdatedProperty(WindowPane.PROPERTY_WIDTH);
743: if (width != null) {
744: renderPixelProperty(windowPane, WindowPane.PROPERTY_WIDTH,
745: updateElement, "width");
746: }
747:
748: PropertyUpdate height = update
749: .getUpdatedProperty(WindowPane.PROPERTY_HEIGHT);
750: if (height != null) {
751: renderPixelProperty(windowPane, WindowPane.PROPERTY_HEIGHT,
752: updateElement, "height");
753: }
754:
755: if (update.getUpdatedProperty(WindowPane.PROPERTY_TITLE) != null) {
756: updateElement.setAttribute("title", (String) windowPane
757: .getRenderProperty(WindowPane.PROPERTY_TITLE, " "));
758: }
759: }
760: }
|