Source Code Cross Referenced for Utils.java in  » Swing-Library » wings3 » org » wings » plaf » css » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Swing Library » wings3 » org.wings.plaf.css 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2000,2005 wingS development team.
0003:         *
0004:         * This file is part of wingS (http://wingsframework.org).
0005:         *
0006:         * wingS is free software; you can redistribute it and/or modify
0007:         * it under the terms of the GNU Lesser General Public License
0008:         * as published by the Free Software Foundation; either version 2.1
0009:         * of the License, or (at your option) any later version.
0010:         *
0011:         * Please see COPYING for the complete licence.
0012:         */
0013:        package org.wings.plaf.css;
0014:
0015:        import org.apache.commons.logging.Log;
0016:        import org.apache.commons.logging.LogFactory;
0017:        import org.wings.*;
0018:        import org.wings.border.SAbstractBorder;
0019:        import org.wings.border.SDefaultBorder;
0020:        import org.wings.border.SBorder;
0021:        import org.wings.externalizer.ExternalizeManager;
0022:        import org.wings.header.JavaScriptHeader;
0023:        import org.wings.header.Link;
0024:        import org.wings.header.Script;
0025:        import org.wings.header.StyleSheetHeader;
0026:        import org.wings.io.Device;
0027:        import org.wings.io.NullDevice;
0028:        import org.wings.io.StringBuilderDevice;
0029:        import org.wings.resource.*;
0030:        import org.wings.script.JavaScriptDOMListener;
0031:        import org.wings.script.JavaScriptEvent;
0032:        import org.wings.script.JavaScriptListener;
0033:        import org.wings.script.ScriptListener;
0034:        import org.wings.session.BrowserType;
0035:        import org.wings.session.Session;
0036:        import org.wings.session.SessionManager;
0037:        import org.wings.style.Style;
0038:        import org.wings.style.CSSStyle;
0039:        import org.wings.style.CSSAttributeSet;
0040:        import org.wings.util.SStringBuilder;
0041:
0042:        import java.awt.*;
0043:        import java.io.BufferedReader;
0044:        import java.io.IOException;
0045:        import java.io.InputStream;
0046:        import java.io.InputStreamReader;
0047:        import java.util.ArrayList;
0048:        import java.util.HashMap;
0049:        import java.util.HashSet;
0050:        import java.util.Iterator;
0051:        import java.util.List;
0052:        import java.util.Map;
0053:        import java.util.Set;
0054:        import java.util.StringTokenizer;
0055:
0056:        /**
0057:         * Utils.java
0058:         * <p/>
0059:         * Helper class that collects static methods usable from CGs.
0060:         *
0061:         * @author <a href="mailto:mreinsch@to.com">Michael Reinsch</a>
0062:         */
0063:        public final class Utils {
0064:            /**
0065:             * Apache jakarta commons logger
0066:             */
0067:            private static final Log log = LogFactory.getLog(Utils.class);
0068:
0069:            /**
0070:             * Print debug information in generated HTML
0071:             */
0072:            public final static boolean PRINT_DEBUG;
0073:            public final static boolean PRINT_PRETTY;
0074:
0075:            public final static String HEADER_LOADED_CALLBACK = "if (typeof wingS != \"undefined\") {\n"
0076:                    + "    wingS.global.finishedLoadingHeader();\n" + "}";
0077:
0078:            static {
0079:                Session session = SessionManager.getSession();
0080:                // Respect settings from resource.properties
0081:                Boolean printDebug = (Boolean) ResourceManager.getObject(
0082:                        "SComponent.printDebug", Boolean.class);
0083:                Boolean printPretty = (Boolean) ResourceManager.getObject(
0084:                        "SComponent.printPretty", Boolean.class);
0085:                // May be overriden in i.e. web.xml. Hopefully we touch the class inside a session for the first time
0086:                if (session != null) {
0087:                    if (session.getProperty("SComponent.printDebug") != null)
0088:                        printDebug = Boolean.valueOf((String) session
0089:                                .getProperty("SComponent.printDebug"));
0090:                    if (session.getProperty("SComponent.printPretty") != null)
0091:                        printPretty = Boolean.valueOf((String) session
0092:                                .getProperty("SComponent.printPretty"));
0093:                }
0094:                PRINT_DEBUG = printDebug.booleanValue();
0095:                PRINT_PRETTY = printPretty.booleanValue();
0096:            }
0097:
0098:            protected final static char[] hexDigits = { '0', '1', '2', '3',
0099:                    '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
0100:
0101:            private Utils() {
0102:            }
0103:
0104:            /**
0105:             * Default list of javascript events to exlcude in {@link #writeEvents(org.wings.io.Device, org.wings.SComponent, String[])}
0106:             */
0107:            public final static String[] EXCLUDE_ON_CLICK = new String[] { JavaScriptEvent.ON_CLICK };
0108:
0109:            /**
0110:             * Renders a container using its Layout manager or fallback just one after another.
0111:             */
0112:            public static void renderContainer(Device d, SContainer c)
0113:                    throws IOException {
0114:                final SLayoutManager layout = c.getLayout();
0115:
0116:                if (layout == null) {
0117:                    d.print("<tbody><tr><td>");
0118:                    // just write out the components one after another
0119:                    for (int i = 0; i < c.getComponentCount(); i++) {
0120:                        c.getComponent(i).write(d);
0121:                    }
0122:                    d.print("</td></tr></tbody>");
0123:                } else {
0124:                    layout.write(d);
0125:                }
0126:            }
0127:
0128:            /**
0129:             * Render inline event listeners attached to the passed component exlucding types of suppressed listeners
0130:             *
0131:             * @param device                      output device
0132:             * @param c                           component to retrieve listeners from
0133:             * @param suppressScriptListenerTypes Array of String i.e. <code>new String[] { JavaScriptEvent.ON_CLICK } )</code>
0134:             */
0135:            public static void writeEvents(final Device device,
0136:                    final SComponent c,
0137:                    final String[] suppressScriptListenerTypes)
0138:                    throws IOException {
0139:                if (!c.isEnabled())
0140:                    return;
0141:
0142:                Set<String> types = new HashSet<String>();
0143:                // Create set of strings (in lower case) defining the event types to be suppressed
0144:                if (suppressScriptListenerTypes != null
0145:                        && suppressScriptListenerTypes.length > 0) {
0146:                    for (String suppressScriptListenerType : suppressScriptListenerTypes) {
0147:                        types.add(suppressScriptListenerType.toLowerCase());
0148:                    }
0149:                }
0150:                ScriptListener[] listeners = c.getScriptListeners();
0151:                if (listeners.length > 0) {
0152:                    Map<String, String> eventScripts = new HashMap<String, String>();
0153:                    // Fill map with script codes grouped by event type (key)
0154:                    for (final ScriptListener script : listeners) {
0155:                        if (types.contains(script.getEvent().toLowerCase())) {
0156:                            continue;
0157:                        }
0158:                        // If its a DOM event we are finished here
0159:                        if (script instanceof  JavaScriptDOMListener) {
0160:                            continue;
0161:                        }
0162:                        final String event = script.getEvent();
0163:                        String eventScriptCode = script.getCode();
0164:
0165:                        if (event == null || event.length() == 0
0166:                                || eventScriptCode == null
0167:                                || eventScriptCode.length() == 0) {
0168:                            continue;
0169:                        }
0170:
0171:                        if (eventScripts.containsKey(event)) {
0172:                            String savedEventScriptCode = eventScripts
0173:                                    .get(event);
0174:                            eventScriptCode = savedEventScriptCode
0175:                                    + (savedEventScriptCode.trim()
0176:                                            .endsWith(";") ? "" : ";")
0177:                                    + eventScriptCode;
0178:                        }
0179:                        eventScripts.put(event, eventScriptCode);
0180:                    }
0181:
0182:                    // Print map of script codes grouped by event type (key)
0183:                    for (final String event : eventScripts.keySet()) {
0184:                        final String code = eventScripts.get(event);
0185:                        Utils.optAttribute(device, event, code);
0186:                    }
0187:                }
0188:            }
0189:
0190:            /**
0191:             * Returns the according event ID for the given component.
0192:             */
0193:            public static String event(SComponent component) {
0194:                if (component instanceof  SClickable)
0195:                    return ((SClickable) component).getEventTarget()
0196:                            .getLowLevelEventId();
0197:                else
0198:                    return component.getLowLevelEventId();
0199:            }
0200:
0201:            /**
0202:             * HTML allows 4 values for the horizontal align property of a div element.
0203:             *
0204:             * @param d     Output
0205:             * @param align Please refer {@link SConstants}
0206:             * @throws IOException
0207:             */
0208:            public static void printDivHorizontalAlignment(Device d, int align)
0209:                    throws IOException {
0210:                printTableHorizontalAlignment(d, align);
0211:            }
0212:
0213:            /**
0214:             * Horizontal alignment for TABLE cells. i.e. <code>align="center"</code>
0215:             */
0216:            private static void printTableHorizontalAlignment(final Device d,
0217:                    final int align) throws IOException {
0218:                if (align == SConstants.NO_ALIGN) {
0219:                    // d.print(" align=\"left\"");
0220:                } else if (align == SConstants.LEFT) {
0221:                    d.print(" align=\"left\"");
0222:                } else if (align == SConstants.CENTER) {
0223:                    d.print(" align=\"center\"");
0224:                } else if (align == SConstants.RIGHT) {
0225:                    d.print(" align=\"right\"");
0226:                } else if (align == SConstants.JUSTIFY) {
0227:                    d.print(" align=\"justify\"");
0228:                }
0229:            }
0230:
0231:            /**
0232:             * HTML allows 4 values for the vertical align property of a div element.
0233:             *
0234:             * @param d     Output
0235:             * @param align Please refer {@link SConstants}
0236:             * @throws IOException
0237:             */
0238:            public static void printDivVerticalAlignment(Device d, int align)
0239:                    throws IOException {
0240:                printTableVerticalAlignment(d, align);
0241:            }
0242:
0243:            /**
0244:             * Vertical alignment for TABLE cells. i.e. <code>valign="top"</code>
0245:             */
0246:            private static void printTableVerticalAlignment(Device d, int align)
0247:                    throws IOException {
0248:                if (align == SConstants.NO_ALIGN) {
0249:                    //d.print(" valign=\"center\"");
0250:                } else if (align == SConstants.CENTER) {
0251:                    d.print(" valign=\"middle\"");
0252:                } else if (align == SConstants.TOP) {
0253:                    d.print(" valign=\"top\"");
0254:                } else if (align == SConstants.BOTTOM) {
0255:                    d.print(" valign=\"bottom\"");
0256:                } else if (align == SConstants.BASELINE) {
0257:                    d.print(" valign=\"baseline\"");
0258:                }
0259:            }
0260:
0261:            /**
0262:             * Renders the alignment commands for a table cell (horzontal and vertical).
0263:             * To ensure a consistent behaviour you have to pass the default alignment applied for <code>SConstants.NO_ALIGN</code>.
0264:             *
0265:             * @param defaultHorizontal default horizontal alignment to use is not aligned
0266:             * @param defaultVertical   default vertical alignment to use if component is not aligned
0267:             */
0268:            public static void printTableCellAlignment(final Device d,
0269:                    final SComponent c, final int defaultHorizontal,
0270:                    final int defaultVertical) throws IOException {
0271:                if (c != null) {
0272:                    final int horizontalAlignment = c.getHorizontalAlignment();
0273:                    final int verticalAlignment = c.getVerticalAlignment();
0274:                    printTableHorizontalAlignment(
0275:                            d,
0276:                            horizontalAlignment != SConstants.NO_ALIGN ? horizontalAlignment
0277:                                    : defaultHorizontal);
0278:                    printTableVerticalAlignment(
0279:                            d,
0280:                            verticalAlignment != SConstants.NO_ALIGN ? verticalAlignment
0281:                                    : defaultVertical);
0282:                }
0283:            }
0284:
0285:            public static String toColorString(int rgb) {
0286:                char[] buf = new char[6];
0287:                int digits = 6;
0288:                do {
0289:                    buf[--digits] = hexDigits[rgb & 15];
0290:                    rgb >>>= 4;
0291:                } while (digits != 0);
0292:
0293:                return new String(buf);
0294:            }
0295:
0296:            public static String toColorString(java.awt.Color c) {
0297:                return toColorString(c.getRGB());
0298:            }
0299:
0300:            /**
0301:             * Generates a SStringBuilder containing inlined CSS styles for the following properties of a SComponent:
0302:             * <p><ul><li>Preffered Size</li><li>Font</li><li>Background- and Foregroud color.</li></ul>
0303:             *
0304:             * @param component Component to grab parameters from.
0305:             */
0306:            public static SStringBuilder generateCSSComponentInlineStyle(
0307:                    SComponent component) {
0308:                final SStringBuilder styleString = new SStringBuilder();
0309:                appendCSSInlineSize(styleString, component);
0310:                appendCSSComponentInlineColorStyle(styleString, component);
0311:                appendCSSComponentInlineFontStyle(styleString, component);
0312:                return styleString;
0313:            }
0314:
0315:            /**
0316:             * Append a inline CSS style definition for the passed component of the aspect foreground- and background color.
0317:             *
0318:             * @param styleString SStringBuilder to append to
0319:             * @param component   Component to use as style source
0320:             * @return The passed styleString
0321:             */
0322:            public static SStringBuilder appendCSSComponentInlineColorStyle(
0323:                    SStringBuilder styleString, final SComponent component) {
0324:                if (component != null) {
0325:                    if (component.getBackground() != null) {
0326:                        styleString.append("background-color:#").append(
0327:                                toColorString(component.getBackground()))
0328:                                .append(";");
0329:                    }
0330:
0331:                    if (component.getForeground() != null) {
0332:                        styleString.append("color:#").append(
0333:                                toColorString(component.getForeground()))
0334:                                .append(";");
0335:                    }
0336:                }
0337:                return styleString;
0338:            }
0339:
0340:            /**
0341:             * Append a inline CSS style definition for the passed component of the aspect font properties.
0342:             *
0343:             * @param styleString SStringBuilder to append to
0344:             * @param component   Component to use as style source
0345:             * @return The passed styleString
0346:             */
0347:            public static SStringBuilder appendCSSComponentInlineFontStyle(
0348:                    final SStringBuilder styleString, final SComponent component) {
0349:                if (component != null && component.getFont() != null) {
0350:                    final SFont font = component.getFont();
0351:                    styleString.append("font-size:").append(font.getSize())
0352:                            .append("pt;");
0353:                    styleString.append("font-style:").append(
0354:                            (font.getStyle() & SFont.ITALIC) > 0 ? "italic;"
0355:                                    : "normal;");
0356:                    styleString.append("font-weight:").append(
0357:                            (font.getStyle() & SFont.BOLD) > 0 ? "bold;"
0358:                                    : "normal;");
0359:                    styleString.append("font-family:").append(font.getFace())
0360:                            .append(";");
0361:                }
0362:                return styleString;
0363:            }
0364:
0365:            /**
0366:             * Appends a CSS inline style string for the preferred size of the passed component to the passed stringbuffer.
0367:             * <p>Sample: <code>width:100%;heigth=15px"</code>
0368:             */
0369:            public static SStringBuilder appendCSSInlineSize(
0370:                    SStringBuilder styleString, SComponent component) {
0371:                if (component == null)
0372:                    return styleString;
0373:                SDimension preferredSize = component.getPreferredSize();
0374:                if (preferredSize != null) {
0375:                    boolean msie = isMSIE(component);
0376:                    if (msie && "px".equals(preferredSize.getWidthUnit())) {
0377:                        int oversize = calculateHorizontalOversize(component,
0378:                                false);
0379:                        styleString.append("width:").append(
0380:                                preferredSize.getWidthInt() - oversize).append(
0381:                                "px;");
0382:                    } else if (!SDimension.AUTO.equals(preferredSize
0383:                            .getWidthUnit()))
0384:                        styleString.append("width:").append(
0385:                                preferredSize.getWidth()).append(';');
0386:
0387:                    if (msie && "px".equals(preferredSize.getHeightUnit())) {
0388:                        int oversize = calculateVerticalOversize(component,
0389:                                false);
0390:                        styleString.append("height:").append(
0391:                                preferredSize.getHeightInt() - oversize)
0392:                                .append("px;");
0393:                    } else if (!SDimension.AUTO.equals(preferredSize
0394:                            .getHeightUnit()))
0395:                        styleString.append("height:").append(
0396:                                preferredSize.getHeight()).append(';');
0397:                }
0398:                return styleString;
0399:            }
0400:
0401:            public static SStringBuilder generateCSSInlineBorder(
0402:                    SStringBuilder styles, int borderSize) {
0403:                if (borderSize > 0) {
0404:                    styles.append("border:").append(borderSize).append(
0405:                            "px solid black;");
0406:                } else {
0407:                    //styleString.append("border:none;"); Not necessary. Default
0408:                }
0409:                return styles;
0410:            }
0411:
0412:            /**
0413:             * Prints a HTML style attribute with widht/height of 100% if the passed dimension defines a height or width..
0414:             * <p>Sample: <code> style="width:100%;"</code>
0415:             * <p/>
0416:             * <p>This is typicall needed to stretch inner HTML element to expand to the full dimenstion defined
0417:             * on an outer, sized HTML element. Otherwise the component would appear to small (as size is applied only
0418:             * on the invisible outer limiting element)
0419:             *
0420:             * @param device        Device to print to
0421:             * @param preferredSize trigger dimension
0422:             */
0423:            public static void printCSSInlineFullSize(Device device,
0424:                    SDimension preferredSize) throws IOException {
0425:                if ((preferredSize != null)
0426:                        && (!SDimension.AUTO.equals(preferredSize.getWidth()) || !SDimension.AUTO
0427:                                .equals(preferredSize.getHeight()))) {
0428:                    // opera doesn't show height 100% when parent has no defined height
0429:                    if (!SDimension.AUTO.equals(preferredSize.getHeight())) {
0430:                        device.print(" style=\"width:100%;height:100%\"");
0431:                    } else {
0432:                        device.print(" style=\"width:100%\"");
0433:                    }
0434:                }
0435:            }
0436:
0437:            /**
0438:             * Prints a HTML style attribute with widht/height of 100% if the passed dimension defines a height or width..
0439:             * <p>Sample: <code> style="width:100%;"</code>
0440:             * <p/>
0441:             * <p>This is typicall needed to stretch inner HTML element to expand to the full dimenstion defined
0442:             * on an outer, sized HTML element. Otherwise the component would appear to small (as size is applied only
0443:             * on the invisible outer limiting element)
0444:             *
0445:             * @param pSStringBuilder buffer to append to
0446:             * @param pComponent      preferredSize trigger dimension
0447:             */
0448:            public static void appendCSSInlineFullSize(
0449:                    SStringBuilder pSStringBuilder, SComponent pComponent) {
0450:                SDimension preferredSize = pComponent.getPreferredSize();
0451:                if (preferredSize != null
0452:                        && (!SDimension.AUTO.equals(preferredSize.getWidth()) || !SDimension.AUTO
0453:                                .equals(preferredSize.getHeight()))) {
0454:                    pSStringBuilder.append("width:100%;height:100%;");
0455:                }
0456:            }
0457:
0458:            /**
0459:             * Writes an {X|HT}ML quoted string according to RFC 1866.
0460:             * '"', '<', '>', '&'  become '&quot;', '&lt;', '&gt;', '&amp;'
0461:             *
0462:             * @param d              The device to print out on
0463:             * @param s              the String to print
0464:             * @param quoteNewline   should newlines be transformed into <code>&lt;br&gt;</code> tags
0465:             * @param quoteSpaces    should spaces be transformed into <code>&amp;nbsp</code>  chars
0466:             * @param quoteApostroph Quote apostroph <code>'</code> by <code>\'</code>
0467:             * @throws IOException
0468:             */
0469:            public static void quote(final Device d, final String s,
0470:                    final boolean quoteNewline, final boolean quoteSpaces,
0471:                    final boolean quoteApostroph) throws IOException {
0472:                if (s == null) {
0473:                    return;
0474:                }
0475:                char[] chars = s.toCharArray();
0476:                char c;
0477:                int last = 0;
0478:                for (int pos = 0; pos < chars.length; ++pos) {
0479:                    c = chars[pos];
0480:                    // write special characters as code ..
0481:                    if (c < 32 || c > 127) {
0482:                        d.print(chars, last, (pos - last));
0483:                        if (c == '\n' && quoteNewline) {
0484:                            d.print("<br>");
0485:                            if (pos == chars.length - 1
0486:                                    || chars[pos + 1] == '\n') // insert &nbsp; in empty/sequence <br>s.
0487:                                d.print("&nbsp;");
0488:                        } else {
0489:                            d.print("&#");
0490:                            d.print((int) c);
0491:                            d.print(';');
0492:                        } // end of if ()
0493:                        last = pos + 1;
0494:                    } else {
0495:                        switch (c) {
0496:                        case '&':
0497:                            d.print(chars, last, (pos - last));
0498:                            d.print("&amp;");
0499:                            last = pos + 1;
0500:                            break;
0501:                        case '"':
0502:                            d.print(chars, last, (pos - last));
0503:                            d.print("&quot;");
0504:                            last = pos + 1;
0505:                            break;
0506:                        case '<':
0507:                            d.print(chars, last, (pos - last));
0508:                            d.print("&lt;");
0509:                            last = pos + 1;
0510:                            break;
0511:                        case '>':
0512:                            d.print(chars, last, (pos - last));
0513:                            d.print("&gt;");
0514:                            last = pos + 1;
0515:                            break;
0516:                        /*
0517:                         * watchout: we cannot replace _space_ by &nbsp;
0518:                         * since non-breakable-space is a different
0519:                         * character: isolatin-char 160, not 32.
0520:                         * This will result in a confusion in forms:
0521:                         *   - the user enters space, presses submit
0522:                         *   - the form content is written to the Device by wingS,
0523:                         *     space is replaced by &nbsp;
0524:                         *   - the next time the form is submitted, we get
0525:                         *     isolatin-char 160, _not_ space.
0526:                         * (at least Konqueror behaves this correct; mozilla does not)
0527:                         *                                                       Henner
0528:                         *
0529:                         * But we must do this for IE, since it doesn't accept the
0530:                         * white-space: pre; property...so conditionalize it.
0531:                         *                                                       Ole
0532:                         */
0533:                        case ' ':
0534:                            if (quoteSpaces) {
0535:                                d.print(chars, last, (pos - last));
0536:                                d.print("&nbsp;");
0537:                                last = pos + 1;
0538:                            }
0539:                            break;
0540:                        /* Needed for i.e. js-code. */
0541:                        case '\'':
0542:                            if (quoteApostroph) {
0543:                                d.print(chars, last, (pos - last));
0544:                                d.print('\\');
0545:                                last = pos;
0546:                            }
0547:                            break;
0548:
0549:                        }
0550:                    }
0551:                }
0552:                d.print(chars, last, chars.length - last);
0553:            }
0554:
0555:            /**
0556:             * Writes text to the device without any HTML tag content.
0557:             * @param device The output device to use for quoting
0558:             * @param htmlWrappedText The text which may contain HTML to strip.
0559:             * @return The amount of characters written to the ouput device
0560:             * @throws IOException
0561:             */
0562:            public static int writeWithoutHTML(final Device device,
0563:                    final String htmlWrappedText) throws IOException {
0564:                final char[] chars = htmlWrappedText.toCharArray();
0565:                int pos = 0;
0566:                int len = 0;
0567:                for (int c = 0; c < chars.length; c++) {
0568:                    switch (chars[c]) {
0569:                    case '\n':
0570:                        chars[c] = ' ';
0571:                        break;
0572:                    case '<':
0573:                        len += (c - pos);
0574:                        device.print(chars, pos, c - pos);
0575:                        break;
0576:                    case '>':
0577:                        pos = c + 1;
0578:                    }
0579:                }
0580:                final int remain = chars.length - pos;
0581:                device.print(chars, pos, remain);
0582:                len += remain;
0583:                return len;
0584:            }
0585:
0586:            /**
0587:             * write string as it is
0588:             *
0589:             * @param d
0590:             * @param s
0591:             * @throws IOException
0592:             */
0593:            public static void writeRaw(Device d, String s) throws IOException {
0594:                if (s == null) {
0595:                    return;
0596:                }
0597:                d.print(s);
0598:            }
0599:
0600:            /**
0601:             * writes the given String to the device. The string is quoted, i.e.
0602:             * for all special characters in *ML, their appropriate entity is
0603:             * returned.
0604:             * If the String starts with '<html>', the content is regarded being
0605:             * HTML-code and is written as is (without the <html> tag).
0606:             */
0607:            public static void write(Device d, String s) throws IOException {
0608:                writeQuoted(d, s, false);
0609:            }
0610:
0611:            /**
0612:             * writes the given String to the device. The string is quoted, i.e.
0613:             * for all special characters in *ML, their appropriate entity is
0614:             * returned.
0615:             * If the String starts with '<html>', the content is regarded being
0616:             * HTML-code and is written as is (without the <html> tag).
0617:             * It is possible to define the quoteNewline behavoiur
0618:             */
0619:            public static void writeQuoted(Device d, String s,
0620:                    boolean quoteNewline) throws IOException {
0621:                if (s == null) {
0622:                    return;
0623:                }
0624:                if ((s.length() > 5)
0625:                        && (s.substring(0, 6).equalsIgnoreCase("<html>"))) {
0626:                    writeRaw(d, s.substring(6));
0627:                } else {
0628:                    quote(d, s, quoteNewline, false, false);
0629:                }
0630:            }
0631:
0632:            /**
0633:             * Prints an <b>optional</b> attribute. If the String value has a content
0634:             * (value != null && value.length > 0), the attrib is added otherwise
0635:             * it is left out
0636:             */
0637:            public static void optAttribute(final Device d, String attr,
0638:                    final SStringBuilder value) throws IOException {
0639:                optAttribute(d, attr, value != null ? value.toString() : null);
0640:            }
0641:
0642:            /**
0643:             * Prints an <b>optional</b> attribute. If the String value has a content
0644:             * (value != null && value.length > 0), the attrib is added otherwise
0645:             * it is left out
0646:             */
0647:            public static void optAttribute(final Device d,
0648:                    final char[] attributeName, final String value)
0649:                    throws IOException {
0650:                if (value != null && value.length() > 0) {
0651:                    d.print(' ').print(attributeName).print("=\"");
0652:                    quote(d, value, true, false, false);
0653:                    d.print('"');
0654:                }
0655:            }
0656:
0657:            /**
0658:             * Prints an <b>optional</b> attribute. If the String value has a content
0659:             * (value != null && value.length > 0), the attrib is added otherwise
0660:             * it is left out
0661:             */
0662:            public static void optAttribute(final Device d,
0663:                    final String attributeName, final String value)
0664:                    throws IOException {
0665:                if (value != null && value.length() > 0) {
0666:                    d.print(' ').print(attributeName).print("=\"");
0667:                    quote(d, value, true, false, false);
0668:                    d.print('"');
0669:                }
0670:            }
0671:
0672:            /**
0673:             * Prints an <b>mandatory</b> attribute. If the String value has a content
0674:             * (value != null && value.length > 0), the attrib is added otherwise
0675:             * it is left out
0676:             */
0677:            public static void attribute(final Device d, final String attr,
0678:                    final String value) throws IOException {
0679:                d.print(' ').print(attr).print("=\"");
0680:                if (value != null)
0681:                    quote(d, value, true, false, false);
0682:                d.print('"');
0683:            }
0684:
0685:            /**
0686:             * Prints an <b>optional</b> attribute. If the String value has a content
0687:             * (value != null && value.length > 0), the attrib is added otherwise
0688:             * it is left out
0689:             */
0690:            public static void optAttribute(final Device d, final String attr,
0691:                    final Color value) throws IOException {
0692:                if (value != null) {
0693:                    d.print(' ');
0694:                    d.print(attr);
0695:                    d.print("=\"");
0696:                    write(d, value);
0697:                    d.print('"');
0698:                }
0699:            }
0700:
0701:            /**
0702:             * Prints an optional, renderable attribute.
0703:             */
0704:            public static void optAttribute(final Device d, final String attr,
0705:                    final Renderable r) throws IOException {
0706:                if (r != null) {
0707:                    d.print(' ');
0708:                    d.print(attr);
0709:                    d.print("=\"");
0710:                    r.write(d);
0711:                    d.print('"');
0712:                }
0713:            }
0714:
0715:            /**
0716:             * Prints an <b>optional</b> attribute. If the integer value is greater than 0,
0717:             * the attrib is added otherwise it is left out
0718:             */
0719:            public static void optAttribute(final Device d,
0720:                    final char[] attributeName, final int value)
0721:                    throws IOException {
0722:                if (value > 0) {
0723:                    d.print(' ');
0724:                    d.print(attributeName);
0725:                    d.print("=\"");
0726:                    d.print(String.valueOf(value));
0727:                    d.print('"');
0728:                }
0729:            }
0730:
0731:            /**
0732:             * Prints an <b>optional</b> attribute. If the integer value is greater than 0,
0733:             * the attrib is added otherwise it is left out
0734:             */
0735:            public static void optAttribute(final Device d,
0736:                    final String attributeName, final int value)
0737:                    throws IOException {
0738:                if (value > 0) {
0739:                    d.print(' ');
0740:                    d.print(attributeName);
0741:                    d.print("=\"");
0742:                    d.print(String.valueOf(value));
0743:                    d.print('"');
0744:                }
0745:            }
0746:
0747:            /**
0748:             * Prints an <b>optional</b> attribute. If the dimension value not equals <i>null</i>
0749:             * the attrib is added otherwise it is left out
0750:             */
0751:            public static void optAttribute(final Device d, final String attr,
0752:                    final SDimension value) throws IOException {
0753:                if (value != null) {
0754:                    d.print(' ');
0755:                    d.print(attr);
0756:                    d.print("=\"");
0757:                    write(d, value.toString());
0758:                    d.print('"');
0759:                }
0760:            }
0761:
0762:            /**
0763:             * Prints all <b>optional</b> attributes that are contained in the
0764:             * <code>Map</code>. The keys of the map should be instances
0765:             * of <code>String</code> and the values one of the following
0766:             * classes.<br/>
0767:             * <ul>
0768:             * <li>org.wings.util.SStringBuilder</li>
0769:             * <li>java.lang.String</li>
0770:             * <li>java.awt.Color</li>
0771:             * <li>org.wings.Renderable</li>
0772:             * <li>java.lang.Integer</li>
0773:             * <li>org.wings.SDimension</li>
0774:             * </ul>
0775:             *
0776:             * @param d          The device to print the <b>optional</b> attributes.
0777:             * @param attributes The <b>optional</b> attributes. The key is the attribute
0778:             *                   name and the value is the attribute value.
0779:             * @throws IOException The exception maybe thrown if an error occurs
0780:             *                     while trying to write to device.
0781:             */
0782:            public static void optAttributes(final Device d,
0783:                    final Map attributes) throws IOException {
0784:                if (attributes != null) {
0785:                    for (final Object o : attributes.entrySet()) {
0786:                        Map.Entry entries = (Map.Entry) o;
0787:
0788:                        Object key = entries.getKey();
0789:                        if (key instanceof  String) {
0790:                            String attr = (String) key;
0791:
0792:                            Object value = entries.getValue();
0793:                            if (value instanceof  SStringBuilder) {
0794:                                Utils.optAttribute(d, attr,
0795:                                        (SStringBuilder) value);
0796:                            } else if (value instanceof  String) {
0797:                                Utils.optAttribute(d, attr, (String) value);
0798:                            } else if (value instanceof  Color) {
0799:                                Utils.optAttribute(d, attr, (Color) value);
0800:                            } else if (value instanceof  Renderable) {
0801:                                Utils.optAttribute(d, attr, (Renderable) value);
0802:                            } else if (value instanceof  Integer) {
0803:                                Utils.optAttribute(d, attr, ((Integer) value)
0804:                                        .intValue());
0805:                            } else if (value instanceof  SDimension) {
0806:                                Utils.optAttribute(d, attr, (SDimension) value);
0807:                            }
0808:                        }
0809:                    }
0810:                }
0811:            }
0812:
0813:            /**
0814:             * writes the given java.awt.Color to the device. Speed optimized;
0815:             * character conversion avoided.
0816:             */
0817:            public static void write(final Device d, final Color c)
0818:                    throws IOException {
0819:                d.print('#');
0820:                int rgb = (c == null) ? 0 : c.getRGB();
0821:                int mask = 0xf00000;
0822:                for (int bitPos = 20; bitPos >= 0; bitPos -= 4) {
0823:                    d.print(hexDigits[(rgb & mask) >>> bitPos]);
0824:                    mask >>>= 4;
0825:                }
0826:            }
0827:
0828:            /**
0829:             * writes anything Renderable
0830:             */
0831:            public static void write(final Device d, final Renderable r)
0832:                    throws IOException {
0833:                if (r == null) {
0834:                    return;
0835:                }
0836:                r.write(d);
0837:            }
0838:
0839:            /*
0840:             * testing purposes.
0841:             */
0842:            public static void main(String argv[]) throws Exception {
0843:                Color c = new Color(255, 254, 7);
0844:                Device d = new org.wings.io.StringBuilderDevice(1024);
0845:                write(d, c);
0846:                quote(d, "\nThis is a <abc> string \"; foo & sons\nmoin", true,
0847:                        false, false);
0848:                d.print(String.valueOf(-42));
0849:                d.print(String.valueOf(Integer.MIN_VALUE));
0850:
0851:                write(d, "hello test&nbsp;\n");
0852:                write(d, "<html>hallo test&nbsp;\n");
0853:
0854:                d = new org.wings.io.NullDevice();
0855:                long start = System.currentTimeMillis();
0856:                for (int i = 0; i < 1000000; ++i) {
0857:                    quote(d, "this is a little & foo", true, false, false);
0858:                }
0859:                System.out.println("took: "
0860:                        + (System.currentTimeMillis() - start) + "ms");
0861:            }
0862:
0863:            /**
0864:             * Helper method for CGs to print out debug information in output stream.
0865:             * If {@link #PRINT_DEBUG} prints the passed string and returns the current {@link Device}.
0866:             * In other case omits ouput and returns a {@link NullDevice}
0867:             *
0868:             * @param d The original device
0869:             * @return The original device or a {@link NullDevice}
0870:             */
0871:            public static Device printDebug(final Device d, final char[] s)
0872:                    throws IOException {
0873:                if (PRINT_DEBUG) {
0874:                    return d.print(s);
0875:                } else {
0876:                    return d;
0877:                }
0878:            }
0879:
0880:            /**
0881:             * Helper method for CGs to print out debug information in output stream.
0882:             * If {@link #PRINT_DEBUG} prints the passed string and returns the current {@link Device}.
0883:             * In other case omits ouput and returns a {@link NullDevice}
0884:             *
0885:             * @param d The original device
0886:             * @return The original device or a {@link NullDevice}
0887:             */
0888:            public static Device printDebug(final Device d, final String s)
0889:                    throws IOException {
0890:                if (PRINT_DEBUG) {
0891:                    return d.print(s);
0892:                } else {
0893:                    return d;
0894:                }
0895:            }
0896:
0897:            /**
0898:             * Prints a hierarchical idented newline if debug mode is enabled.
0899:             * {@link #printNewline(org.wings.io.Device, org.wings.SComponent)}
0900:             */
0901:            public static Device printDebugNewline(Device d,
0902:                    SComponent currentComponent) throws IOException {
0903:                if (PRINT_DEBUG) {
0904:                    return printNewline(d, currentComponent);
0905:                } else {
0906:                    return NullDevice.DEFAULT;
0907:                }
0908:            }
0909:
0910:            /**
0911:             * Prints a hierarchical idented newline. For each surrounding container of the passed component one ident level.
0912:             */
0913:            public static Device printNewline(final Device d,
0914:                    SComponent currentComponent) throws IOException {
0915:                // special we save every ms handling for holger ;-)
0916:                /* (OL) I took out the test for PRINT_DEBUG, since
0917:                 * sometimes we just need newlines (example tabbedPane)
0918:                 * I hope Holger doesn't need that microsecond ;)
0919:                 */
0920:                if (currentComponent == null) {
0921:                    return d;
0922:                }
0923:                d.print('\n');
0924:
0925:                if (PRINT_PRETTY) {
0926:                    SContainer current = currentComponent.getParent();
0927:                    while (current != null) {
0928:                        d.print('\t');
0929:                        current = current.getParent();
0930:                    }
0931:                }
0932:                return d;
0933:            }
0934:
0935:            /**
0936:             * Prints a hierarchical idented newline. For each surrounding container of the passed component one ident level.
0937:             */
0938:            public static Device printNewline(final Device d,
0939:                    SComponent currentComponent, int offset) throws IOException {
0940:                d.print('\n');
0941:                if (PRINT_PRETTY) {
0942:                    while (currentComponent != null) {
0943:                        d.print('\t');
0944:                        currentComponent = currentComponent.getParent();
0945:                    }
0946:                }
0947:
0948:                while (offset > 0) {
0949:                    d.print('\t');
0950:                    offset--;
0951:                }
0952:                return d;
0953:            }
0954:
0955:            /**
0956:             * loads a script from disk through the classloader.
0957:             *
0958:             * @param path the path where the script can be found
0959:             * @return the script as a String
0960:             */
0961:            public static String loadScript(final String path) {
0962:                InputStream in = null;
0963:                BufferedReader reader = null;
0964:
0965:                try {
0966:                    in = Thread.currentThread().getContextClassLoader()
0967:                            .getResourceAsStream(path);
0968:                    reader = new BufferedReader(new InputStreamReader(in));
0969:                    SStringBuilder buffer = new SStringBuilder();
0970:                    String line;
0971:                    while ((line = reader.readLine()) != null) {
0972:                        buffer.append(line).append("\n");
0973:                    }
0974:                    buffer.append("\n");
0975:
0976:                    return buffer.toString();
0977:                } catch (Exception e) {
0978:                    log.warn("Unable to load script '" + path + "'", e);
0979:                    return "";
0980:                } finally {
0981:                    try {
0982:                        in.close();
0983:                    } catch (Exception ign) {
0984:                    }
0985:                    try {
0986:                        reader.close();
0987:                    } catch (Exception ign1) {
0988:                    }
0989:                }
0990:            }
0991:
0992:            /**
0993:             * prints a String. Substitutes spaces with nbsp's
0994:             */
0995:            public static String nonBreakingSpaces(String text) {
0996:                return text.replace(' ', '\u00A0');
0997:            }
0998:
0999:            /**
1000:             * Takes a string, tokenizes it and appends the wordSuffix on each word.
1001:             *
1002:             * @param words      A list of words, may be <code>null</code>.
1003:             * @param wordSuffix A suffix string to append to each word
1004:             * @return modified string (<code>i.e. "slayout myclass","_box"</code>  gets <code>"slayout_box myclass_box"</code>).
1005:             */
1006:            public static String appendSuffixesToWords(String words,
1007:                    String wordSuffix) {
1008:                if (words == null || words.length() == 0 || wordSuffix == null
1009:                        || wordSuffix.length() == 0) {
1010:                    return words;
1011:                }
1012:
1013:                // trivial case
1014:                if (words.indexOf(' ') < 0) {
1015:                    return words + wordSuffix;
1016:                }
1017:
1018:                // more than one word
1019:                StringTokenizer tokenizer = new StringTokenizer(words, " ");
1020:                SStringBuilder returnValue = new SStringBuilder();
1021:                while (tokenizer.hasMoreElements()) {
1022:                    returnValue.append(tokenizer.nextToken())
1023:                            .append(wordSuffix);
1024:                    if (tokenizer.hasMoreTokens()) {
1025:                        returnValue.append(' ');
1026:                    }
1027:                }
1028:
1029:                return returnValue.toString();
1030:            }
1031:
1032:            /**
1033:             * Prepends the component style class set on the component to the existing style string.
1034:             *
1035:             * @param component   Component may be <code>null</code> and may have a <code>null</code> style string.
1036:             * @param styleString The style string to append
1037:             */
1038:            public static SStringBuilder joinStyles(final SComponent component,
1039:                    final SStringBuilder styleString) {
1040:                if (component != null && component.getStyle() != null) {
1041:                    if (styleString != null) {
1042:                        styleString.insert(0, " ");
1043:                        styleString.insert(0, component.getStyle());
1044:                        return styleString;
1045:                    } else {
1046:                        return new SStringBuilder(component.getStyle());
1047:                    }
1048:                } else {
1049:                    return styleString;
1050:                }
1051:            }
1052:
1053:            /**
1054:             * Prepends the component style class set on the component to the existing style string.
1055:             *
1056:             * @param component   Component may be <code>null</code> and may have a <code>null</code> style string.
1057:             * @param styleString The style string to append
1058:             */
1059:            public static String joinStyles(final SComponent component,
1060:                    final String styleString) {
1061:                if (component != null && component.getStyle() != null) {
1062:                    if (styleString != null) {
1063:                        return component.getStyle() + " " + styleString;
1064:                    } else {
1065:                        return component.getStyle();
1066:                    }
1067:                } else {
1068:                    return styleString != null ? styleString : "";
1069:                }
1070:            }
1071:
1072:            public static void printButtonStart(Device device,
1073:                    SComponent eventTarget, String eventValue, boolean b,
1074:                    boolean showAsFormComponent) throws IOException {
1075:                printButtonStart(device, eventTarget, eventValue, b,
1076:                        showAsFormComponent, null);
1077:            }
1078:
1079:            public static void printButtonStart(final Device device,
1080:                    final SComponent component, final String eventValue,
1081:                    final boolean enabled, final boolean formComponent,
1082:                    String cssClassName) throws IOException {
1083:                if (enabled) {
1084:                    device.print("<a href=\"#\"");
1085:                    printClickability(device, component, eventValue, enabled,
1086:                            formComponent);
1087:                } else {
1088:                    device.print("<span");
1089:                }
1090:
1091:                Utils.optAttribute(device, "class", cssClassName);
1092:            }
1093:
1094:            public static void printButtonEnd(final Device device,
1095:                    final boolean enabled) throws IOException {
1096:                if (enabled)
1097:                    device.print("</a>");
1098:                else
1099:                    device.print("</span>");
1100:            }
1101:
1102:            public static void printClickability(final Device device,
1103:                    final SComponent component, final String eventValue,
1104:                    final boolean enabled, final boolean formComponent)
1105:                    throws IOException {
1106:                if (enabled) {
1107:                    // Render onclick JS listeners
1108:                    device.print(" onclick=\"wingS.request.sendEvent(event,");
1109:                    device.print(formComponent);
1110:                    device.print(',');
1111:                    device.print(!component.isReloadForced());
1112:                    device.print(",'");
1113:                    device.print(Utils.event(component));
1114:                    device.print("','");
1115:                    if (eventValue != null) {
1116:                        device.print(eventValue);
1117:                    }
1118:                    device.print('\'');
1119:                    device.print(collectJavaScriptListenerCode(component,
1120:                            JavaScriptEvent.ON_CLICK));
1121:                    device.print("); return false;\"");
1122:
1123:                    // Render remaining JS listeners
1124:                    Utils.writeEvents(device, component, EXCLUDE_ON_CLICK);
1125:                }
1126:            }
1127:
1128:            /**
1129:             * Renders inline the javascript code attached to the passed javascipt event type
1130:             * on the component. Used to allow usage of javascript events by the framework
1131:             * as well as by the application itself.
1132:             * <p> For an example: See the <code>wingS.request.sendEvent()</code>.
1133:             *
1134:             * @param component           The component wearing the event handler
1135:             * @param javascriptEventType the event type declared in {@link JavaScriptEvent}
1136:             * @return javascript code fragment n the form of <code>,new Array(function(){...},function(){...})</code>
1137:             */
1138:            public static String collectJavaScriptListenerCode(
1139:                    final SComponent component, final String javascriptEventType) {
1140:                SStringBuilder script = null;
1141:                JavaScriptListener[] eventListeners = getEventTypeListeners(
1142:                        component, javascriptEventType);
1143:                if (eventListeners != null && eventListeners.length > 0) {
1144:                    for (int i = 0; i < eventListeners.length; ++i) {
1145:                        if (eventListeners[i].getCode() != null) {
1146:                            if (script == null) {
1147:                                script = new SStringBuilder(64);
1148:                            }
1149:                            if (i > 0) {
1150:                                script.append(",");
1151:                            }
1152:                            script.append("function(){").append(
1153:                                    eventListeners[i].getCode()).append("}");
1154:                        }
1155:                    }
1156:                    if (script != null && script.length() > 0) {
1157:                        script.insert(0, ",new Array(");
1158:                        script.append(")");
1159:                    }
1160:                }
1161:                return script != null ? script.toString() : "";
1162:            }
1163:
1164:            /**
1165:             * @param button          The component wearing the event handler
1166:             * @param javaScriptEvent the event type declared in {@link JavaScriptEvent}
1167:             * @return The attached listeners to event type
1168:             */
1169:            private static JavaScriptListener[] getEventTypeListeners(
1170:                    final SComponent button, final String javaScriptEvent) {
1171:                ArrayList<JavaScriptListener> result = new ArrayList<JavaScriptListener>();
1172:                ScriptListener[] listeners = button.getScriptListeners();
1173:                for (ScriptListener listener : listeners) {
1174:                    if (listener instanceof  JavaScriptListener) {
1175:                        JavaScriptListener jsListener = (JavaScriptListener) listener;
1176:                        if (javaScriptEvent.equals(jsListener.getEvent()
1177:                                .toLowerCase())) {
1178:                            result.add(jsListener);
1179:                        }
1180:                    }
1181:                }
1182:                return result.toArray(new JavaScriptListener[result.size()]);
1183:            }
1184:
1185:            public static SStringBuilder inlineStyles(Style tabAreaStyle) {
1186:                if (tabAreaStyle != null) {
1187:                    SStringBuilder tabArea = new SStringBuilder();
1188:                    tabArea.append(tabAreaStyle.toString());
1189:                    return tabArea;
1190:                } else {
1191:                    return null;
1192:                }
1193:            }
1194:
1195:            /**
1196:             * @return true if current browser is microsoft exploder
1197:             */
1198:            public static boolean isMSIE(SComponent component) {
1199:                return component.getSession().getUserAgent().getBrowserType() == BrowserType.IE;
1200:            }
1201:
1202:            /**
1203:             * @return true if current browser is microsoft exploder
1204:             */
1205:            public static boolean isMSIE() {
1206:                return SessionManager.getSession().getUserAgent()
1207:                        .getBrowserType() == BrowserType.IE;
1208:            }
1209:
1210:            /**
1211:             * @param insets The inset param to test
1212:             * @return <code>true</code> if any valid inset greater zero is set
1213:             */
1214:            public static boolean hasInsets(Insets insets) {
1215:                return insets != null
1216:                        && (insets.top > 0 || insets.left > 0
1217:                                || insets.right > 0 || insets.bottom > 0);
1218:            }
1219:
1220:            public static void optFullSize(Device device, SComponent component)
1221:                    throws IOException {
1222:                SDimension dim = component.getPreferredSize();
1223:                if (dim != null) {
1224:                    String width = dim.getWidth();
1225:                    boolean widthSet = width != null && !"".equals(width)
1226:                            && !SDimension.AUTO.equals(width);
1227:                    String height = dim.getHeight();
1228:                    boolean heightSet = height != null && !"".equals(height)
1229:                            && !SDimension.AUTO.equals(height);
1230:                    SStringBuilder style = new SStringBuilder();
1231:                    if (widthSet) {
1232:                        style.append("width:100%;");
1233:                    }
1234:                    if (heightSet) {
1235:                        style.append("height:100%;");
1236:                    }
1237:                    if (style.length() > 0)
1238:                        Utils.optAttribute(device, "style", style);
1239:                }
1240:            }
1241:
1242:            /**
1243:             * Converts a hgap/vgap in according inline css padding style.
1244:             *
1245:             * @param insets The insets to generate CSS padding declaration
1246:             * @return Empty or filled stringbuffer with padding declaration
1247:             */
1248:            public static SStringBuilder createInlineStylesForInsets(
1249:                    Insets insets) {
1250:                return createInlineStylesForInsets(new SStringBuilder(), insets);
1251:            }
1252:
1253:            /**
1254:             * Converts a hgap/vgap in according inline css padding style.
1255:             *
1256:             * @param device Appender to append inset style.
1257:             * @param insets The insets to generate CSS padding declaration
1258:             * @return Empty or filled stringbuffer with padding declaration
1259:             */
1260:            public static Device printInlineStylesForInsets(
1261:                    final Device device, final Insets insets)
1262:                    throws IOException {
1263:                if (insets != null
1264:                        && (insets.top > 0 || insets.left > 0
1265:                                || insets.right > 0 || insets.bottom > 0)) {
1266:                    if (insets.top == insets.left
1267:                            && insets.left == insets.right
1268:                            && insets.right == insets.bottom) {
1269:                        device.print(" style=\"padding:").print(insets.top)
1270:                                .print("px;\"");
1271:                    } else if (insets.top == insets.bottom
1272:                            && insets.left == insets.right) {
1273:                        device.print(" style=\"padding:").print(insets.top)
1274:                                .print("px ").print(insets.right)
1275:                                .print("px;\"");
1276:                    } else {
1277:                        device.print(" style=\"padding:").print(insets.top)
1278:                                .print("px ").print(insets.right).print("px ")
1279:                                .print(insets.bottom).print("px ").print(
1280:                                        insets.left).print("px;\"");
1281:                    }
1282:                }
1283:                return device;
1284:            }
1285:
1286:            /**
1287:             * Converts a hgap/vgap in according inline css padding style.
1288:             *
1289:             * @param styles Appender to append inset style.
1290:             * @param insets The insets to generate CSS padding declaration
1291:             * @return Empty or filled stringbuffer with padding declaration
1292:             */
1293:            public static SStringBuilder createInlineStylesForInsets(
1294:                    SStringBuilder styles, Insets insets) {
1295:                if (insets != null
1296:                        && (insets.top > 0 || insets.left > 0
1297:                                || insets.right > 0 || insets.bottom > 0)) {
1298:                    if (insets.top == insets.left
1299:                            && insets.left == insets.right
1300:                            && insets.right == insets.bottom) {
1301:                        styles.append("padding:").append(insets.top).append(
1302:                                "px;");
1303:                    } else if (insets.top == insets.bottom
1304:                            && insets.left == insets.right) {
1305:                        styles.append("padding:").append(insets.top).append(
1306:                                "px ").append(insets.right).append("px;");
1307:                    } else {
1308:                        styles.append("padding:").append(insets.top).append(
1309:                                "px ").append(insets.right).append("px ")
1310:                                .append(insets.bottom).append("px ").append(
1311:                                        insets.left).append("px;");
1312:                    }
1313:                }
1314:                return styles;
1315:            }
1316:
1317:            public static int calculateHorizontalOversize(SComponent component,
1318:                    boolean percentageUnitOnly) {
1319:                if (component != null && isMSIE(component)
1320:                        && component instanceof  STextComponent) {
1321:                    SDimension preferredSize = component.getPreferredSize();
1322:                    if (preferredSize != null) {
1323:                        String widthUnit = preferredSize.getWidthUnit();
1324:                        if (!SDimension.AUTO.equals(widthUnit)) {
1325:                            if (percentageUnitOnly && !"%".equals(widthUnit))
1326:                                return 0;
1327:
1328:                            SAbstractBorder border = (SAbstractBorder) component
1329:                                    .getBorder();
1330:                            if (border != SDefaultBorder.INSTANCE) {
1331:                                int oversize = 0;
1332:                                int thickness = border
1333:                                        .getThickness(SConstants.LEFT);
1334:                                if (thickness != -1)
1335:                                    oversize += thickness;
1336:                                thickness = border
1337:                                        .getThickness(SConstants.RIGHT);
1338:                                if (thickness != -1)
1339:                                    oversize += thickness;
1340:                                final Insets insets = border.getInsets();
1341:                                if (insets != null) {
1342:                                    oversize += insets.left + insets.right;
1343:                                }
1344:                                return oversize;
1345:                            } else {
1346:                                return ((Integer) component
1347:                                        .getClientProperty("horizontalOversize"))
1348:                                        .intValue();
1349:                            }
1350:                        }
1351:                    }
1352:                }
1353:                return 0;
1354:            }
1355:
1356:            public static int calculateVerticalOversize(SComponent component,
1357:                    boolean percentageUnitOnly) {
1358:                if (component != null && isMSIE(component)
1359:                        && component instanceof  STextComponent) {
1360:                    SDimension preferredSize = component.getPreferredSize();
1361:                    if (preferredSize != null) {
1362:                        String heightUnit = preferredSize.getHeightUnit();
1363:                        if (!SDimension.AUTO.equals(heightUnit)) {
1364:                            if (percentageUnitOnly && !"%".equals(heightUnit))
1365:                                return 0;
1366:
1367:                            SAbstractBorder border = (SAbstractBorder) component
1368:                                    .getBorder();
1369:                            if (border != SDefaultBorder.INSTANCE) {
1370:                                int oversize = 0;
1371:                                int thickness = border
1372:                                        .getThickness(SConstants.TOP);
1373:                                if (thickness != -1)
1374:                                    oversize += thickness;
1375:                                thickness = border
1376:                                        .getThickness(SConstants.BOTTOM);
1377:                                if (thickness != -1)
1378:                                    oversize += thickness;
1379:                                final Insets insets = border.getInsets();
1380:                                if (insets != null) {
1381:                                    oversize += insets.top + insets.bottom;
1382:                                }
1383:                                return oversize;
1384:                            } else {
1385:                                return 4;
1386:                            }
1387:                        }
1388:                    }
1389:                }
1390:                return 0;
1391:            }
1392:
1393:            /**
1394:             * Lookup keys for wings resources
1395:             */
1396:            public static final String JS_WINGS_ALL = "JS.wingsAll";
1397:            public static final String JS_WINGS_ALL_DEBUG = "JS.wingsAllDebug";
1398:
1399:            /**
1400:             * Lookup keys for yui resources
1401:             */
1402:            public static final String JS_YUI_ANIMATION = "JS.yuiAnimation";
1403:            // CSS: public static final String CSS_YUI_ASSETS_... = "CSS.yuiAssets...";
1404:            public static final String CSS_YUI_ASSETS_CALENDAR = "CSS.yuiAssetsCalendar";
1405:            public static final String CSS_YUI_ASSETS_CONTAINER = "CSS.yuiAssetsContainer";
1406:            public static final String IMG_YUI_ASSETS_SPRITE = "IMG.yuiAssetsSprite";
1407:            public static final String JS_YUI_AUTOCOMPLETE = "JS.yuiAutocomplete";
1408:            // CSS: public static final String CSS_YUI_BASE = "CSS.yuiBase";
1409:            public static final String JS_YUI_BUTTON = "JS.yuiButton";
1410:            public static final String JS_YUI_CALENDAR = "JS.yuiCalendar";
1411:            // Experimental: public static final String JS_YUI_CHARTS = "JS.yuiCharts";
1412:            public static final String JS_YUI_COLORPICKER = "JS.yuiColorpicker";
1413:            public static final String JS_YUI_CONNECTION = "JS.yuiConnection";
1414:            public static final String JS_YUI_CONTAINER = "JS.yuiContainer";
1415:            public static final String JS_YUI_CONTAINER_CORE = "JS.yuiContainerCore";
1416:            // Beta: public static final String JS_YUI_COOKIE = "JS.yuiCookie";
1417:            // Beta: public static final String JS_YUI_DATASOURCE = "JS.yuiDatasource";
1418:            // Beta: public static final String JS_YUI_DATATABLE = "JS.yuiDatatable";
1419:            public static final String JS_YUI_DOM = "JS.yuiDom";
1420:            public static final String JS_YUI_DRAGDROP = "JS.yuiDragdrop";
1421:            // Beta: public static final String JS_YUI_EDITOR = "JS.yuiEditor";
1422:            // Beta: public static final String JS_YUI_EDITOR_SIMPLE = "JS.yuiEditorSimple";
1423:            // Beta: public static final String JS_YUI_ELEMENT = "JS.yuiElement";
1424:            public static final String JS_YUI_EVENT = "JS.yuiEvent";
1425:            // CSS: public static final String CSS_YUI_FONTS = "CSS.yuiFonts";
1426:            public static final String JS_YUI_GET = "JS.yuiGet";
1427:            // CSS: public static final String CSS_YUI_GRIDS = "CSS.yuiGrids";
1428:            public static final String JS_YUI_HISTORY = "JS.yuiHistory";
1429:            // Beta: public static final String JS_YUI_IMAGECROPPER = "JS.yuiImagecropper";
1430:            public static final String JS_YUI_IMAGELOADER = "JS.yuiImageloader";
1431:            public static final String JS_YUI_JSON = "JS.yuiJson";
1432:            // Beta: public static final String JS_YUI_LAYOUT = "JS.yuiLayout";
1433:            public static final String JS_YUI_LOGGER = "JS.yuiLogger";
1434:            public static final String JS_YUI_MENU = "JS.yuiMenu";
1435:            // Beta: public static final String JS_YUI_PROFILER = "JS.yuiProfiler";
1436:            // Beta: public static final String JS_YUI_PROFILERVIEWER = "JS.yuiProfilerviewer";
1437:            // CSS: public static final String CSS_YUI_RESET = "CSS.yuiReset";
1438:            // CSS: public static final String CSS_YUI_RESET_FONTS = "CSS.yuiResetFonts";
1439:            // CSS: public static final String CSS_YUI_RESET_FONTS_GRIDS = "CSS.yuiResetFontsGrids";
1440:            // Beta: public static final String JS_YUI_RESIZE = "JS.yuiResize";
1441:            // Beta: public static final String JS_YUI_SELECTOR = "JS.yuiSelector";
1442:            public static final String JS_YUI_SLIDER = "JS.yuiSlider";
1443:            public static final String JS_YUI_TABVIEW = "JS.yuiTabview";
1444:            public static final String JS_YUI_TREEVIEW = "JS.yuiTreeview";
1445:            // Experimental: public static final String JS_YUI_UPLOADER = "JS.yuiUploader";
1446:            public static final String JS_YUI_UTILITIES = "JS.yuiUtilities";
1447:            public static final String JS_YUI_YAHOO = "JS.yuiYahoo";
1448:            public static final String JS_YUI_YAHOO_DOM_EVENT = "JS.yuiYahooDomEvent";
1449:            // Beta: public static final String JS_YUI_YUILOADER = "JS.yuiYuiloader";
1450:            public static final String JS_YUI_YUILOADER_DOM_EVENT = "JS.yuiYuiloaderDomEvent";
1451:            public static final String JS_YUI_TEST = "JS.yuiYuitest";
1452:            public static final String JS_YUI_TEST_CORE = "JS.yuiYuitestCore";
1453:
1454:            public static final String JS_YUI_ANIMATION_DEBUG = "JS.yuiAnimationDebug";
1455:            public static final String JS_YUI_CONNECTION_DEBUG = "JS.yuiConnectionDebug";
1456:            public static final String JS_YUI_CONTAINER_DEBUG = "JS.yuiContainerDebug";
1457:            public static final String JS_YUI_DOM_DEBUG = "JS.yuiDomDebug";
1458:            public static final String JS_YUI_DRAGDROP_DEBUG = "JS.yuiDragdropDebug";
1459:            public static final String JS_YUI_EVENT_DEBUG = "JS.yuiEventDebug";
1460:            public static final String JS_YUI_ELEMENT_DEBUG = "JS.yuiElementDebug";
1461:            public static final String JS_YUI_YAHOO_DEBUG = "JS.yuiYahooDebug";
1462:
1463:            /**
1464:             * Lookup keys for other resources
1465:             */
1466:            public static final String JS_ETC_MENU = "JS.etcMenu";
1467:            public static final String JS_ETC_POPUP = "JS.etcPopup";
1468:            public static final String JS_ETC_WZ_TOOLTIP = "JS.etcWzTooltip";
1469:
1470:            public static final String JS_DEBUG_FIREBUGLITE = "JS.debugFirebugLite";
1471:            public static final String HTML_DEBUG_FIREBUGLITE = "HTML.debugFirebugLite";
1472:            public static final String CSS_DEBUG_FIREBUGLITE = "CSS.debugFirebugLite";
1473:            public static final String IMG_DEBUG_FIREBUGLITE_ERROR = "IMG.debugFirebugLiteError";
1474:            public static final String IMG_DEBUG_FIREBUGLITE_WARN = "IMG.debugFirebugLiteWarn";
1475:            public static final String IMG_DEBUG_FIREBUGLITE_INFO = "IMG.debugFirebugLiteInfo";
1476:
1477:            /**
1478:             * Load a Javascript library that comes with wingS by a property. Check <code>JS_XXX</code> constants.
1479:             * @param jsResourceProperty A property lookup key, preferably by a constant in this utility class
1480:             * @return A script reference to the desired script addable as header
1481:             */
1482:            public static Script createExternalizedJSHeaderFromProperty(
1483:                    String jsResourceProperty) {
1484:                String jsClassPath = (String) ResourceManager.getObject(
1485:                        jsResourceProperty, String.class);
1486:                return createExternalizedJSHeader(jsClassPath);
1487:            }
1488:
1489:            /**
1490:             * Load a Javascript library from the classpath.
1491:             * @param jsClassPath A classpath to the .js-file
1492:             * @return A script reference to the desired script addable as header
1493:             */
1494:            public static Script createExternalizedJSHeader(String jsClassPath) {
1495:                ClassPathResource res = new ClassPathJavascriptResource(
1496:                        jsClassPath, HEADER_LOADED_CALLBACK);
1497:                ExternalizeManager extMgr = SessionManager.getSession()
1498:                        .getExternalizeManager();
1499:                String jsUrl = extMgr.externalize(res,
1500:                        ExternalizeManager.GLOBAL);
1501:                return new JavaScriptHeader(new SessionResource(jsUrl));
1502:            }
1503:
1504:            /**
1505:             * Load a Stylesheet document that comes with wingS by a property. Check <code>CSS_XXX</code> constants.
1506:             * @param cssResourceProperty A property lookup key, preferably by a constant in this utility class
1507:             * @return A Link reference to the desired stylesheet addable as header
1508:             */
1509:            public static Link createExternalizedCSSHeaderFromProperty(
1510:                    String cssResourceProperty) {
1511:                String cssClassPath = (String) ResourceManager.getObject(
1512:                        cssResourceProperty, String.class);
1513:                return createExternalizedCSSHeader(cssClassPath);
1514:            }
1515:
1516:            /**
1517:             * Load a Stylesheet document from the classpath.
1518:             * @param cssClassPath A classpath to the .css-file
1519:             * @return A Link reference to the desired stylesheet addable as header
1520:             */
1521:            public static Link createExternalizedCSSHeader(String cssClassPath) {
1522:                ClassPathResource res = new ClassPathResource(cssClassPath,
1523:                        "text/css");
1524:                ExternalizeManager extMgr = SessionManager.getSession()
1525:                        .getExternalizeManager();
1526:                String cssUrl = extMgr.externalize(res,
1527:                        ExternalizeManager.GLOBAL);
1528:                return new StyleSheetHeader(new SessionResource(cssUrl));
1529:            }
1530:
1531:            public static Renderable listToJsArray(List list) {
1532:                return new JSArray(list);
1533:            }
1534:
1535:            public static Renderable mapToJsObject(Map map) {
1536:                return new JSObject(map);
1537:            }
1538:
1539:            private static final char[] BACKSLASH_N = "\\n".toCharArray();
1540:            private static final char[] BACKSLASH_R = "\\r".toCharArray();
1541:            private static final char[] BACKSLASH_T = "\\t".toCharArray();
1542:
1543:            public static void encodeJS(Device d, Object o) throws IOException {
1544:                // The common cases that never need escaping.
1545:                if (o == null) {
1546:                    d.print("null");
1547:                    return;
1548:                }
1549:                if (o instanceof  Number || o instanceof  Boolean) {
1550:                    d.print(o.toString());
1551:                    return;
1552:                }
1553:                if (o instanceof  Renderable) {
1554:                    ((Renderable) o).write(d);
1555:                    return;
1556:                }
1557:
1558:                // Using an Objects toString() method to JSON-serialize them is DIRTY.
1559:                assert (o instanceof  String) : " never rely on toString() to serialize "
1560:                        + "an object in JSON! Implement org.wings.Renderable instead. "
1561:                        + "Object was a " + o.getClass() + ": >" + o + "<";
1562:
1563:                d.print('\'');
1564:                final String stringRep = o.toString();
1565:                final char chars[] = stringRep.toCharArray();
1566:                char c;
1567:                int last = 0;
1568:                for (int pos = 0; pos < chars.length; ++pos) {
1569:                    c = chars[pos];
1570:                    switch (c) {
1571:                    case '\'':
1572:                        d.print(chars, last, (pos - last));
1573:                        d.print('\\');
1574:                        last = pos; // next starts with single quote
1575:                        break;
1576:                    case '\\':
1577:                        d.print(chars, last, (pos - last));
1578:                        d.print('\\');
1579:                        last = pos; // next starts with backslash
1580:                        break;
1581:                    case '\b':
1582:                        d.print(chars, last, (pos - last));
1583:                        d.print("\\b");
1584:                        last = pos + 1;
1585:                        break;
1586:                    case '\f':
1587:                        d.print(chars, last, (pos - last));
1588:                        d.print("\\f");
1589:                        last = pos + 1;
1590:                        break;
1591:                    case '\n':
1592:                        d.print(chars, last, (pos - last));
1593:                        d.print(BACKSLASH_N);
1594:                        last = pos + 1;
1595:                        break;
1596:                    case '\r':
1597:                        d.print(chars, last, (pos - last));
1598:                        d.print(BACKSLASH_R);
1599:                        last = pos + 1;
1600:                        break;
1601:                    case '\t':
1602:                        d.print(chars, last, (pos - last));
1603:                        d.print(BACKSLASH_T);
1604:                        last = pos + 1;
1605:                        break;
1606:                    case '/': // Regular expressions start with a slash.
1607:                        d.print(chars, last, (pos - last));
1608:                        d.print('\\');
1609:                        last = pos; // next starts with slash.
1610:                        break;
1611:                    default:
1612:                        if ((c >= '\u0000' && c <= '\u001F') || c >= '\u007F') {
1613:                            d.print(chars, last, pos - last);
1614:                            final String hex = Integer.toHexString(c);
1615:                            d.print("\\u");
1616:                            for (int j = 4 - hex.length(); j > 0; --j) {
1617:                                d.print('0');
1618:                            }
1619:                            d.print(hex);
1620:                            last = pos + 1;
1621:                        }
1622:                    }
1623:                }
1624:                d.print(chars, last, chars.length - last);
1625:                d.print('\'');
1626:            }
1627:
1628:            public static void writeAllAttributes(Device device,
1629:                    SComponent component) throws IOException {
1630:                optAttribute(device, "class", component.getStyle());
1631:                optAttribute(device, "id", component.getName());
1632:                optAttribute(device, "style", getInlineStyles(component));
1633:
1634:                if (component instanceof  LowLevelEventListener) {
1635:                    optAttribute(device, "eid", component.getLowLevelEventId());
1636:                }
1637:
1638:                // Tooltip handling
1639:                writeTooltipMouseOver(device, component);
1640:
1641:                // Component popup menu
1642:                writeContextMenu(device, component);
1643:            }
1644:
1645:            public static String getInlineStyles(SComponent component) {
1646:                // write inline styles
1647:                final SStringBuilder builder = new SStringBuilder();
1648:
1649:                appendCSSInlineSize(builder, component);
1650:
1651:                // Determine Style String
1652:                Style allStyle = component
1653:                        .getDynamicStyle(SComponent.SELECTOR_ALL);
1654:                if (component instanceof  SAbstractIconTextCompound
1655:                        && ((SAbstractIconTextCompound) component).isSelected()) {
1656:                    // present, SComponent.getDynamicStyle() always is instance of CSSStyle
1657:                    CSSStyle selectedStyle = (CSSStyle) component
1658:                            .getDynamicStyle(SAbstractIconTextCompound.SELECTOR_SELECTED);
1659:                    if (selectedStyle != null) {
1660:                        if (allStyle != null) {
1661:                            // make a copy to modify
1662:                            allStyle = new CSSStyle(SComponent.SELECTOR_ALL,
1663:                                    (CSSAttributeSet) allStyle);
1664:                            allStyle.putAll(selectedStyle);
1665:                        } else {
1666:                            allStyle = selectedStyle;
1667:                        }
1668:                    }
1669:                }
1670:                // Render Style string
1671:                if (allStyle != null)
1672:                    builder.append(allStyle.toString());
1673:
1674:                final SBorder border = component.getBorder();
1675:                if (border != null) {
1676:                    if (border.getAttributes() != null)
1677:                        builder.append(border.getAttributes().toString());
1678:                } else
1679:                    builder.append("border:none;padding:0px");
1680:
1681:                return builder.toString();
1682:            }
1683:
1684:            /**
1685:             * Write JS code for context menus. Common implementaton for MSIE and gecko.
1686:             */
1687:            public static void writeContextMenu(Device device,
1688:                    SComponent component) throws IOException {
1689:                final SPopupMenu menu = component.getComponentPopupMenu();
1690:                if (menu != null && menu.isEnabled()) {
1691:                    final String componentId = menu.getName();
1692:                    final String popupId = componentId + "_pop";
1693:                    device
1694:                            .print(" onContextMenu=\"return wpm_menuPopup(event, '");
1695:                    device.print(popupId);
1696:                    device
1697:                            .print("');\" onMouseDown=\"return wpm_menuPopup(event, '");
1698:                    device.print(popupId);
1699:                    device.print("');\"");
1700:                }
1701:            }
1702:
1703:            /**
1704:             * Write Tooltip code.
1705:             */
1706:            public static void writeTooltipMouseOver(Device device,
1707:                    SComponent component) throws IOException {
1708:                final String toolTipText = component != null ? component
1709:                        .getToolTipText() : null;
1710:                if (toolTipText != null && toolTipText.length() > 0) {
1711:                    device.print(" onmouseover=\"Tip('");
1712:                    quote(device, toolTipText, true, false, true);
1713:                    device.print("')\"");
1714:                }
1715:            }
1716:
1717:            public static final boolean hasDimension(final SComponent component) {
1718:                SDimension dim = component.getPreferredSize();
1719:                return dim != null
1720:                        && (dim.getHeightInt() != SDimension.AUTO_INT || dim
1721:                                .getWidthInt() != SDimension.AUTO_INT);
1722:            }
1723:
1724:            private static class JSArray implements  Renderable {
1725:                private final List list;
1726:
1727:                public JSArray(List list) {
1728:                    this .list = list;
1729:                }
1730:
1731:                public void write(Device d) throws IOException {
1732:                    d.print('[');
1733:                    final Iterator it = list.iterator();
1734:                    boolean isFirst = true;
1735:                    while (it.hasNext()) {
1736:                        if (!isFirst)
1737:                            d.print(',');
1738:                        encodeJS(d, it.next());
1739:                        isFirst = false;
1740:                    }
1741:                    d.print(']');
1742:                }
1743:
1744:                @Override
1745:                public String toString() {
1746:                    final StringBuilderDevice sb = new StringBuilderDevice(256);
1747:                    // Prevent this toString() be used for rendering, provide
1748:                    // info string to break that assumption.
1749:                    sb.print("JSArray.toString():");
1750:                    try {
1751:                        write(sb);
1752:                    } catch (IOException e) {
1753:                    }
1754:                    return sb.toString();
1755:                }
1756:
1757:                @Override
1758:                public boolean equals(Object object) {
1759:                    return list.equals(object);
1760:                }
1761:
1762:                @Override
1763:                public int hashCode() {
1764:                    return list.hashCode();
1765:                }
1766:            }
1767:
1768:            private static final class JSObject implements  Renderable {
1769:                private final Map map;
1770:
1771:                public JSObject(Map map) {
1772:                    this .map = map;
1773:                }
1774:
1775:                public void write(Device d) throws IOException {
1776:                    final Iterator it = map.entrySet().iterator();
1777:                    boolean isFirst = true;
1778:                    d.print('{');
1779:                    while (it.hasNext()) {
1780:                        if (!isFirst)
1781:                            d.print(',');
1782:                        Map.Entry entry = (Map.Entry) it.next();
1783:                        d.print('\'').print(entry.getKey().toString()).print(
1784:                                "':");
1785:                        encodeJS(d, entry.getValue());
1786:                        isFirst = false;
1787:                    }
1788:                    d.print('}');
1789:                }
1790:
1791:                @Override
1792:                // TODO: removeme
1793:                public String toString() {
1794:                    final StringBuilderDevice sb = new StringBuilderDevice(10);
1795:                    // Prevent this toString() be used for rendering, provide
1796:                    // info string to break that assumption.
1797:                    sb.print("JSObject.toString():");
1798:                    try {
1799:                        write(sb);
1800:                    } catch (IOException e) {
1801:                    }
1802:                    return sb.toString();
1803:                }
1804:
1805:                @Override
1806:                public boolean equals(Object object) {
1807:                    return map.equals(object);
1808:                }
1809:
1810:                @Override
1811:                public int hashCode() {
1812:                    return map.hashCode();
1813:                }
1814:            }
1815:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.