Source Code Cross Referenced for ContainerBox.java in  » IDE-Netbeans » visualweb.api.designer » org » netbeans » modules » visualweb » css2 » 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 » IDE Netbeans » visualweb.api.designer » org.netbeans.modules.visualweb.css2 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:        package org.netbeans.modules.visualweb.css2;
0042:
0043:        import org.netbeans.modules.visualweb.api.designer.cssengine.CssListValue;
0044:        import org.netbeans.modules.visualweb.api.designer.cssengine.CssProvider;
0045:        import org.netbeans.modules.visualweb.api.designer.cssengine.CssValue;
0046:        import org.netbeans.modules.visualweb.api.designer.markup.MarkupService;
0047:        import org.netbeans.modules.visualweb.designer.CssUtilities;
0048:        import java.awt.Color;
0049:        import java.awt.Font;
0050:        import java.awt.FontMetrics;
0051:        import java.awt.Graphics;
0052:        import java.awt.Point;
0053:        import java.awt.Rectangle;
0054:        import java.io.PrintStream;
0055:        import java.io.PrintWriter;
0056:        import java.util.ArrayList;
0057:        import java.util.Arrays;
0058:        import java.util.List;
0059:
0060:        import javax.swing.JViewport;
0061:
0062:        import org.openide.ErrorManager;
0063:        import org.w3c.dom.Element;
0064:        import org.w3c.dom.Node;
0065:        import org.w3c.dom.NodeList;
0066:
0067:        import org.netbeans.modules.visualweb.designer.DesignerUtils;
0068:        import org.netbeans.modules.visualweb.designer.WebForm;
0069:        import org.netbeans.modules.visualweb.api.designer.cssengine.XhtmlCss;
0070:        import org.netbeans.modules.visualweb.designer.html.HtmlTag;
0071:        import org.w3c.dom.Text;
0072:
0073:        // For CVS archaeology: This file used to be called org.netbeans.modules.visualweb.css2.CssContainerBox
0074:
0075:        /**
0076:         * A CSS box which can hold children. Also a box which performs Css Layout!
0077:         * @todo I'm handling inline parents (e.g. <span>) and block parents
0078:         * (e.g. <div>, <p>, ...) differently. Perhaps instead of these if's in various
0079:         * places, make separate CssInlineContainerBox and CssBlockContainer box classes
0080:         * implementing the different semantics? (And a common parent for things like
0081:         * defining the box list field.)
0082:         *
0083:         * @author Tor Norbye
0084:         */
0085:        public class ContainerBox extends CssBox {
0086:            /** @todo Given that I support CSS2 whitespace handling now, shouldn't I nuke this flag? */
0087:            static final boolean COLLAPSE = true;
0088:            static Rectangle sharedClipRect = new Rectangle();
0089:            BoxList boxes;
0090:            protected boolean grid = false;
0091:            protected boolean clipOverflow;
0092:
0093:            public ContainerBox(WebForm webform, Element element,
0094:                    BoxType boxType, boolean inline, boolean replaced) {
0095:                super (webform, element, boxType, inline, replaced);
0096:            }
0097:
0098:            protected void initialize() {
0099:                super .initialize();
0100:                initializeGrid();
0101:
0102:                // Initialize overflow property
0103:                Element element = getElement();
0104:                if (element != null) {
0105:                    //            Value val = CssLookup.getValue(element, XhtmlCss.OVERFLOW_INDEX);
0106:                    CssValue cssValue = CssProvider.getEngineService()
0107:                            .getComputedValueForElement(element,
0108:                                    XhtmlCss.OVERFLOW_INDEX);
0109:
0110:                    //            if (val != CssValueConstants.VISIBLE_VALUE) {
0111:                    if (!CssProvider.getValueService().isVisibleValue(cssValue)) {
0112:                        clipOverflow = true;
0113:                    }
0114:                }
0115:            }
0116:
0117:            /** Return true iff the given box is "opaque", e.g. paints its own
0118:             * contents, in which case we don't want to for example make it paint
0119:             * its own background to erase grid dots underneath
0120:             */
0121:            protected boolean isOpaqueBox() {
0122:                return false;
0123:            }
0124:
0125:            /** Return true iff this box is "on top of" a container with an
0126:             * image -- unless a box in between this box and the image box
0127:             * paints the background with a solid color */
0128:            private boolean isAboveImage() {
0129:                CssBox curr = getParent();
0130:
0131:                while (curr != null) {
0132:                    if (curr.bgPainter != null) { // painter implies bg image
0133:
0134:                        return true;
0135:                    }
0136:
0137:                    if (curr.bg != null) {
0138:                        return false;
0139:                    }
0140:
0141:                    curr = curr.getParent();
0142:                }
0143:
0144:                return false;
0145:            }
0146:
0147:            protected void initializeBackground() {
0148:                super .initializeBackground();
0149:
0150:                ContainerBox parent = getParent();
0151:                // Note: TableBox.CellBox doesn't call super.initializeBackground,
0152:                // so if you do additional work here, check CellBox too.
0153:                // XXX parent cannot be null here since background is an invariant and
0154:                // is initialized from the constructor! Therefore, this code is
0155:                // useless at the moment; I've gotta make it run later
0156:                if (!isOpaqueBox()
0157:                        && (!inline || boxType.isAbsolutelyPositioned())
0158:                        && (bg == null) && (parent != null) && !grid
0159:                        && (parent.isGrid() || (parent.tag == HtmlTag.FORM))
0160:                        // special handling for the <form> tag - we want the grid to
0161:                        // shine through
0162:                        && (tag != HtmlTag.FORM) && !isAboveImage()) {
0163:                    // The parent has painted a grid, yet we're not a grid
0164:                    // component, so we've gotta "erase" the parent's grid dots
0165:                    CssBox p = parent;
0166:
0167:                    while ((p != null) && (p.bg == null)) {
0168:                        p = p.getParent();
0169:                    }
0170:
0171:                    if (p != null) {
0172:                        bg = p.bg;
0173:                    }
0174:                }
0175:            }
0176:
0177:            /** Initialize whether this box should show a visual grid and should receive
0178:             * grid mode handling from mouse operations */
0179:            protected void initializeGrid() {
0180:                if (!inline) {
0181:                    //            Value val = CssLookup.getValue(getElement(), XhtmlCss.RAVELAYOUT_INDEX);
0182:                    CssValue cssValue = CssProvider.getEngineService()
0183:                            .getComputedValueForElement(getElement(),
0184:                                    XhtmlCss.RAVELAYOUT_INDEX);
0185:
0186:                    //            if (val == CssValueConstants.GRID_VALUE) {
0187:                    if (CssProvider.getValueService().isGridValue(cssValue)) {
0188:                        setGrid(true);
0189:                    }
0190:                }
0191:            }
0192:
0193:            /** Set whether this is a grid-positioned box */
0194:            public void setGrid(boolean grid) {
0195:                this .grid = grid;
0196:            }
0197:
0198:            /** Indicate whether this is a grid-positioned box */
0199:            public boolean isGrid() {
0200:                if (tag == HtmlTag.FORM) {
0201:                    return grid || getParent().isGrid();
0202:                }
0203:
0204:                return grid;
0205:            }
0206:
0207:            /**
0208:             * Return the list of boxes "managed" by this box.  Managed simply
0209:             * means that the coordinates in the boxes are all relative to this
0210:             * one.
0211:             */
0212:            public int getBoxCount() {
0213:                return (boxes != null) ? boxes.size() : 0;
0214:            }
0215:
0216:            /**
0217:             * Return the box with the given index. There is no particular
0218:             * significance to the index other than identifying a box; in particular
0219:             * boxes with adjacent indices may not be adjacent visually.
0220:             */
0221:            public CssBox getBox(int index) {
0222:                return boxes.get(index);
0223:            }
0224:
0225:            protected BoxList getBoxList() {
0226:                return boxes;
0227:            }
0228:
0229:            public CssBox[] getBoxes() {
0230:                if (boxes == null) {
0231:                    return new CssBox[0];
0232:                }
0233:
0234:                List<CssBox> boxList = new ArrayList<CssBox>();
0235:                int count = boxes.size();
0236:                for (int i = 0; i < count; i++) {
0237:                    CssBox box = boxes.get(i);
0238:                    boxList.add(box);
0239:                }
0240:
0241:                return boxList.toArray(new CssBox[boxList.size()]);
0242:            }
0243:
0244:            boolean containsChild(CssBox cssBox) {
0245:                if (cssBox == null) {
0246:                    return false;
0247:                }
0248:                CssBox[] children = getBoxes();
0249:                return Arrays.asList(children).contains(cssBox);
0250:            }
0251:
0252:            /**
0253:             * Remove all the children boxes from the box list
0254:             */
0255:            protected void removeBoxes() {
0256:                boxes = null;
0257:            }
0258:
0259:            /**
0260:             * Add a new box to the list of boxes managed by this box
0261:             */
0262:            protected void addBox(CssBox box, CssBox prevBox, CssBox nextBox) {
0263:                if (boxes == null) {
0264:                    //boxes = new ArrayList(8);
0265:                    int initialSize = 8;
0266:
0267:                    // XXX todo: pick an initial size based on the box we're
0268:                    // about to create; e.g. look at our node/element field,
0269:                    // look at the number of children, and do something based
0270:                    // on that. Typically we should do the number of element
0271:                    // nodes in the child (since most text nodes are just
0272:                    // whitespace formatting), but for LineBoxes we should do
0273:                    // something smarter.
0274:                    // Ditto for tables - we know roughly how many cells we're
0275:                    // going to add (non-rectangular tables or tables with
0276:                    // colspans and rowspans will be smaller).
0277:                    boxes = new BoxList(initialSize);
0278:
0279:                    if (boxType != BoxType.LINEBOX) {
0280:                        boxes.setKeepSorted(true);
0281:                    }
0282:                }
0283:
0284:                // This seems to be not needed yet.
0285:                //        // XXX #113899 Ensure the correct order. Due to complicated architecture,
0286:                //        // strange layout processing of LineBoxGroup sometimes leads to wrong order in the line box.
0287:                //        int size = boxes.size();
0288:                //        if (size > 0 && prevBox == null && nextBox == null) {
0289:                //            for (int i = 0; i < size; i++) {
0290:                //                CssBox sibling = boxes.get(i);
0291:                //                if(DesignerUtils.getNextSiblingElement(box.getElement()) == sibling.getElement()) {
0292:                //                    nextBox = sibling;
0293:                //                    break;
0294:                //                }
0295:                //            }
0296:                //            for (int i = size - 1; i >= 0; i--) {
0297:                //                CssBox sibling = boxes.get(i);
0298:                //                if (DesignerUtils.getPreviousSiblingElement(box.getElement()) == sibling.getElement()) {
0299:                //                    prevBox = sibling;
0300:                //                    break;
0301:                //                }
0302:                //            }
0303:                //        }
0304:
0305:                boxes.add(box, prevBox, nextBox);
0306:                box.setParent(this );
0307:                box.setPositionedBy(this );
0308:            }
0309:
0310:            /**
0311:             * Remove a particular box from the children list
0312:             */
0313:            protected boolean removeBox(CssBox box) {
0314:                if (boxes == null) {
0315:                    // Internal error
0316:                    ErrorManager
0317:                            .getDefault()
0318:                            .log(
0319:                                    "Unexpected box removal - box list is empty already");
0320:
0321:                    return false;
0322:                }
0323:
0324:                return boxes.remove(box);
0325:            }
0326:
0327:            /** XXX #112576.
0328:             * @see LineBoxGroup#getBoxesToRemove */
0329:            protected CssBox[] getBoxesToRemove(CssBox toRemove) {
0330:                return new CssBox[] { toRemove };
0331:            }
0332:
0333:            /** This method can be called to make a hint as to how many
0334:             * children will be added to this box. If the box already has
0335:             * children, this method has no effect.
0336:             */
0337:            protected void setProbableChildCount(int children) {
0338:                if (boxes == null) {
0339:                    boxes = new BoxList(children);
0340:
0341:                    if (boxType != BoxType.LINEBOX) {
0342:                        boxes.setKeepSorted(true);
0343:                    }
0344:                }
0345:            }
0346:
0347:            /**
0348:             *  Return the last box in the format list for this box container, or
0349:             *  null if there are no boxes yet.
0350:             * @todo Is this method unused now that I have getPrevNormalBox?
0351:             */
0352:
0353:            /*
0354:            CssBox getLastBox() {
0355:                return (getBoxCount() > 0) ? getBox(getBoxCount() - 1) : null;
0356:            }
0357:             */
0358:
0359:            /** For debugging purposes only */
0360:            static void printLayout(CssBox b, StringBuffer sb, int depth) {
0361:                sb.append("\n");
0362:
0363:                //Log.indent(depth);
0364:                //sb.append("printLayout(box=" + box + ", depth=" + depth);
0365:                for (int i = 0; i < depth; i++) {
0366:                    sb.append("   ");
0367:                }
0368:
0369:                sb.append("  [" + b.getX() + "," + b.getY() + ","
0370:                        + b.getWidth() + "," + b.getHeight() + "] ");
0371:                sb.append("  BoxModel [");
0372:
0373:                if ((b.boxType != null) && b.boxType.isPositioned()) {
0374:                    sb.append(b.left + "," + b.top + "," + b.right + ","
0375:                            + b.bottom + ",");
0376:                }
0377:
0378:                sb.append(b.contentWidth + "," + b.contentHeight + ", mrg="
0379:                        + b.leftMargin + "," + b.effectiveTopMargin + "] ");
0380:                sb.append(" CB  [" + b.containingBlockX + ","
0381:                        + b.containingBlockY + "," + b.containingBlockWidth
0382:                        + "," + b.containingBlockHeight + "] ");
0383:
0384:                //        sb.append(
0385:                //            "  Color ["
0386:                //                + org.netbeans.modules.visualweb.designer.DesignerUtils.colorToStringName(b.bg)
0387:                //                + "] ");
0388:                sb.append("\n");
0389:
0390:                if (b.border != null) {
0391:                    sb.append("  Border [" + b.border.toString() + "]\n");
0392:                }
0393:
0394:                for (int i = 0; i < depth; i++) {
0395:                    sb.append("   ");
0396:                }
0397:
0398:                sb.append(b.toString());
0399:
0400:                //                if (lb == null) {
0401:                for (int i = 0; i < depth; i++) {
0402:                    sb.append("   ");
0403:                }
0404:
0405:                sb.append("  [abs=" + b.getAbsoluteX() + "," + b.getAbsoluteY()
0406:                        + ", rel=" + b.getX() + "," + b.getY() + ", size="
0407:                        + b.getWidth() + "," + b.getHeight() + "]  ");
0408:
0409:                if (b.getBoxCount() > 0) {
0410:                    //Log.indent(depth);
0411:                    //sb.append("Num Boxes=" + box.getBoxCount());
0412:                    for (int l = 0; l < b.getBoxCount(); l++) {
0413:                        CssBox bc = b.getBox(l);
0414:                        sb.append("\n");
0415:
0416:                        for (int i = 0; i < (depth + 1); i++) {
0417:                            sb.append("   ");
0418:                        }
0419:
0420:                        sb.append("Box number " + l + "\n");
0421:                        printLayout(bc, sb, depth + 1);
0422:                        sb.append("\n");
0423:                    }
0424:                }
0425:            }
0426:
0427:            /**
0428:             * Recursively create and add boxes for all the children elements
0429:             * of the element corresponding to this box. In other words, build
0430:             * the box hierarchy.  This will not do layout on the boxes - assigning
0431:             * positions, sizes, or flowing inline content. org.netbeans.modules.visualweb.css2.FacesSupport.printNode(element)
0432:             */
0433:            protected void createChildren(CreateContext context) {
0434:                Element element = getElement();
0435:                if (element == null) {
0436:                    return;
0437:                }
0438:
0439:                NodeList list = element.getChildNodes();
0440:                int len = list.getLength();
0441:                setProbableChildCount(len);
0442:
0443:                for (int i = 0; i < len; i++) {
0444:                    org.w3c.dom.Node child = (org.w3c.dom.Node) list.item(i);
0445:
0446:                    if ((child.getNodeType() == Node.TEXT_NODE)
0447:                            && COLLAPSE
0448:                            && DesignerUtils.onlyWhitespace(child
0449:                                    .getNodeValue())) {
0450:                        continue;
0451:                    }
0452:
0453:                    addNode(context, child, null, null, null);
0454:                }
0455:            }
0456:
0457:            /**
0458:             * Add a box for the given child node
0459:             */
0460:            void addNode(CreateContext context, Node node,
0461:                    Element sourceElement, CssBox prevBox, CssBox nextBox) {
0462:                // Find out what kind of box positioning we're dealing with
0463:                if (node.getNodeType() == Node.ELEMENT_NODE) {
0464:                    Element element = (Element) node;
0465:                    String tagName = element.getTagName();
0466:                    HtmlTag tag = HtmlTag.getTag(tagName);
0467:
0468:                    if (tag == null) {
0469:                        if ((tagName.length() > 0)
0470:                                && Character.isUpperCase(tagName.charAt(0))) {
0471:                            //                    // TODO - line number?
0472:                            ////                    org.netbeans.modules.visualweb.insync.markup.MarkupUnit unit = webform.getMarkup();
0473:                            //                    Element e = MarkupService.getCorrespondingSourceElement(element);
0474:                            //                    String message =
0475:                            //                        NbBundle.getMessage(ContainerBox.class, "UppercaseTag", tagName);
0476:                            ////                    MarkupService.displayError(unit.getFileObject(), unit.computeLine(e), message);
0477:                            //                    Document doc = e.getOwnerDocument();
0478:                            //                    FileObject fo = InSyncService.getProvider().getFileObject(doc);
0479:                            //                    int line = InSyncService.getProvider().computeLine(doc, e);
0480:                            //                    InSyncService.getProvider().getRaveErrorHandler().displayErrorForFileObject(message, fo, line, 0);
0481:                            // XXX This validation should be done in parser, not here!
0482:                            ErrorManager.getDefault().notify(
0483:                                    ErrorManager.INFORMATIONAL,
0484:                                    new IllegalStateException(
0485:                                            "The element has uppercase tag name, element="
0486:                                                    + element)); // NOI18N
0487:                        }
0488:
0489:                        // What do we do about unrecognized content? Should
0490:                        // probably process its children, right? E.g. if the
0491:                        // document contains <foobar>Hello World</foobar>,
0492:                        // "Hello World" should be shown even though it's
0493:                        // contained in an "unknown" element.
0494:                        NodeList nl = element.getChildNodes();
0495:                        int num = nl.getLength();
0496:
0497:                        if (num > 0) {
0498:                            setProbableChildCount(num); // or addProbablyChildCount?? XXX
0499:
0500:                            for (int i = 0, n = num; i < n; i++) {
0501:                                Node nn = nl.item(i);
0502:
0503:                                if ((nn.getNodeType() == Node.TEXT_NODE)
0504:                                        && COLLAPSE
0505:                                        && DesignerUtils.onlyWhitespace(nn
0506:                                                .getNodeValue())) {
0507:                                    continue;
0508:                                }
0509:
0510:                                addNode(context, nn, null, prevBox, nextBox); // Recurse
0511:                            }
0512:                        }
0513:
0514:                        return;
0515:                    } else {
0516:                        // XXX if element == body, it should be the case that
0517:                        // boxType == BoxType.STATIC -- we should ignore the position
0518:                        // and float properties! (See section 9.1.2)
0519:                        //                Value display = CssLookup.getValue(element, XhtmlCss.DISPLAY_INDEX);
0520:                        CssValue cssDisplay = CssProvider.getEngineService()
0521:                                .getComputedValueForElement(element,
0522:                                        XhtmlCss.DISPLAY_INDEX);
0523:
0524:                        //                if (display == CssValueConstants.NONE_VALUE) {
0525:                        if (CssProvider.getValueService().isNoneValue(
0526:                                cssDisplay)) {
0527:                            return;
0528:                        }
0529:
0530:                        //                boolean inline = isInlineTag(display, element, tag);
0531:                        boolean inline = isInlineTag(cssDisplay, element, tag);
0532:
0533:                        BoxType boxType = BoxType.getBoxType(element);
0534:                        boolean replaced = tag.isReplacedTag();
0535:                        CssBox box = null;
0536:
0537:                        //                if (display == CssValueConstants.TABLE_VALUE /* || display == CssValueConstants.INLINE_TABLE_VALUE*/) {
0538:                        if (CssProvider.getValueService().isTableValue(
0539:                                cssDisplay)) {
0540:                            // TODO when the dust settles: move this logic into the box factory
0541:
0542:                            /*
0543:                            if (display == CssValueConstants.INLINE_TABLE_VALUE) {
0544:                                inline = true;
0545:                                replaced = true;
0546:                            }
0547:                             */
0548:                            box = TableBox.getTableBox(webform, element,
0549:                                    boxType, inline, replaced);
0550:                        } else {
0551:                            box = BoxFactory.create(context, tag, webform,
0552:                                    element, boxType, inline, replaced);
0553:                        }
0554:
0555:                        if (box == null) {
0556:                            // It's a hidden element - e.g. <input type="hidden">, 
0557:                            // or perhaps some tag we've marked as visually hidden,
0558:                            // e.g. <area>.
0559:                            return;
0560:                        }
0561:
0562:                        if (sourceElement != null) {
0563:                            // This box was derived from a different source element
0564:                            // (e.g. a jsf tag which was rendered into an html tag)
0565:                            // so set up a mapping from the source element as well
0566:                            //                    CssBox.putBoxReference(sourceElement, box);
0567:                            putBoxReference(sourceElement, box);
0568:                        }
0569:
0570:                        addBoxNode(tag, box, context, prevBox, nextBox);
0571:                    }
0572:                } else if ((node.getNodeType() == Node.TEXT_NODE)
0573:                        || (node.getNodeType() == Node.CDATA_SECTION_NODE)) {
0574:                    String content = node.getNodeValue();
0575:                    Element styleElement = null;
0576:
0577:                    if ((node.getParentNode() != null)
0578:                            && (node.getParentNode().getNodeType() == Node.ELEMENT_NODE)) {
0579:                        styleElement = (Element) node.getParentNode();
0580:
0581:                        // XXX I should just use context.element without above
0582:                        // check and cast - context.element should always
0583:                        // point to the nearest element from which I draw CSS
0584:                        // properties!
0585:                        //assert parent == this.element;
0586:                        //if (parent != this.element) {
0587:                        //    System.out.println("Parent element was " + parent + " and this.element is " + this.element);
0588:                        //}
0589:                    }
0590:
0591:                    Text textNode = (node instanceof  Text) ? (Text) node : null;
0592:
0593:                    //            if (textNode != null) {
0594:                    //                textNode = textNode.getSourceNode();
0595:                    //            }
0596:                    addText(context, textNode, styleElement, content);
0597:                }
0598:            }
0599:
0600:            /** Add the given child box to this parent box list, and
0601:             * recursively create its children / box hiearchy. */
0602:            protected void addBoxNode(HtmlTag tag, CssBox box,
0603:                    CreateContext context, CssBox prevBox, CssBox nextBox) {
0604:                // Special handling when we're inserting in the middle of an
0605:                // existing box tree
0606:                if ((prevBox != null) || (nextBox != null)) {
0607:                    // For absolutely positioned boxes, we don't care about siblings
0608:                    if (!box.getBoxType().isAbsolutelyPositioned()) {
0609:                        addSiblingBoxNode(tag, box, context, prevBox, nextBox);
0610:
0611:                        return;
0612:                    }
0613:
0614:                    nextBox = null;
0615:                    prevBox = null;
0616:                }
0617:
0618:                // XXX just pass in null for the other puppies
0619:                boolean finishLineBoxAfterChildren = false;
0620:                boolean preserveLineBox = false;
0621:                LineBoxGroup oldLineBox = null;
0622:
0623:                if ((box.getBoxType() == BoxType.ABSOLUTE)
0624:                        || (box.getBoxType() == BoxType.FIXED)) {
0625:                    // Even inline tags should be positioned absolutely (not
0626:                    // added to a line box) but don't break the inline context
0627:                    finishLineBoxAfterChildren = true;
0628:                    preserveLineBox = true;
0629:                    oldLineBox = context.lineBox;
0630:                    context.lineBox = null;
0631:                    getBlockBox().addBox(box, prevBox, nextBox);
0632:
0633:                    if (box.getBoxType() == BoxType.FIXED) {
0634:                        context.addFixedBox(box);
0635:                    }
0636:                } else if (box.getBoxType() == BoxType.FLOAT) {
0637:                    addToLineBox(context, box, null, null); // XXX Should finishLineBoxAfterChildren!
0638:                    preserveLineBox = true;
0639:                    oldLineBox = context.lineBox;
0640:                    context.lineBox = null;
0641:                } else if (box.isBlockLevel()) {
0642:                    finishLineBox(context);
0643:                    getBlockBox().addBox(box, prevBox, nextBox); // redundant?
0644:                    finishLineBoxAfterChildren = true;
0645:                } else {
0646:                    addToLineBox(context, box, null, null);
0647:                }
0648:
0649:                //        // Create children of the box
0650:                if (box instanceof  ContainerBox) {
0651:                    ((ContainerBox) box).createChildren(context);
0652:                }
0653:
0654:                if (finishLineBoxAfterChildren) {
0655:                    finishLineBox(context);
0656:                }
0657:
0658:                if (preserveLineBox) {
0659:                    context.lineBox = oldLineBox;
0660:                }
0661:            }
0662:
0663:            /** Add the given child box to this parent box list, and
0664:             * recursively create its children / box hiearchy.
0665:             * Deal with "prevBox" and "nextBox" to determine insertion
0666:             * in the middle of the box hierarchy; used during insert events.
0667:             *
0668:             * @todo This code is really hacky; clean it up.
0669:             */
0670:            protected void addSiblingBoxNode(HtmlTag tag, CssBox box,
0671:                    CreateContext context, CssBox prevBox, CssBox nextBox) {
0672:                boolean finishLineBoxAfterChildren = false;
0673:                boolean preserveLineBox = false;
0674:                LineBoxGroup oldLineBox = null;
0675:
0676:                if ((box.getBoxType() == BoxType.ABSOLUTE)
0677:                        || (box.getBoxType() == BoxType.FIXED)) {
0678:                    // Absolute boxes do not care where they're inserted - 
0679:                    // other than the actual painting/rendering order, since
0680:                    // z-order is sometimes related to the model/boxlist
0681:                    // position.
0682:                    // Even inline tags should be positioned absolutely (not
0683:                    // added to a line box) but don't break the inline context
0684:                    finishLineBoxAfterChildren = true;
0685:                    preserveLineBox = true;
0686:                    oldLineBox = context.lineBox;
0687:                    context.lineBox = null;
0688:                    getBlockBox().addBox(box, prevBox, nextBox);
0689:
0690:                    if (box.getBoxType() == BoxType.FIXED) {
0691:                        context.addFixedBox(box);
0692:                    }
0693:                } else if (box.getBoxType() == BoxType.FLOAT) {
0694:                    // XXX how does this work?
0695:                    addToLineBox(context, box, prevBox, nextBox);
0696:                    preserveLineBox = true;
0697:                    oldLineBox = context.lineBox;
0698:                    context.lineBox = null;
0699:                } else if (box.isBlockLevel()) {
0700:                    // Since we're not looking at absolute positioning, adjust prev/next
0701:                    // references to refer to normal children only
0702:                    while ((prevBox != null)
0703:                            && !(prevBox.getBoxType().isNormalFlow() || (prevBox
0704:                                    .getBoxType().isInlineTextBox()))) {
0705:                        prevBox = prevBox.getPrevNormalBox();
0706:                    }
0707:
0708:                    while ((nextBox != null)
0709:                            && !(nextBox.getBoxType().isNormalFlow() || (nextBox
0710:                                    .getBoxType().isInlineTextBox()))) {
0711:                        nextBox = nextBox.getNextNormalBox();
0712:                    }
0713:
0714:                    if ((prevBox != null) && (nextBox != null)
0715:                            && prevBox.isInlineBox() && nextBox.isInlineBox()) {
0716:                        // Block box is inserted in the middle of an inline context.
0717:                        // This means we need to split the linebox in half and
0718:                        // insert the block box in the middle.
0719:                        // XXX TODO
0720:                        LineBoxGroup lb = null;
0721:
0722:                        if (prevBox instanceof  LineBoxGroup) {
0723:                            lb = (LineBoxGroup) prevBox; // happens when prev was absolutely positioned for example
0724:                        } else if (prevBox.getParent() instanceof  LineBoxGroup) {
0725:                            lb = (LineBoxGroup) prevBox.getParent();
0726:                        } else {
0727:                            lb = (LineBoxGroup) prevBox.getParent().getParent();
0728:                        }
0729:
0730:                        // prev and next should be in the same lineboxgroup
0731:                        //assert lb == (nextBox.getParent() instanceof LineBoxGroup ?
0732:                        //              (LineBoxGroup)nextBox.getParent() :
0733:                        //              (LineBoxGroup)nextBox.getParent().getParent());
0734:                        //      gotta check if nextBox instanceof LineBoxGroup too
0735:                        LineBoxGroup alb = lb.split(prevBox);
0736:                        context.prevChangedBox = lb;
0737:                        context.nextChangedBox = alb;
0738:                        getBlockBox().addBox(box, lb, null);
0739:                        getBlockBox().addBox(alb, box, null);
0740:                    } else {
0741:                        // We're either right above or right below a block box,
0742:                        // so simply insert the box where it needs to be.
0743:                        finishLineBox(context);
0744:
0745:                        if ((prevBox != null) && prevBox.isInlineBox()) {
0746:                            while ((prevBox != null)
0747:                                    && !(prevBox instanceof  LineBoxGroup)) {
0748:                                prevBox = prevBox.getParent();
0749:                            }
0750:                        }
0751:
0752:                        if ((nextBox != null) && nextBox.isInlineBox()) {
0753:                            while ((nextBox != null)
0754:                                    && !(nextBox instanceof  LineBoxGroup)) {
0755:                                nextBox = nextBox.getParent();
0756:                            }
0757:                        }
0758:
0759:                        getBlockBox().addBox(box, prevBox, nextBox);
0760:                        finishLineBoxAfterChildren = true;
0761:                    }
0762:                } else {
0763:                    // Inline
0764:                    // Since we're not looking at absolute positioning, adjust prev/next
0765:                    // references to refer to normal children only
0766:                    while ((prevBox != null)
0767:                            && !(prevBox.getBoxType().isNormalFlow() || (prevBox
0768:                                    .getBoxType().isInlineTextBox()))) {
0769:                        prevBox = prevBox.getPrevNormalBox();
0770:                    }
0771:
0772:                    while ((nextBox != null)
0773:                            && !(nextBox.getBoxType().isNormalFlow() || (nextBox
0774:                                    .getBoxType().isInlineTextBox()))) {
0775:                        nextBox = nextBox.getNextNormalBox();
0776:                    }
0777:
0778:                    if ((prevBox != null) && (nextBox != null)
0779:                            && prevBox.isInlineBox() && nextBox.isInlineBox()) {
0780:                        // Inline box is inserted in the middle of an inline context.
0781:                        // This means we simply need to inject the inline box
0782:                        // into the middle of the LineBoxGroup
0783:                        LineBoxGroup lb = null;
0784:
0785:                        if (prevBox instanceof  LineBoxGroup) {
0786:                            lb = (LineBoxGroup) prevBox; // happens when prev was absolutely positioned for example
0787:                        } else if (prevBox.getParent() instanceof  LineBoxGroup) {
0788:                            lb = (LineBoxGroup) prevBox.getParent();
0789:                        } else {
0790:                            lb = (LineBoxGroup) prevBox.getParent().getParent();
0791:                        }
0792:
0793:                        // prev and next should be in the same lineboxgroup
0794:                        //assert lb == (nextBox.getParent() instanceof LineBoxGroup ?
0795:                        //              (LineBoxGroup)nextBox.getParent() :
0796:                        //               (LineBoxGroup)nextBox.getParent().getParent());
0797:                        //      gotta check if nextBox instanceof LineBoxGroup too
0798:                        lb.addBox(box, prevBox, nextBox);
0799:
0800:                        // XXX #109446 Use just the created LineBoxGroup in the context.
0801:                        preserveLineBox = true;
0802:                        oldLineBox = context.lineBox;
0803:                        context.lineBox = lb;
0804:                    } else if ((prevBox != null) && prevBox.isInlineBox()) {
0805:                        // We're inserting an inline element between an
0806:                        // inline box and a block box; add it to the previous
0807:                        // linebox
0808:                        LineBoxGroup lb = null;
0809:
0810:                        if (prevBox instanceof  LineBoxGroup) {
0811:                            lb = (LineBoxGroup) prevBox;
0812:                            prevBox = null;
0813:                        } else if (prevBox.getParent() instanceof  LineBoxGroup) {
0814:                            lb = (LineBoxGroup) prevBox.getParent();
0815:                        } else {
0816:                            assert (prevBox.getParent() != null)
0817:                                    && prevBox.getParent().getParent() instanceof  LineBoxGroup;
0818:                            lb = (LineBoxGroup) prevBox.getParent().getParent();
0819:                        }
0820:
0821:                        lb.addBox(box, prevBox, null);
0822:
0823:                        // XXX #109446 Use just the created LineBoxGroup in the context.
0824:                        preserveLineBox = true;
0825:                        oldLineBox = context.lineBox;
0826:                        context.lineBox = lb;
0827:                    } else if ((nextBox != null) && nextBox.isInlineBox()) {
0828:                        // We're inserting an inline element between a
0829:                        // block box and an inline box; add it to the front
0830:                        // of the next linebox
0831:                        LineBoxGroup lb = null;
0832:
0833:                        if (nextBox instanceof  LineBoxGroup) {
0834:                            lb = (LineBoxGroup) nextBox;
0835:                            nextBox = null;
0836:                        } else if (nextBox.getParent() instanceof  LineBoxGroup) {
0837:                            lb = (LineBoxGroup) nextBox.getParent();
0838:                        } else {
0839:                            assert (nextBox.getParent() != null)
0840:                                    && nextBox.getParent().getParent() instanceof  LineBoxGroup;
0841:                            lb = (LineBoxGroup) nextBox.getParent().getParent();
0842:                        }
0843:
0844:                        lb.addBox(box, null, nextBox);
0845:
0846:                        // XXX #109446 Use just the created LineBoxGroup in the context.
0847:                        preserveLineBox = true;
0848:                        oldLineBox = context.lineBox;
0849:                        context.lineBox = lb;
0850:                    } else {
0851:                        // We're inserting an inline element between two block
0852:                        // boxes
0853:                        addToLineBox(context, box, prevBox, nextBox);
0854:                    }
0855:                }
0856:
0857:                // Create children of the box
0858:                if (box instanceof  ContainerBox) {
0859:                    ((ContainerBox) box).createChildren(context);
0860:                }
0861:
0862:                if (finishLineBoxAfterChildren) {
0863:                    finishLineBox(context);
0864:                }
0865:
0866:                if (preserveLineBox) {
0867:                    context.lineBox = oldLineBox;
0868:                }
0869:            }
0870:
0871:            /**
0872:             *  For a given TEXT_NODE/CDATA_SECTION_NODE, add the text to the
0873:             *  current line box
0874:             */
0875:            protected void addText(CreateContext context, Text textNode,
0876:                    Element styleElement, String text) {
0877:                // Check font size and attributes
0878:                int decoration = 0;
0879:                Color fg = Color.black;
0880:                Color bg = null;
0881:                FontMetrics metrics = context.metrics;
0882:                boolean collapseSpaces = true;
0883:                boolean hidden = false;
0884:
0885:                if (styleElement != null) {
0886:                    //            metrics = CssLookup.getFontMetrics(styleElement);
0887:                    //            metrics = CssProvider.getValueService().getFontMetricsForElement(styleElement);
0888:                    metrics = CssUtilities.getDesignerFontMetricsForElement(
0889:                            styleElement, text, webform.getDefaultFontSize());
0890:
0891:                    //            fg = CssLookup.getColor(styleElement, XhtmlCss.COLOR_INDEX);
0892:                    fg = CssProvider.getValueService().getColorForElement(
0893:                            styleElement, XhtmlCss.COLOR_INDEX);
0894:
0895:                    if (fg == null) {
0896:                        fg = Color.black;
0897:                    }
0898:
0899:                    //bg = Css.getColor(styleElement, XhtmlCssEngine.BACKGROUND_COLOR_INDEX);
0900:                    // Pick up the background color for text only when the background
0901:                    // color is set on an inline tag. If the background color
0902:                    // is coming from a block level box, then the background will
0903:                    // already have been painted as part of the block. Thus, this
0904:                    // will let us paint backgrounds when set on e.g. spans.
0905:                    // I also noticed Mozilla will inherit background colors when
0906:                    // set on inline tags - e.g.
0907:                    //   <span style="background: red"><b><i>Has Red Bg</i></b></span>
0908:                    // So this code achieves that too; it's a bit of a hack since
0909:                    // it won't use proper selectors etc - when we redo the CSS
0910:                    // parser this should hopefully be taken care of by the
0911:                    // cascade!
0912:                    bg = null;
0913:
0914:                    CssBox curr = this ;
0915:
0916:                    while ((curr != null) && curr.inline && !curr.replaced) {
0917:                        if (curr.bg == null) {
0918:                            // XXX This is a hack! I should initialize this
0919:                            // earlier on. 
0920:                            // XXX this should not be a problem anymore, I have initializeInvariants now
0921:                            curr.initializeBackground();
0922:                        }
0923:
0924:                        if (curr.bg != null) {
0925:                            bg = curr.bg;
0926:
0927:                            break;
0928:                        }
0929:
0930:                        curr = curr.getParent();
0931:                    }
0932:
0933:                    //            Value val = CssLookup.getValue(styleElement, XhtmlCss.TEXT_DECORATION_INDEX);
0934:                    CssValue cssValue = CssProvider.getEngineService()
0935:                            .getComputedValueForElement(styleElement,
0936:                                    XhtmlCss.TEXT_DECORATION_INDEX);
0937:
0938:                    //            switch (val.getCssValueType()) {
0939:                    //            case CSSValue.CSS_VALUE_LIST:
0940:                    //                ListValue lst = CssLookup.getListValue(val);
0941:                    //                if (lst == null) {
0942:                    //                    break;
0943:                    //                }
0944:                    CssListValue cssListValue = CssProvider.getValueService()
0945:                            .getComputedCssListValue(cssValue);
0946:                    if (cssListValue != null) {
0947:
0948:                        //                int len = lst.getLength();
0949:                        int len = cssListValue.getLength();
0950:
0951:                        for (int i = 0; i < len; i++) {
0952:                            //                    Value v = lst.item(i);
0953:                            CssValue cssV = cssListValue.item(i);
0954:                            //                    String s = v.getStringValue();
0955:                            String s = cssV.getStringValue();
0956:
0957:                            switch (s.charAt(0)) {
0958:                            case 'u':
0959:                                decoration |= TextBox.UNDERLINE;
0960:
0961:                                break;
0962:
0963:                            case 'o':
0964:                                decoration |= TextBox.OVERLINE;
0965:
0966:                                break;
0967:
0968:                            case 'l':
0969:                                decoration |= TextBox.STRIKE;
0970:
0971:                                break;
0972:                            }
0973:                        }
0974:
0975:                        //                break;
0976:                        //            default:
0977:                    } else {
0978:                        // XXX what happened?
0979:                    }
0980:
0981:                    // XXX Technically, should check for decoration=="overline" too...
0982:                    // (See section 16.3.1). However, does that have ANY practical
0983:                    // utility?
0984:                    //            val = CssLookup.getValue(styleElement, XhtmlCss.WHITE_SPACE_INDEX);
0985:                    CssValue cssValue2 = CssProvider.getEngineService()
0986:                            .getComputedValueForElement(styleElement,
0987:                                    XhtmlCss.WHITE_SPACE_INDEX);
0988:
0989:                    //            if ((val == CssValueConstants.PRE_VALUE) || (val == CssValueConstants.PRE_WRAP_VALUE)) {
0990:                    if (CssProvider.getValueService().isPreValue(cssValue2)
0991:                            || CssProvider.getValueService().isPreWrapValue(
0992:                                    cssValue2)) {
0993:                        collapseSpaces = false;
0994:                    }
0995:
0996:                    //            val = CssLookup.getValue(getElement(), XhtmlCss.VISIBILITY_INDEX);
0997:                    CssValue cssValue3 = CssProvider.getEngineService()
0998:                            .getComputedValueForElement(getElement(),
0999:                                    XhtmlCss.VISIBILITY_INDEX);
1000:                    //            hidden = (val != CssValueConstants.VISIBLE_VALUE);
1001:                    hidden = !CssProvider.getValueService().isVisibleValue(
1002:                            cssValue3);
1003:                } else {
1004:                    // Initialize metrics to something useful!
1005:                    ErrorManager.getDefault().log(
1006:                            "Gotta set font from somewhere else!");
1007:                }
1008:
1009:                addText(text, styleElement, textNode, context, metrics, fg, bg,
1010:                        decoration, collapseSpaces, hidden);
1011:            }
1012:
1013:            protected void addGrayItalicText(CreateContext context,
1014:                    Element styleElement, String text) {
1015:                FontMetrics metrics = null;
1016:
1017:                if (styleElement != null) {
1018:                    //            metrics = CssLookup.getFontMetrics(styleElement);
1019:                    //            metrics = CssProvider.getValueService().getFontMetricsForElement(styleElement);
1020:                    metrics = CssUtilities.getDesignerFontMetricsForElement(
1021:                            styleElement, text, webform.getDefaultFontSize());
1022:
1023:                    Font font = metrics.getFont();
1024:                    font = font.deriveFont(Font.ITALIC);
1025:                    //            metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
1026:                    metrics = DesignerUtils.getFontMetrics(font);
1027:                }
1028:
1029:                if (metrics == null) {
1030:                    metrics = context.metrics;
1031:                }
1032:
1033:                addText(text, styleElement, null, context, metrics, Color.GRAY,
1034:                        null, 0, true, false);
1035:            }
1036:
1037:            /**
1038:             * May add one or more boxes, each one of which may have box
1039:             * children.
1040:             * @todo Move this routine into static TextBox method?
1041:             */
1042:            private void addText(String content, Element styleElement,
1043:                    Text textNode, CreateContext context, FontMetrics metrics,
1044:                    Color fg, Color bg, int decoration, boolean collapseSpaces,
1045:                    boolean hidden) {
1046:                // XXX separateTextBox(context);
1047:                // Translate the string from jspx to xhtml
1048:                // When doing visual position computations, we need to 
1049:                // reverse the computation.
1050:                String source = content;
1051:
1052:                //        if ((textNode != null) && textNode.isJspx()) {
1053:                if (textNode != null && MarkupService.isJspxNode(textNode)) {
1054:                    content =
1055:                    // <markup_separation>
1056:                    //                MarkupServiceProvider.getDefault().expandHtmlEntities(content, true, styleElement);
1057:                    // ====
1058:                    //                InSyncService.getProvider().expandHtmlEntities(content, true, styleElement);
1059:                    webform.getDomProviderService().expandHtmlEntities(content,
1060:                            true, styleElement);
1061:                    // </markup_separation>
1062:                }
1063:
1064:                if (styleElement != null) {
1065:                    //            Value v1 = CssLookup.getValue(styleElement, XhtmlCss.FONT_VARIANT_INDEX);
1066:                    //            Value v2 = CssLookup.getValue(styleElement, XhtmlCss.TEXT_TRANSFORM_INDEX);
1067:                    CssValue cssV1 = CssProvider.getEngineService()
1068:                            .getComputedValueForElement(styleElement,
1069:                                    XhtmlCss.FONT_VARIANT_INDEX);
1070:                    CssValue cssV2 = CssProvider.getEngineService()
1071:                            .getComputedValueForElement(styleElement,
1072:                                    XhtmlCss.TEXT_TRANSFORM_INDEX);
1073:
1074:                    //            if ((v1 == CssValueConstants.SMALL_CAPS_VALUE) ||
1075:                    //                    (v2 == CssValueConstants.UPPERCASE_VALUE)) {
1076:                    if (CssProvider.getValueService().isSmallCapsValue(cssV1)
1077:                            || CssProvider.getValueService().isUpperCaseValue(
1078:                                    cssV2)) {
1079:                        // Uppercase the text
1080:                        content = content.toUpperCase();
1081:
1082:                        // TODO (much later): split the text up like under capitalization
1083:                        // and apply different fonts to the initial letters
1084:                        // and the rest of the words. I can't trivially do that
1085:                        // here because I would create separate TextBoxes for the
1086:                        // initial character and the rest of the words, and this
1087:                        // COULD be split up both in text justification and in word
1088:                        // wrapping by the LineBox and LineBoxGroup containers, which
1089:                        // would be visually disasterous. I think the painting of
1090:                        // this would really have to be done in the TextBox itself.
1091:                        //            } else if (v2 == CssValueConstants.LOWERCASE_VALUE) {
1092:                    } else if (CssProvider.getValueService().isLowerCaseValue(
1093:                            cssV2)) {
1094:                        content = content.toLowerCase();
1095:                        //            } else if (v2 == CssValueConstants.CAPITALIZE_VALUE) {
1096:                    } else if (CssProvider.getValueService().isCapitalizeValue(
1097:                            cssV2)) {
1098:                        StringBuffer sb = new StringBuffer(content.length());
1099:                        boolean capitalize = false;
1100:
1101:                        for (int i = 0, n = content.length(); i < n; i++) {
1102:                            char c = content.charAt(i);
1103:
1104:                            if (Character.isWhitespace(c)) {
1105:                                capitalize = true;
1106:                            } else if (capitalize) {
1107:                                c = Character.toUpperCase(c);
1108:                                capitalize = false;
1109:                            }
1110:
1111:                            sb.append(c);
1112:                        }
1113:
1114:                        content = sb.toString();
1115:                    }
1116:                }
1117:
1118:                // Determine how much text will fit
1119:                char[] contentChars = null;
1120:                int len = content.length();
1121:
1122:                /*
1123:                  From the HTML4.01 spec: make sure we handle this correctly:
1124:
1125:                  In Western scripts, for example, text should only be
1126:                  wrapped at white space. Early user agents incorrectly
1127:                  wrapped lines just after the start tag or just before
1128:                  the end tag of an element, which resulted in dangling
1129:                  punctuation. For example, consider this sentence:
1130:
1131:                  A statue of the <A href="cih78">Cihuateteus</A>, who are
1132:                  patron ...
1133:
1134:                  Wrapping the line just before the end tag of the A
1135:                  element causes the comma to be stranded at the beginning
1136:                  of the next line:
1137:
1138:                  A statue of the Cihuateteus
1139:                  , who are patron ...
1140:
1141:                 */
1142:
1143:                // Find (and add) the next word
1144:                int begin = 0;
1145:                int end;
1146:
1147:                if (!collapseSpaces) {
1148:                    end = len;
1149:
1150:                    if (contentChars == null) {
1151:                        contentChars = content.toCharArray(); // XXX share among views?
1152:                    }
1153:
1154:                    if (content.indexOf('\n') != -1) { // XXX what about \r and \r\n and \n\r?
1155:
1156:                        for (int i = begin; i < end; i++) {
1157:                            if (content.charAt(i) == '\n') {
1158:                                // Split here           
1159:                                if (i > begin) {
1160:                                    TextBox box = new TextBox(webform,
1161:                                            styleElement, textNode,
1162:                                            contentChars, content, source,
1163:                                            begin, i, fg, bg, decoration,
1164:                                            metrics, hidden);
1165:                                    addToLineBox(context, box, null, null);
1166:                                }
1167:
1168:                                addToLineBox(context, new LineBreakBox(webform,
1169:                                        styleElement, null), null, null);
1170:                                begin = i + 1;
1171:                            }
1172:                        }
1173:
1174:                        if (end > begin) {
1175:                            TextBox box = new TextBox(webform, styleElement,
1176:                                    textNode, contentChars, content, source,
1177:                                    begin, end, fg, bg, decoration, metrics,
1178:                                    hidden);
1179:                            addToLineBox(context, box, null, null);
1180:                        }
1181:
1182:                        addToLineBox(context, new LineBreakBox(webform,
1183:                                styleElement, null), null, null);
1184:                    } else {
1185:                        TextBox box = new TextBox(webform, styleElement,
1186:                                textNode, contentChars, content, source, begin,
1187:                                end, fg, bg, decoration, metrics, hidden);
1188:                        addToLineBox(context, box, null, null);
1189:                    }
1190:
1191:                    return;
1192:                }
1193:
1194:                while (begin < len) {
1195:                    //char c = content.charAt(begin);
1196:                    if (Character.isWhitespace(content.charAt(begin))) {
1197:                        int spaceBegin = begin;
1198:                        begin++;
1199:
1200:                        // Skip remaining space characters
1201:                        while ((begin < len)
1202:                                && Character
1203:                                        .isWhitespace(content.charAt(begin))) {
1204:                            begin++;
1205:                        }
1206:
1207:                        // XXX What if the linebox previous box is a space box?
1208:                        // if so there's nothing to do since the linebox
1209:                        // should never allow too consecutive space boxes...
1210:                        // However... I need to extend model range to include
1211:                        // my current range... Can this ever happen?
1212:                        SpaceBox box = new SpaceBox(webform, styleElement,
1213:                                textNode, content, source, spaceBegin, begin,
1214:                                fg, bg, decoration, metrics, hidden);
1215:                        addToLineBox(context, box, null, null);
1216:                    }
1217:
1218:                    // Find end of word
1219:                    end = begin;
1220:
1221:                    while ((end < len)
1222:                            && !Character.isWhitespace(content.charAt(end))) {
1223:                        end++;
1224:                    }
1225:
1226:                    if (end > begin) {
1227:                        if (contentChars == null) {
1228:                            contentChars = content.toCharArray(); // XXX share among views?
1229:                        }
1230:
1231:                        TextBox box = new TextBox(webform, styleElement,
1232:                                textNode, contentChars, content, source, begin,
1233:                                end, fg, bg, decoration, metrics, hidden);
1234:                        addToLineBox(context, box, null, null);
1235:                        begin = end;
1236:                    } else {
1237:                        break;
1238:                    }
1239:                }
1240:            }
1241:
1242:            /**
1243:             * Recompute the layout. Once the layout routine gets to a point
1244:             * where the child layout matches the computed layout, it will leave
1245:             * that tree alone.  Thus, only the portions of the layout below
1246:             * this box that need to be recomputed are updated
1247:             *
1248:             * @param cx X position of containing block
1249:             * @param cy Y position of containing block
1250:             * @param cw Width of containing block
1251:             * @param ch Height of containing block
1252:             */
1253:            public void relayout(FormatContext context) {
1254:                for (int i = 0, n = getBoxCount(); i < n; i++) {
1255:                    CssBox box = getBox(i);
1256:
1257:                    if (!box.isPlaceHolder()) {
1258:                        if ((box.getBoxType() == BoxType.LINEBOX) ||
1259:
1260:                        // Note: This is a bit inefficient: we will be positioning
1261:                                // the boxes more than once while there are floats in effect.
1262:                                // However, we need to ensure that boxes are at least roughly
1263:                                // positioned such that the "is floating box overlapping?" code
1264:                                // can compute relative distances between children of this box
1265:                                // and a common ancestor with a floating box still in effect.
1266:                                // And we can't simply move all positioning up to this point
1267:                                // because accurate block positioning requires the margin to
1268:                                // be computed, which isn't possible until vertical distances
1269:                                // have been computed (which has to be done after the children
1270:                                // have been laid out)
1271:                                (box.getBoxType().isNormalFlow() && (context.floats != null))) {
1272:                            positionBox(box, context);
1273:                        }
1274:
1275:                        layoutChild(box, context, true);
1276:
1277:                        //                if ((box.getBoxType() != BoxType.LINEBOX) &&
1278:                        //                        (box.isBlockLevel() || box.getBoxType().isAbsolutelyPositioned())) {
1279:                        // XXX #113117 To be sure also the normal flow elements have position set.
1280:                        if ((box.getBoxType() != BoxType.LINEBOX)
1281:                                && (box.isBlockLevel()
1282:                                        || box.getBoxType()
1283:                                                .isAbsolutelyPositioned() || box
1284:                                        .getBoxType().isNormalFlow())) {
1285:                            positionBox(box, context);
1286:                        }
1287:                    }
1288:                }
1289:            }
1290:
1291:            /** @todo: make this a CssBox method instead - e.g. have relayout()
1292:             * do this, and have relayout on children call super, then recurse! XXX
1293:             * NO! This is passing values (such as the containing block) to the
1294:             * child, that would have to be done by the parent first!
1295:             */
1296:            protected void layoutChild(CssBox box, FormatContext context,
1297:                    boolean handleChildren) {
1298:                // Set new containing block size
1299:                setContainingBlock(box, context);
1300:
1301:                // Set up margin values etc.
1302:                // XXX NO! This should be done at cration time, not layout time!
1303:                // Oh wait - layout may write values into AUTO-fields.... hm....
1304:                // add effectiveLeft/Right (perhaps call them "used" as in the spec)
1305:                // and only mutate those from computeHorizontal/VerticalLengths
1306:                box.initialize();
1307:
1308:                box.computeHorizontalLengths(context);
1309:
1310:                if (box.contentWidth != AUTO) {
1311:                    box.width = box.leftBorderWidth + box.leftPadding
1312:                            + box.contentWidth + box.rightPadding
1313:                            + box.rightBorderWidth;
1314:                } else {
1315:                    box.width = UNINITIALIZED;
1316:                }
1317:
1318:                boolean abs = box.getBoxType().isAbsolutelyPositioned();
1319:                List<FloatingBoxInfo> oldFloats = null;
1320:                boolean oldFloating = false;
1321:
1322:                if (abs) {
1323:                    // Absolute positioned children are not affected by floating boxes
1324:                    oldFloats = context.floats;
1325:                    oldFloating = context.floating;
1326:                    context.floats = null;
1327:                    context.floating = false;
1328:                }
1329:
1330:                // XXX #109564 This seems to caused the issue, but what it could cause now?
1331:                //        if(getBoxType() == BoxType.FLOAT) {
1332:                //            oldFloats = context.floats;
1333:                //            context.floats = null;
1334:                //        }
1335:
1336:                if (handleChildren) {
1337:                    // Lay out the children now that we've established a containing
1338:                    // block and have constrained the content width if necessary.
1339:                    box.relayout(context);
1340:                }
1341:
1342:                // XXX #109564 This seems to caused the issue, but what it could cause now?
1343:                //        if(getBoxType() == BoxType.FLOAT) {
1344:                //            context.floats = oldFloats;
1345:                //        }
1346:
1347:                if (abs) {
1348:                    context.floats = oldFloats;
1349:                    context.floating = oldFloating;
1350:                }
1351:
1352:                box.computeVerticalLengths(context);
1353:                box.height = box.topBorderWidth + box.topPadding
1354:                        + box.contentHeight + box.bottomPadding
1355:                        + box.bottomBorderWidth;
1356:
1357:                if (handleChildren && box instanceof  ContainerBox) {
1358:                    //only now, when we calculated the height, we can move the relatives
1359:                    ((ContainerBox) box).finishAllRelatives(context);
1360:                }
1361:            }
1362:
1363:            //to move the relatives, see if a child is a linebox
1364:            void finishAllRelatives(FormatContext context) {
1365:                for (int i = 0; i < getBoxCount(); i++) {
1366:                    CssBox box = getBox(i);
1367:                    if (box instanceof  LineBoxGroup) {
1368:                        ((LineBoxGroup) box).finishRelatives(context);
1369:                    }
1370:                }
1371:            }
1372:
1373:            /** Very similar to relayout(context) but does not compute
1374:             * vertical dimensions, and does not position the boxes.
1375:             * Used to initialize box dimensions for computation
1376:             * of minimum widths when we're computing minimum widths
1377:             * for table cells, etc.
1378:             */
1379:            protected void initializeHorizontalWidths(FormatContext context) {
1380:                super .initializeHorizontalWidths(context);
1381:
1382:                for (int i = 0, n = getBoxCount(); i < n; i++) {
1383:                    CssBox box = getBox(i);
1384:
1385:                    // We don't care about absolute/fixed children!
1386:                    if (box.getBoxType().isAbsolutelyPositioned()) {
1387:                        continue;
1388:                    }
1389:
1390:                    box.initializeHorizontalWidths(context);
1391:                }
1392:            }
1393:
1394:            /** Set the containing block for the given box.
1395:             * See section 10.1 of the CSS2.1 spec for details.
1396:             */
1397:            void setContainingBlock(CssBox box, FormatContext context) {
1398:                // Containing Block Box - See CSS21 section 10.1 for logic.
1399:                BoxType boxType = box.getBoxType();
1400:
1401:                if ((boxType == BoxType.STATIC)
1402:                        || (boxType == BoxType.RELATIVE) // What about floats? They aren't mentioned in section 10.1, so I assume
1403:                        // they mean that floats do have a "static" position property
1404:                        || (boxType == BoxType.FLOAT)) {
1405:                    // if the element's position is 'relative' or 'static',
1406:                    // the containing block is formed by the content edge of
1407:                    // the nearest block-level, table cell or inline-block
1408:                    // ancestor box.
1409:                    CssBox cbb = box.getParent();
1410:
1411:                    while ((cbb != null)
1412:                            && !(cbb instanceof  FrameBox)
1413:                            && !cbb.isBlockLevel()
1414:                            &&
1415:                            /*floats and relatives are part of normal flow, so*/
1416:                            !((boxType == BoxType.FLOAT || boxType == BoxType.RELATIVE) && cbb
1417:                                    .getBoxType().isAbsolutelyPositioned())) {
1418:                        cbb = cbb.getParent();
1419:                    }
1420:
1421:                    if (cbb.contentWidth != AUTO) {
1422:                        box.containingBlockWidth = cbb.contentWidth;
1423:                    } else {
1424:                        box.containingBlockWidth = cbb.containingBlockWidth
1425:                                - cbb.leftMargin - cbb.leftBorderWidth
1426:                                - cbb.leftPadding - cbb.rightPadding
1427:                                - cbb.rightBorderWidth - cbb.rightMargin;
1428:                    }
1429:
1430:                    if (cbb.contentHeight != AUTO) {
1431:                        box.containingBlockHeight = cbb.contentHeight;
1432:                    } else {
1433:                        box.containingBlockHeight = cbb.containingBlockHeight
1434:                                - cbb.topMargin - cbb.topBorderWidth
1435:                                - cbb.topPadding - cbb.bottomPadding
1436:                                - cbb.bottomBorderWidth - cbb.bottomMargin;
1437:                    }
1438:
1439:                    // XXX how does x interact with box hierarchies (where children
1440:                    // are relative to their parents) and how about margins? effective
1441:                    // margins?
1442:                    box.containingBlockX = cbb.containingBlockX
1443:                            + cbb.leftMargin + cbb.leftBorderWidth
1444:                            + cbb.leftPadding;
1445:                    box.containingBlockY = cbb.containingBlockY + cbb.topMargin
1446:                            + cbb.topBorderWidth + cbb.topPadding;
1447:                } else if (boxType == BoxType.LINEBOX) {
1448:                    // Line boxes simply keep their parent's containing blocks
1449:
1450:                    /* No - that doesn't work - for example, a <div width=70%>
1451:                     * may have a linebox - that line box should inherit the
1452:                     * content width - 70% - not the div's containing block
1453:                     * which is 100%...
1454:                    box.containingBlockX = containingBlockX;
1455:                    box.containingBlockY = containingBlockY;
1456:                    box.containingBlockWidth = containingBlockWidth;
1457:                    box.containingBlockHeight = containingBlockHeight;
1458:                     */
1459:                    /*
1460:                    box.containingBlockX = 0; //leftBorderWidth+leftPadding;
1461:                    box.containingBlockY = 0; //topBorderWidth+topPadding;
1462:                    // XXX is contentWidth initialized?
1463:                    box.containingBlockWidth = contentWidth-rightBorderWidth-rightPadding-leftBorderWidth-leftPadding;
1464:                    box.containingBlockHeight = contentHeight-bottomBorderWidth-bottomPadding-topBorderWidth-topPadding;
1465:                     */
1466:                    box.containingBlockX = leftMargin + leftBorderWidth
1467:                            + leftPadding;
1468:                    box.containingBlockY = topMargin + topBorderWidth
1469:                            + topPadding;
1470:
1471:                    // XXX is contentWidth initialized?
1472:                    box.containingBlockWidth = contentWidth;
1473:                    box.containingBlockHeight = contentHeight;
1474:                } else if (boxType == BoxType.ABSOLUTE) {
1475:                    CssBox cbb = box.getParent();
1476:
1477:                    // Find nearest ancestor with a 'position' of 'absolute', 
1478:                    // 'relative' or 'fixed'
1479:                    while ((cbb != null)
1480:                            && !(cbb.getBoxType().isPositioned() || (cbb.tag == HtmlTag.FRAME))) {
1481:                        cbb = cbb.getParent();
1482:                    }
1483:
1484:                    // We don't have a positioned parent: use the viewport
1485:                    if (cbb == null) {
1486:                        box.containingBlockX = 0;
1487:                        box.containingBlockY = 0;
1488:                        box.containingBlockWidth = context.initialWidth;
1489:                        box.containingBlockHeight = context.initialHeight;
1490:                        box.setPositionedBy(context.initialCB);
1491:                    } else if (cbb.isBlockLevel()) {
1492:                        /*
1493:                        // The containing block is formed by the padding edge of
1494:                        // the ancestor
1495:                        // XXX what if the ancestor has set a width? If so,
1496:                        // I should use it, shouldn't I?
1497:                        box.containingBlockWidth =
1498:                            cbb.containingBlockWidth - cbb.leftMargin - cbb.leftBorderWidth -
1499:                            cbb.rightBorderWidth - cbb.rightMargin;
1500:
1501:                        // XXX what about effective margins etc.?
1502:                        box.containingBlockHeight =
1503:                            cbb.containingBlockHeight - cbb.topMargin - cbb.topBorderWidth -
1504:                            cbb.bottomBorderWidth - cbb.bottomMargin;
1505:
1506:                        // XXX how does x interact with box hierarchies (where
1507:                        // children are relative to their parents) and how about
1508:                        // margins? effective margins?
1509:                        box.containingBlockX = cbb.containingBlockX + cbb.leftMargin + cbb.leftBorderWidth;
1510:                        box.containingBlockY = cbb.containingBlockY + cbb.topMargin + cbb.topBorderWidth;
1511:                         */
1512:                        box.containingBlockWidth = cbb.contentWidth
1513:                                + leftPadding + rightPadding;
1514:                        box.containingBlockHeight = cbb.contentHeight
1515:                                + topPadding + bottomPadding;
1516:                        box.containingBlockX = leftBorderWidth;
1517:                        box.containingBlockY = topBorderWidth;
1518:                    } else {
1519:                        // LTR assumption: the top and left of the containing
1520:                        // block are the top and left content edges of the first
1521:                        // box generated by the ancestor, and the bottom and
1522:                        // right are the bottom and right content edges of the
1523:                        // last box of the ancestor.
1524:                        // XXX revisit this code once I have redone the way
1525:                        // inline boxes are handled.
1526:                        // XXX I don't quite understand this rule. Or if I do,
1527:                        // it will be difficult to compute - we don't know the
1528:                        // last box of the ancestor yet - we haven't added it!
1529:                        // For now, just use the containing block assigned to
1530:                        // the ancestor.
1531:                        LineBoxGroup lbg = null;
1532:
1533:                        if (box.getParent() instanceof  LineBoxGroup) {
1534:                            lbg = (LineBoxGroup) box.getParent();
1535:                        } else if ((box.getParent() != null)
1536:                                && box.getParent().getParent() instanceof  LineBox) {
1537:                            lbg = (LineBoxGroup) box.getParent().getParent();
1538:                        } else {
1539:                            // XXX #6464191 TODO How should be this handled?
1540:                            // In this case box.getParent() was ContainerBox of the Group Panel.
1541:                            //                    assert false;
1542:                        }
1543:
1544:                        if (lbg != null) {
1545:                            box.containingBlockX = lbg.containingBlockX;
1546:                            box.containingBlockY = lbg.containingBlockY;
1547:                            box.containingBlockWidth = lbg.containingBlockWidth;
1548:                            box.containingBlockHeight = lbg.containingBlockHeight;
1549:                        }
1550:                    }
1551:                } else if (boxType == BoxType.FIXED) {
1552:                    // If the element has 'position: fixed', the containing
1553:                    // block is established by the viewport.  
1554:                    box.containingBlockX = 0;
1555:                    box.containingBlockY = 0;
1556:                    box.containingBlockWidth = context.initialWidth;
1557:                    box.containingBlockHeight = context.initialHeight;
1558:                    box.setPositionedBy(context.initialCB);
1559:                } else {
1560:                    assert false : boxType;
1561:                }
1562:            }
1563:
1564:            /** Position the box - set its x and y values relative to the
1565:             * parent's border edge. Positioning depends on the box' BoxType.
1566:             * This method should get called after margins etc. have been
1567:             * computed properly (e.g. all AUTO values must be resolved).
1568:             */
1569:            protected void positionBox(CssBox box, FormatContext context) {
1570:                // LineBoxes will do special handling of inline boxes; this
1571:                // assert ensures that the LineBox overrides this method and
1572:                // handles it correctly.
1573:                //assert box.isBlockLevel();
1574:                BoxType type = box.getBoxType();
1575:
1576:                if ((type == BoxType.STATIC) || (type == BoxType.LINEBOX)) {
1577:                    positionBlockBox(box, context);
1578:                } else if (type == BoxType.ABSOLUTE) {
1579:                    positionAbsoluteBox(box);
1580:                } else if (type == BoxType.FLOAT) {
1581:                    positionFloatBox(box);
1582:                } else if (type == BoxType.RELATIVE) {
1583:                    // XXX hm, shouldn't relative boxes be allowed in inline ctx
1584:                    // too?  The LineBox needs to call this method as well!
1585:                    positionRelativeBox(box, context);
1586:                } else if (type == BoxType.FIXED) {
1587:                    positionFixedBox(box, context);
1588:                } else {
1589:                    assert false : type;
1590:                }
1591:            }
1592:
1593:            private int calculateMargin(int prevMargin, int boxMargin) {
1594:                // Handle negative offsets
1595:                if ((prevMargin >= 0) && (boxMargin >= 0)) {
1596:                    // Normal case
1597:                    //  The larger of adjacent margin values is used. 
1598:                    return Math.max(prevMargin, boxMargin);
1599:
1600:                    // OLD:
1601:                } else if ((prevMargin < 0) && (boxMargin < 0)) {
1602:                    // If the adjacent margins are all negative, the larger
1603:                    // of the negative values is used.
1604:                    // XXX this is not how I re-read the spec; it says "If
1605:                    // there are no positive margins, the absolute maximum
1606:                    // of the negative adjoining margins is deducted from
1607:                    // zero."   So I take abs
1608:                    //margin = Math.max(-prevMargin, -boxMargin);
1609:                    return Math.min(prevMargin, boxMargin);
1610:                } else {
1611:                    // If positive and negative vertical margins are
1612:                    // adjacent, the value should be collapsed thus: the
1613:                    // largest of the negative margin values should be
1614:                    // subtracted from the largest positive margin value.
1615:                    if ((prevMargin >= 0) && (boxMargin < 0)) {
1616:                        return prevMargin + boxMargin;
1617:                    } else {
1618:                        assert (prevMargin < 0) && (boxMargin >= 0);
1619:                        return boxMargin + prevMargin;
1620:                    }
1621:                }
1622:            }
1623:
1624:            /** Position a box in block formatting context
1625:             * @todo See computeEffectiveMargins and combine these
1626:             */
1627:            private void positionBlockBox(CssBox box, FormatContext context) {
1628:                CssBox parentBox = box.getParent();
1629:                assert parentBox != null;
1630:
1631:                // 9.4.1: each box's left outer edge touches the left edge of the
1632:                // containing block
1633:                // This means that the distance between the child's border
1634:                // edge and the parent's border edge, which we measure x relative to,
1635:                // is parent padding plus child margin (since the parent padding
1636:                // edge is aligned with the child outer edge. To get to the parent
1637:                // border edge from the parent padding edge we add the parent padding,
1638:                // and to get to the child border edge from the child outer edge,
1639:                // we add the child margin.)
1640:                box.setX(parentBox.leftPadding + parentBox.leftBorderWidth);
1641:
1642:                // XXX Tables are block tags -- sorta -- but need different behavior
1643:                // here. In particular, they should also be indented by floating
1644:                // boxes:
1645:                // compute y first, set to targetY
1646:                //int leftEdge = context.getLeftEdge(box, targetY, box.getHeight());
1647:                // TODO: look for "clear" property to clear floats - see section
1648:                // 9.5.2 of the CSS2.1 spec
1649:                // Collapsing vertical margins: specified in 8.3.1
1650:                CssBox prevNormalBox = box.getPrevNormalBlockBox();
1651:
1652:                if (prevNormalBox != null) {
1653:                    if (prevNormalBox instanceof  LineBoxGroup) {
1654:                        prevNormalBox.computeVerticalLengths(context);
1655:                    }
1656:                    int newY = prevNormalBox.getY()
1657:                            + prevNormalBox.getHeight()
1658:                            + calculateMargin(prevNormalBox
1659:                                    .getCollapsedBottomMargin(), box
1660:                                    .getCollapsedTopMargin());
1661:                    box.setY(newY);
1662:                    box.effectiveTopMargin = 0;
1663:                } else {
1664:                    // Else: this is the first normal block box we're adding;
1665:                    // this means we need to consider collapsing the nested
1666:                    // margins.
1667:                    // Margins should only collapse if there is no padding or
1668:                    // border separating them
1669:                    if ((parentBox.topBorderWidth == 0)
1670:                            && (parentBox.topPadding == 0)) {
1671:                        // Yes - collapse margins!
1672:                        // Collapse our parentBox.topMargin with box.topMargin -
1673:                        // except since this has a cumulative effect, gotta
1674:                        // collapse with the EFFECTIVE margin instead!
1675:                        // Handle negative offsets
1676:                        //int margin;
1677:                        int margin = parentBox.getCollapsedTopMargin();
1678:
1679:                        /*
1680:                        //int parentMargin = parentBox.topMargin;
1681:                        //int boxMargin = box.effectiveTopMargin;
1682:                        int parentMargin = parentBox.getCollapsedTopMargin();
1683:                        int boxMargin = box.getcollapsedMargin();
1684:
1685:                        if (parentMargin >= 0 && boxMargin >= 0) {
1686:                            // Normal case
1687:                            //  The larger of adjacent margin values is used.
1688:                            margin =
1689:                                Math.max(parentMargin, boxMargin);
1690:                            // OLD:
1691:                        } else if (
1692:                            parentMargin < 0 && boxMargin < 0) {
1693:
1694:                            // If the adjacent margins are all negative, the larger
1695:                            // of the negative values is used.
1696:
1697:                            // XXX this is not how I re-read the spec; it says "If
1698:                            // there are no positive margins, the absolute maximum
1699:                            // of the negative adjoining margins is deducted from
1700:                            // zero."   So I take abs
1701:                            //margin = Math.max(-parentMargin, -boxMargin);
1702:                            margin =
1703:                                Math.min(parentMargin, boxMargin);
1704:                        } else {
1705:                            // If positive and negative vertical margins are
1706:                            // adjacent, the value should be collapsed thus: the
1707:                            // largest of the negative margin values should be
1708:                            // subtracted from the largest positive margin value.
1709:                            if (parentMargin >= 0
1710:                                && boxMargin < 0) {
1711:                                margin = parentMargin + boxMargin;
1712:                            } else {
1713:                                assert parentMargin < 0
1714:                                    && boxMargin >= 0;
1715:                                margin = boxMargin + parentMargin;
1716:                            }
1717:                        }
1718:                         */
1719:                        //6406309 fix
1720:                        //parentBox.effectiveTopMargin = margin;
1721:                        box.effectiveTopMargin = 0; // collapsed
1722:
1723:                        // All coordinates in this box will be relative to
1724:                        // the effectiveTopMargin
1725:                        // box.setY(0); // Since we've collapsed the box with our
1726:                        // own top margin, the box' border edge is located at
1727:                        // the same position as the paren'ts border edge.
1728:                        box.setY(parentBox.topBorderWidth);
1729:                    } else {
1730:                        // No, don't collapse margins
1731:                        box.setY(parentBox.topPadding
1732:                                + parentBox.topBorderWidth //);
1733:                                + box.effectiveTopMargin); // XXX Already added?
1734:
1735:                        parentBox.effectiveTopMargin = parentBox.topMargin;
1736:                        box.effectiveTopMargin = 0;
1737:                    }
1738:                }
1739:
1740:                //in case the box is clear box, we also need to look for a previous 
1741:                //float box
1742:                if (box.isClearBox()/* && LineBoxGroup.findClearContainer(box) == null*/) {
1743:                    CssBox prevFloatBox = context.getPrevFloatingForClear(box);
1744:                    if (prevFloatBox != null) {
1745:                        int newY = context.adjustY(prevFloatBox.getHeight()
1746:                                + prevFloatBox.bottomMargin
1747:                                + prevFloatBox.topMargin, prevFloatBox, this )
1748:                                + box.topMargin;
1749:                        if (newY > box.getY()) {
1750:                            box.setY(newY);
1751:                        }
1752:                    }
1753:
1754:                }
1755:
1756:                /*
1757:                if ((context.floats != null) && (box.getBoxType() != BoxType.LINEBOX) &&
1758:                        (box.getElement() != null)) {
1759:                //            Value clear = CssLookup.getValue(box.getElement(), XhtmlCss.CLEAR_INDEX);
1760:                    CssValue cssClear = CssProvider.getEngineService().getComputedValueForElement(box.getElement(), XhtmlCss.CLEAR_INDEX);
1761:
1762:                //            if (clear != CssValueConstants.NONE_VALUE) {
1763:                    if (!CssProvider.getValueService().isNoneValue(cssClear)) {
1764:                //                box.clearTop(context, clear);
1765:                        box.clearTop(context, cssClear);
1766:                    }
1767:                }
1768:                 */
1769:            }
1770:
1771:            /** Position a box in block formatting context */
1772:            private void positionRelativeBox(CssBox box, FormatContext context) {
1773:                positionBlockBox(box, context);
1774:                box.setLocation(box.getX() + box.left, box.getY() + box.top);
1775:            }
1776:
1777:            /** Position a box by absolute coordinates (where the coordinates
1778:             * are relative to the containing block
1779:             */
1780:            private void positionAbsoluteBox(CssBox box) {
1781:                box.setLocation(box.left + leftBorderWidth, box.top
1782:                        + topBorderWidth);
1783:            }
1784:
1785:            /** Position a box that is fixed to the viewport */
1786:            private void positionFixedBox(CssBox box, FormatContext context) {
1787:                ViewportBox vb = context.initialCB;
1788:                JViewport viewport = vb.getViewport();
1789:
1790:                if (viewport != null) {
1791:                    Point p = viewport.getViewPosition();
1792:                    box.setLocation(box.left + p.x, box.top + p.y);
1793:                } else {
1794:                    box.setLocation(box.left, box.top);
1795:                }
1796:            }
1797:
1798:            /** Position a box that is floated left or right
1799:             * <p>
1800:             * See section 9.5.1 for details.
1801:             * </p>
1802:             */
1803:            private void positionFloatBox(CssBox box) {
1804:                // Most of the work done in the LineBoxGroup!
1805:                CssBox parentBox = box.getParent();
1806:                assert parentBox != null;
1807:
1808:                //        Value floating = CssLookup.getValue(box.getElement(), XhtmlCss.FLOAT_INDEX);
1809:                CssValue cssFloating = CssProvider.getEngineService()
1810:                        .getComputedValueForElement(box.getElement(),
1811:                                XhtmlCss.FLOAT_INDEX);
1812:                boolean leftSide;
1813:
1814:                //        if (floating == CssValueConstants.LEFT_VALUE) {
1815:                if (CssProvider.getValueService().isLeftValue(cssFloating)) {
1816:                    leftSide = true;
1817:                    //        } else {
1818:                    //            assert floating == CssValueConstants.RIGHT_VALUE;
1819:                } else if (CssProvider.getValueService().isRightValue(
1820:                        cssFloating)) {
1821:
1822:                    // None not permitted since we wouldn't have identified a
1823:                    // float boxtype in the first place in BoxType.getBoxType
1824:                    leftSide = false;
1825:                } else {
1826:                    ErrorManager.getDefault().notify(
1827:                            ErrorManager.INFORMATIONAL,
1828:                            new IllegalStateException(
1829:                                    "Unexpected value, cssFloating="
1830:                                            + cssFloating));
1831:                    return;
1832:                }
1833:
1834:                // 9.4.1: each box's left outer edge touches the left edge of the
1835:                // containing block
1836:                // This means that the distance between the child's border
1837:                // edge and the parent's border edge, which we measure x relative to,
1838:                // is parent padding plus child margin (since the parent padding
1839:                // edge is aligned with the child outer edge. To get to the parent
1840:                // border edge from the parent padding edge we add the parent padding,
1841:                // and to get to the child border edge from the child outer edge,
1842:                // we add the child margin.)
1843:                if (leftSide) {
1844:                    box.setX(parentBox.leftPadding + parentBox.leftBorderWidth);
1845:
1846:                    // + box.leftMargin); // Already added?
1847:                } else {
1848:                    //            System.out.println("WRONG RIGHT POSITIONING!");
1849:                    //            box.setX(parentBox.leftPadding + parentBox.leftBorderWidth);
1850:                    // XXX #99707 Based on the left float positioning above.
1851:                    box.setX(parentBox.width - parentBox.rightPadding
1852:                            - parentBox.rightBorderWidth);
1853:                }
1854:
1855:                // TODO: look for "clear" property to clear floats - see section
1856:                // 9.5.2 of the CSS2.1 spec
1857:                // Collapsing vertical margins: specified in 8.3.1
1858:                CssBox prevBox = box.getPrevNormalBox();
1859:
1860:                if (prevBox != null) {
1861:                    // We have a previous box - place the new box below it,
1862:                    // offset by the collapsed margins -
1863:                    // Handle negative offsets
1864:                    int margin;
1865:
1866:                    //int prevMargin = prevBox.effectiveBottomMargin;
1867:                    //int boxMargin = box.effectiveTopMargin;
1868:                    int prevMargin = prevBox.getCollapsedBottomMargin();
1869:                    int boxMargin = box.getCollapsedTopMargin();
1870:
1871:                    if ((prevMargin >= 0) && (boxMargin >= 0)) {
1872:                        // Normal case
1873:                        //  The larger of adjacent margin values is used. 
1874:                        margin = Math.max(prevMargin, boxMargin);
1875:
1876:                        // OLD:
1877:                    } else if ((prevMargin < 0) && (boxMargin < 0)) {
1878:                        // If the adjacent margins are all negative, the larger
1879:                        // of the negative values is used.
1880:                        // XXX this is not how I re-read the spec; it says "If
1881:                        // there are no positive margins, the absolute maximum
1882:                        // of the negative adjoining margins is deducted from
1883:                        // zero."   So I take abs
1884:                        //margin = Math.max(-prevMargin, -boxMargin);
1885:                        margin = Math.min(prevMargin, boxMargin);
1886:                    } else {
1887:                        // If positive and negative vertical margins are
1888:                        // adjacent, the value should be collapsed thus: the
1889:                        // largest of the negative margin values should be
1890:                        // subtracted from the largest positive margin value.
1891:                        if ((prevMargin >= 0) && (boxMargin < 0)) {
1892:                            margin = prevMargin + boxMargin;
1893:                        } else {
1894:                            assert (prevMargin < 0) && (boxMargin >= 0);
1895:                            margin = boxMargin + prevMargin;
1896:                        }
1897:                    }
1898:
1899:                    box.setY( /*parentBox.topBorderWidth*/
1900:                    prevBox.getY() + prevBox.getHeight() + margin);
1901:                    box.effectiveTopMargin = 0;
1902:                } else {
1903:                    // Else: this is the first normal block box we're adding;
1904:                    // this means we need to consider collapsing the nested
1905:                    // margins.
1906:                    // Margins should only collapse if there is no padding or
1907:                    // border separating them
1908:                    if ((parentBox.topBorderWidth == 0)
1909:                            && (parentBox.topPadding == 0)) {
1910:                        // Yes - collapse margins!
1911:                        // Collapse our parentBox.topMargin with box.topMargin -
1912:                        // except since this has a cumulative effect, gotta
1913:                        // collapse with the EFFECTIVE margin instead!
1914:                        // Handle negative offsets
1915:                        //int margin;
1916:                        int margin = parentBox.getCollapsedTopMargin();
1917:
1918:                        /*
1919:                        //int parentMargin = parentBox.topMargin;
1920:                        //int boxMargin = box.effectiveTopMargin;
1921:                        int parentMargin = parentBox.getCollapsedTopMargin();
1922:                        int boxMargin = box.getcollapsedMargin();
1923:
1924:                        if (parentMargin >= 0 && boxMargin >= 0) {
1925:                            // Normal case
1926:                            //  The larger of adjacent margin values is used.
1927:                            margin =
1928:                                Math.max(parentMargin, boxMargin);
1929:                            // OLD:
1930:                        } else if (
1931:                            parentMargin < 0 && boxMargin < 0) {
1932:
1933:                            // If the adjacent margins are all negative, the larger
1934:                            // of the negative values is used.
1935:
1936:                            // XXX this is not how I re-read the spec; it says "If
1937:                            // there are no positive margins, the absolute maximum
1938:                            // of the negative adjoining margins is deducted from
1939:                            // zero."   So I take abs
1940:                            //margin = Math.max(-parentMargin, -boxMargin);
1941:                            margin =
1942:                                Math.min(parentMargin, boxMargin);
1943:                        } else {
1944:                            // If positive and negative vertical margins are
1945:                            // adjacent, the value should be collapsed thus: the
1946:                            // largest of the negative margin values should be
1947:                            // subtracted from the largest positive margin value.
1948:                            if (parentMargin >= 0
1949:                                && boxMargin < 0) {
1950:                                margin = parentMargin + boxMargin;
1951:                            } else {
1952:                                assert parentMargin < 0
1953:                                    && boxMargin >= 0;
1954:                                margin = boxMargin + parentMargin;
1955:                            }
1956:                        }
1957:                         */
1958:                        parentBox.effectiveTopMargin = margin;
1959:                        box.effectiveTopMargin = 0; // collapsed
1960:
1961:                        // All coordinates in this box will be relative to
1962:                        // the effectiveTopMargin
1963:                        // box.setY(0); // Since we've collapsed the box with our
1964:                        // own top margin, the box' border edge is located at
1965:                        // the same position as the paren'ts border edge.
1966:                        box.setY(parentBox.topBorderWidth);
1967:                    } else {
1968:                        // No, don't collapse margins
1969:                        box.setY(parentBox.topPadding
1970:                                + parentBox.topBorderWidth //);
1971:                                + box.effectiveTopMargin); // XXX Already added?
1972:
1973:                        parentBox.effectiveTopMargin = parentBox.topMargin;
1974:                        box.effectiveTopMargin = 0;
1975:                    }
1976:                }
1977:            }
1978:
1979:            //    /** Returns true if this box represents an inline span.  This is true for
1980:            //      * inline boxes that are not block tags, or are not inline tags that are
1981:            //      * absolutely positioned, or are replaced.
1982:            //     */
1983:            //    private boolean isSpan() {
1984:            //        return inline && !boxType.isAbsolutelyPositioned() && !replaced;
1985:            //    }
1986:            //    
1987:            //    private static boolean isTextualBox(CssBox box) {
1988:            //        if (box == null) {
1989:            //            return false;
1990:            //        }
1991:            //        BoxType boxType = box.getBoxType();
1992:            //        return boxType == BoxType.TEXT || boxType == BoxType.SPACE || boxType == BoxType.LINEBREAK;
1993:            //    }
1994:
1995:            /**
1996:             * NOTE: prevBox and nextBox refer to the siblings for
1997:             * the new LineBoxGroup to be created (if any), not where
1998:             * within the LineBoxGroup to add the inline box!
1999:             */
2000:            private void addToLineBox(CreateContext context, CssBox ibox,
2001:                    CssBox prevBox, CssBox nextBox) {
2002:                // Inline tags like <span> in flow context should simply include
2003:                // the children as normal children; the LineBoxGroup will organize
2004:                // them into LineBoxes
2005:
2006:                // XXX #117840 This shuffle seems to be wrong, commented out.
2007:                //        // XXX #105679 This doesn't know how to deal with the 'textual' boxes, adding those normally.
2008:                //        if (isSpan() && !isTextualBox(ibox)) {
2009:                //            addBox(ibox, prevBox, nextBox);
2010:                //        } else {
2011:                if (context.lineBox == null) {
2012:                    FontMetrics metrics = context.metrics;
2013:
2014:                    if (ibox.getBoxType() == BoxType.TEXT) {
2015:                        metrics = ((TextBox) ibox).getMetrics();
2016:                    } else if (ibox.getBoxType() == BoxType.SPACE) {
2017:                        metrics = ((SpaceBox) ibox).getMetrics();
2018:                    }
2019:
2020:                    context.lineBox = new LineBoxGroup(webform, getElement(),
2021:                            metrics);
2022:
2023:                    getBlockBox().addBox(context.lineBox, prevBox, nextBox);
2024:                }
2025:
2026:                context.lineBox.addBox(ibox, null, null);
2027:                //        }
2028:            }
2029:
2030:            /**
2031:             * Finish the current line box we're working on; a new
2032:             * addToLineBox call will generate a new line.
2033:             */
2034:            void finishLineBox(CreateContext context) {
2035:                if (context.lineBox == null) {
2036:                    return;
2037:                }
2038:
2039:                if (context.lineBox.isEmpty()) {
2040:                    return;
2041:                }
2042:
2043:                context.lineBox = null;
2044:            }
2045:
2046:            public int getPrefMinWidth() {
2047:                if (inline) {
2048:                    //            Value val = CssLookup.getValue(getElement(), XhtmlCss.WHITE_SPACE_INDEX);
2049:                    CssValue cssValue = CssProvider.getEngineService()
2050:                            .getComputedValueForElement(getElement(),
2051:                                    XhtmlCss.WHITE_SPACE_INDEX);
2052:                    //            if ((val == CssValueConstants.PRE_VALUE) || (val == CssValueConstants.NOWRAP_VALUE)) {
2053:                    if (CssProvider.getValueService().isPreValue(cssValue)
2054:                            || CssProvider.getValueService().isNoWrapValue(
2055:                                    cssValue)) {
2056:                        return getPrefWidth();
2057:                    }
2058:                }
2059:
2060:                int largest = 0;
2061:                int n = getBoxCount();
2062:
2063:                for (int i = 0; i < n; i++) {
2064:                    CssBox child = getBox(i);
2065:
2066:                    if (child.getBoxType().isAbsolutelyPositioned()) {
2067:                        continue;
2068:                    }
2069:
2070:                    int min = child.getPrefMinWidth();
2071:
2072:                    if (min > largest) {
2073:                        largest = min;
2074:                    }
2075:                }
2076:
2077:                if (leftMargin != AUTO) {
2078:                    largest += leftMargin;
2079:                }
2080:
2081:                if (rightMargin != AUTO) {
2082:                    largest += rightMargin;
2083:                }
2084:
2085:                // Borders and padding can't be left auto, can they?
2086:                largest += (leftBorderWidth + leftPadding + rightBorderWidth + rightPadding);
2087:
2088:                int curr = super .getPrefMinWidth();
2089:
2090:                if (curr > largest) {
2091:                    largest = curr;
2092:                }
2093:
2094:                return largest;
2095:            }
2096:
2097:            public int getPrefWidth() {
2098:                int largest = 0;
2099:                int n = getBoxCount();
2100:
2101:                if (inline && !boxType.isAbsolutelyPositioned()) {
2102:                    // Let the line box compute the size of these children
2103:                    CssBox curr = getParent();
2104:
2105:                    while ((curr != null) && !(curr instanceof  LineBoxGroup)) {
2106:                        curr = curr.getParent();
2107:                    }
2108:
2109:                    if (curr != null) {
2110:                        largest = ((LineBoxGroup) curr).getPrefWidth(boxes);
2111:                    } else {
2112:                        // Shouldn't happen - this is just for safety right now
2113:                        // Inline tag: add up all the children and use that
2114:                        for (int i = 0; i < n; i++) {
2115:                            CssBox child = getBox(i);
2116:
2117:                            if (child.getBoxType().isAbsolutelyPositioned()) {
2118:                                continue;
2119:                            }
2120:
2121:                            // XXX does not properly handle LineBox.LINEBREAK
2122:                            largest += child.getPrefWidth();
2123:                        }
2124:                    }
2125:                } else {
2126:                    // Block tag: find the widest child and use that
2127:                    for (int i = 0; i < n; i++) {
2128:                        CssBox child = getBox(i);
2129:
2130:                        if (child.getBoxType().isAbsolutelyPositioned()) {
2131:                            continue;
2132:                        }
2133:
2134:                        int min = child.getPrefWidth();
2135:
2136:                        if (min > largest) {
2137:                            largest = min;
2138:                        }
2139:                    }
2140:                }
2141:
2142:                if (leftMargin != AUTO) {
2143:                    largest += leftMargin;
2144:                }
2145:
2146:                if (rightMargin != AUTO) {
2147:                    largest += rightMargin;
2148:                }
2149:
2150:                // XXX #124104 There are some hacking their border sizes into contentHeight.
2151:                // see FormComponentBox.
2152:                if (!isBorderSizeIncluded()) {
2153:                    // Borders and padding can't be left auto, can they?
2154:                    largest += (leftBorderWidth + leftPadding
2155:                            + rightBorderWidth + rightPadding);
2156:                }
2157:
2158:                int curr = super .getPrefWidth();
2159:
2160:                if (curr > largest) {
2161:                    largest = curr;
2162:                }
2163:
2164:                return largest;
2165:            }
2166:
2167:            protected boolean hasNormalBlockLevelChildren() {
2168:                // XXX This gets tricky. Children boxes may be anonymous
2169:                // block boxes - but I haven't been creating those!
2170:                // Figure out how to handle this....
2171:                int n = getBoxCount();
2172:
2173:                for (int i = 0; i < n; i++) {
2174:                    CssBox child = getBox(i);
2175:
2176:                    if (child.getBoxType().isNormalFlow()) {
2177:                        if (!child.isInlineBox()) {
2178:                            return true;
2179:                        }
2180:                    }
2181:                }
2182:
2183:                return false;
2184:            }
2185:
2186:            /**
2187:             * Notify the parent that the given child has been resized.
2188:             * This might cause a reflow.
2189:             * @return The topmost box in the hierarchy which had its size changed.
2190:             */
2191:            protected CssBox notifyChildResize(CssBox child,
2192:                    FormatContext context) {
2193:                // Update positions to accomodate the new dimensions
2194:                // of the given child
2195:                // We don't check the parent pointer because pageBox should
2196:                // override this method
2197:                if (child.getParentIndex() != -1) {
2198:                    positionBox(child, context);
2199:                }
2200:
2201:                // If this is an absolutely positioned box, the parent has
2202:                // no interest in our dimensions so we don't need to
2203:                // propagate the size change.
2204:                //if (boxType.isAbsolutelyPositioned()) {
2205:                if (child.getBoxType().isAbsolutelyPositioned()) {
2206:                    return child;
2207:                }
2208:
2209:                // Move siblings further down in the flow
2210:                if (child.getBoxType().isNormalFlow()) {
2211:                    // Adjust the remaining normal flow boxes too
2212:                    int i = child.getParentIndex() + 1;
2213:                    int n = getBoxCount();
2214:
2215:                    for (; i < n; i++) {
2216:                        CssBox sibling = getBox(i);
2217:
2218:                        if (sibling.getBoxType().isNormalFlow()) {
2219:                            positionBox(sibling, context);
2220:                        }
2221:                    }
2222:                }
2223:
2224:                ContainerBox parent = getParent();
2225:                if (parent == null) {
2226:                    return this ; // page box: no furhter propagation is necessary
2227:
2228:                    // its contentHeight/height is computed from the extents,
2229:                    // which we will update manually
2230:                }
2231:
2232:                int oldWidth = contentWidth;
2233:                int oldHeight = contentHeight;
2234:                parent.layoutChild(this , context, false);
2235:
2236:                // What about left/top, etc.?
2237:                // Have the dimensions changed? If not, we're done
2238:                if ((contentWidth == oldWidth) && (contentHeight == oldHeight)) {
2239:                    // TODO what if the effective margin has changed?
2240:                    // That might require us to propagate the change upwards
2241:                    // too!
2242:
2243:                    /*
2244:                    if (child.getParentIndex() != -1) {
2245:                        positionBox(child, context);
2246:                    }
2247:                     */
2248:                    return child;
2249:                }
2250:
2251:                // Otherwise, propagate the dimension change notification
2252:                // to the parent so it can adjust its positions
2253:                return parent.notifyChildResize(this , context);
2254:            }
2255:
2256:            protected void paintBox(Graphics g, int x, int y, int w, int h) {
2257:                super .paintBox(g, x, y, w, h);
2258:
2259:                //        if (grid && GridHandler.getInstance().grid()) {
2260:                //        if (grid && getWebForm().getGridHandler().grid()) {
2261:                //        if (grid && GridHandler.getDefault().isGrid()) {
2262:                if (grid && webform.isGridShow()) {
2263:                    if (hidden && !(this  instanceof  PageBox)) { // paint grid for the root pagebox!
2264:
2265:                        return;
2266:                    }
2267:
2268:                    paintGrid(g, x, y, w, h);
2269:                }
2270:            }
2271:
2272:            protected void paintGrid(Graphics g, int x, int y, int w, int h) {
2273:                //long start = System.currentTimeMillis();
2274:                int width = w;
2275:                int height = h;
2276:
2277:                // On my U60, this takes roughly 24S-34 ms for the default
2278:                // screensize
2279:                Color oldColor = g.getColor();
2280:                Color gridColor = webform.getColors().gridColor;
2281:                assert gridColor != null;
2282:                g.setColor(gridColor);
2283:
2284:                //        final int gridWidth = GridHandler.getInstance().getGridWidth();
2285:                //        final int gridHeight = GridHandler.getInstance().getGridHeight();
2286:                //        final int gridTraceWidth = GridHandler.getInstance().getGridTraceWidth();
2287:                //        final int gridTraceHeight = GridHandler.getInstance().getGridTraceHeight();
2288:                //        final int gridOffset = GridHandler.getInstance().getGridOffset();
2289:                //        GridHandler gridHandler = getWebForm().getGridHandler();
2290:                //        GridHandler gridHandler = GridHandler.getDefault();
2291:                //        final int gridWidth = gridHandler.getGridWidth();
2292:                //        final int gridHeight = gridHandler.getGridHeight();
2293:                //        final int gridTraceWidth = gridHandler.getGridTraceWidth();
2294:                //        final int gridTraceHeight = gridHandler.getGridTraceHeight();
2295:                //        final int gridOffset = gridHandler.getGridOffset();
2296:                final int gridWidth = webform.getGridWidth();
2297:                final int gridHeight = webform.getGridHeight();
2298:                final int gridTraceWidth = webform.getGridTraceWidth();
2299:                final int gridTraceHeight = webform.getGridTraceHeight();
2300:                //        final int gridOffset = webform.getGridOffset();
2301:
2302:                // Draw a plain grid (one dot on each gridsize boundary
2303:                //for (int x = gridOffset; x < width; x += gridSize) {
2304:                //    for (int y = gridOffset; y < height; y += gridSize) {
2305:                //        //g.drawLine(x, y, x, y);
2306:                //        // Is this faster?
2307:                //        g.fillRect(x, y, 1, 1);
2308:                //    }
2309:                //}
2310:                //        int xstart = gridOffset;
2311:                int xstart = 0;
2312:
2313:                // Draw grid with smaller trace lines along the axes
2314:                for (int xp = xstart; xp < width; xp += gridWidth) {
2315:                    for (int yp = gridTraceHeight; yp < height; yp += gridTraceHeight) {
2316:                        //g.drawLine(xp, yp, xp, yp);
2317:                        // Is this faster?
2318:                        g.fillRect(x + xp, y + yp, 1, 1);
2319:                    }
2320:                }
2321:
2322:                //        int ystart = gridOffset;
2323:                int ystart = 0;
2324:
2325:                // This is going to redraw all the pixels on the gridsize*gridsize
2326:                // grid - I can count gridTrace's and skip these.  TODO.
2327:                for (int xp = gridTraceWidth; xp < width; xp += gridTraceWidth) {
2328:                    for (int yp = ystart; yp < height; yp += gridHeight) {
2329:                        //g.drawLine(xp, yp, xp, yp);
2330:                        // Is this faster?
2331:                        g.fillRect(x + xp, y + yp, 1, 1);
2332:                    }
2333:                }
2334:
2335:                g.setColor(oldColor);
2336:
2337:                //long end = System.currentTimeMillis();
2338:                //System.out.println("Scan time for grid painting = " + (end-start) + " ms");
2339:            }
2340:
2341:            /** The iframe box should be clipped */
2342:            public void paint(Graphics g, int px, int py) {
2343:                if (clipOverflow) {
2344:                    g.getClipBounds(sharedClipRect);
2345:
2346:                    int cx = sharedClipRect.x;
2347:                    int cy = sharedClipRect.y;
2348:                    int cw = sharedClipRect.width;
2349:                    int ch = sharedClipRect.height;
2350:                    g.clipRect(px + leftMargin + getX(), py
2351:                            + effectiveTopMargin + getY(), width, height);
2352:                    super .paint(g, px, py);
2353:                    g.setClip(cx, cy, cw, ch);
2354:                } else {
2355:                    super .paint(g, px, py);
2356:                }
2357:            }
2358:
2359:            /** Prints a listing of this container box.
2360:             * @see java.awt.Container#list(java.io.PrintStream, int) */
2361:            public void list(PrintStream out, int indent) {
2362:                super .list(out, indent);
2363:
2364:                CssBox[] boxes = getBoxes();
2365:                for (int i = 0; i < boxes.length; i++) {
2366:                    CssBox box = boxes[i];
2367:                    if (box != null) {
2368:                        box.list(out, indent + 1);
2369:                    }
2370:                }
2371:            }
2372:
2373:            /** Prints a listing of this container box.
2374:             * @see java.awt.Container#list(java.io.PrintWriter, int) */
2375:            public void list(PrintWriter out, int indent) {
2376:                super .list(out, indent);
2377:
2378:                CssBox[] boxes = getBoxes();
2379:                for (int i = 0; i < boxes.length; i++) {
2380:                    CssBox box = boxes[i];
2381:                    if (box != null) {
2382:                        box.list(out, indent + 1);
2383:                    }
2384:                }
2385:            }
2386:
2387:            /** Finds all external form in this box tree. */
2388:            public WebForm[] findExternalForms() {
2389:                List<WebForm> externalForms = new ArrayList<WebForm>();
2390:                CssBox[] boxes = getBoxes();
2391:                for (CssBox box : boxes) {
2392:                    if (box instanceof  ExternalDocumentBox) {
2393:                        ExternalDocumentBox externalDocBox = (ExternalDocumentBox) box;
2394:                        WebForm externalForm = externalDocBox.getExternalForm();
2395:                        if (externalForm != null) {
2396:                            externalForms.add(externalForm);
2397:                        }
2398:                    } else if (box instanceof  ContainerBox) {
2399:                        ContainerBox containerBox = (ContainerBox) box;
2400:                        WebForm[] webForms = containerBox.findExternalForms();
2401:                        externalForms.addAll(Arrays.asList(webForms));
2402:                    }
2403:                }
2404:                return externalForms.toArray(new WebForm[externalForms.size()]);
2405:            }
2406:
2407:            /** Determine if the given element represents an inline tag
2408:             * @todo Move to Utilities ?
2409:             */
2410:            private/*public*/static boolean isInlineTag(CssValue cssDisplay,
2411:                    Element element, HtmlTag tag) {
2412:                ////        if (display == CssValueConstants.NONE_VALUE) {
2413:                //        if (CssProvider.getValueService().isNoneValue(cssDisplay)) {
2414:                //            return false;
2415:                //        }
2416:                //
2417:                ////        if ((display == CssValueConstants.BLOCK_VALUE) ||
2418:                ////                (display == CssValueConstants.LIST_ITEM_VALUE) ||
2419:                ////                (display == CssValueConstants.TABLE_VALUE) ||
2420:                ////                (
2421:                ////            /* These are not always block
2422:                ////            display == CssValueConstants.COMPACT_VALUE ||
2423:                ////            display == CssValueConstants.RUN_IN_VALUE ||
2424:                ////             */
2425:                ////            display == CssValueConstants.INLINE_BLOCK_VALUE)) {
2426:                //        if (CssProvider.getValueService().isBlockValue(cssDisplay)
2427:                //        || CssProvider.getValueService().isListItemValue(cssDisplay)
2428:                //        || CssProvider.getValueService().isTableValue(cssDisplay)
2429:                //        || CssProvider.getValueService().isInlineBlockValue(cssDisplay)){
2430:                //            return false;
2431:                ////        } else if (display == CssValueConstants.INLINE_VALUE) {
2432:                //        } else if (CssProvider.getValueService().isInlineValue(cssDisplay)) {
2433:                //            return true;
2434:                //
2435:                //            // TODO: Handle rest of constants appropriately.
2436:                //            // The "inline" boolean flag is too simplistic; we should
2437:                //            // store the formatting type here and do the right type
2438:                //            // of layout
2439:                //
2440:                //            /*
2441:                //              CssValueConstants.COMPACT_VALUE,
2442:                //              CssValueConstants.INLINE_TABLE_VALUE,
2443:                //              CssValueConstants.MARKER_VALUE,
2444:                //              CssValueConstants.RUN_IN_VALUE,
2445:                //              CssValueConstants.TABLE_VALUE,
2446:                //              CssValueConstants.TABLE_CAPTION_VALUE,
2447:                //              CssValueConstants.TABLE_CELL_VALUE,
2448:                //              CssValueConstants.TABLE_COLUMN_VALUE,
2449:                //              CssValueConstants.TABLE_COLUMN_GROUP_VALUE,
2450:                //              CssValueConstants.TABLE_FOOTER_GROUP_VALUE,
2451:                //              CssValueConstants.TABLE_HEADER_GROUP_VALUE,
2452:                //              CssValueConstants.TABLE_ROW_VALUE,
2453:                //              CssValueConstants.TABLE_ROW_GROUP_VALUE,
2454:                //             */
2455:                //        } else {
2456:                //            // Else - use tag default
2457:                //            if (tag == null) {
2458:                //                tag = HtmlTag.getTag(element.getTagName());
2459:                //            }
2460:                //
2461:                //            if (tag != null) {
2462:                //                return tag.isInlineTag();
2463:                //            }
2464:                //        }
2465:                //
2466:                //        return true;
2467:                return CssProvider.getValueService().isInlineTag(cssDisplay,
2468:                        element, tag);
2469:            }
2470:
2471:            /** If this is a block-level box, return self, otherwise
2472:             * return the nearest block-level ancestor box.
2473:             * Note that absolutely positioned inline boxes are considered
2474:             * block boxes, and so are replaced inline boxes (e.g. iframe, stringbox).
2475:             */
2476:            private ContainerBox getBlockBox() {
2477:                // XXX what about floats?
2478:                if (!inline || boxType.isAbsolutelyPositioned()) {
2479:                    return this ;
2480:                    //        } if (isSpan() && !isTextualBox(this)) {
2481:                    //            // XXX #117840 Improving the tree layout.
2482:                    //            return this;
2483:                } else {
2484:                    ContainerBox blockBox = this ;
2485:
2486:                    while (blockBox.inline
2487:                            && !blockBox.boxType.isAbsolutelyPositioned()
2488:                            && !blockBox.replaced
2489:                            || !(blockBox instanceof  ContainerBox)) {
2490:                        ContainerBox parent = blockBox.getParent();
2491:                        if (parent == null) {
2492:                            break;
2493:                        }
2494:                        blockBox = parent;
2495:                    }
2496:
2497:                    return blockBox;
2498:                }
2499:            }
2500:
2501:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.