Source Code Cross Referenced for LineBoxGroup.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 java.awt.Color;
0044:        import java.awt.FontMetrics;
0045:        import java.awt.Graphics;
0046:        import java.awt.Rectangle;
0047:        import java.util.ArrayList;
0048:        import java.util.List;
0049:
0050:        import org.netbeans.modules.visualweb.api.designer.DomProvider.DomPosition;
0051:        import org.netbeans.modules.visualweb.api.designer.cssengine.CssProvider;
0052:        import org.netbeans.modules.visualweb.api.designer.cssengine.CssValue;
0053:        import org.netbeans.modules.visualweb.designer.CssUtilities;
0054:        import org.netbeans.modules.visualweb.designer.DesignerPane;
0055:        import org.netbeans.modules.visualweb.designer.WebForm;
0056:        import org.netbeans.modules.visualweb.api.designer.cssengine.XhtmlCss;
0057:
0058:        import org.openide.ErrorManager;
0059:
0060:        import org.w3c.dom.Element;
0061:        import org.w3c.dom.Node;
0062:
0063:        /**
0064:         * This class represents a LineBoxGroup; a box representing
0065:         * a single Inline context, which will be rendered as a set
0066:         * of LineBoxes managed by this LineBoxGroup.
0067:         * This class also maintains floating boxes, since these are
0068:         * positioned along with line boxes (and in particular, if a float
0069:         * appears in the middle of a stack of line boxes, we need to know
0070:         * exactly where to put it - and only the LineBoxGroup can handle this.)
0071:         * @todo Rename to LineBoxGroup
0072:         *
0073:         * @author Tor Norbye
0074:         */
0075:        public class LineBoxGroup extends ContainerBox {
0076:            //private int maxWidth;
0077:            //private int nextX;
0078:            private final FontMetrics metrics;
0079:            private LineBox lineBox = null;
0080:            private int targetY;
0081:            //    private ArrayList floats = null;
0082:            List<CssBox> floats = null;
0083:            private BoxList allBoxes;
0084:
0085:            public LineBoxGroup(WebForm webform, Element element,
0086:                    FontMetrics metrics) {
0087:                // A LineBox isn't exactly an inline box, but it's NOT a block
0088:                // level box. Perhaps I should reverse the logic and call
0089:                // the constructor parameter "blocklevel" instead.
0090:                super (webform, element, BoxType.LINEBOX, true, false);
0091:
0092:                // XXX why am I passing element to super? I shouldn't do that
0093:                this .metrics = metrics;
0094:
0095:                effectiveTopMargin = 0; // Is this still necessary?
0096:                effectiveBottomMargin = 0;
0097:            }
0098:
0099:            /** LineBoxes do not have margins, borders, grids, etc. like regular
0100:             * boxes.
0101:             */
0102:            protected void initialize() {
0103:                effectiveTopMargin = 0;
0104:                effectiveBottomMargin = 0;
0105:            }
0106:
0107:            /** LineBoxes do not have margins, borders, grids, etc. like regular
0108:             * boxes.
0109:             */
0110:            protected void initializeInvariants() {
0111:            }
0112:
0113:            // Gotta override this one too since it gets called separately from initialize()
0114:            protected void initializeBackground() {
0115:            }
0116:
0117:            public FontMetrics getMetrics() {
0118:                return metrics;
0119:            }
0120:
0121:            /**
0122:             *  Report whether the line box is empty (contains no inline boxes).
0123:             *
0124:             *  @return true iff there are no inline boxes in this linebox.
0125:             */
0126:            public boolean isEmpty() {
0127:                return (allBoxes == null) || (allBoxes.size() == 0);
0128:            }
0129:
0130:            /**
0131:             * The actual "box list" (as seen by CssBox.getBoxCount())
0132:             * is not updated until we perform layout, since we'll need to
0133:             * create multiple intermediate line boxes to fit the contents
0134:             * depending on the actual layout width and float box positioning.
0135:             * TODO - consider changing this box into something else,
0136:             * e.g. LineBoxGroup
0137:             */
0138:            protected void addBox(CssBox box, CssBox prevBox, CssBox nextBox) {
0139:                assert box.isInlineBox() || (box.getBoxType() == BoxType.FLOAT);
0140:
0141:                if (allBoxes == null) {
0142:                    allBoxes = new BoxList(10); // XXX good default? Do statistics.
0143:                } else if ((box.getBoxType() == BoxType.SPACE)
0144:                        && (allBoxes != null)
0145:                        && (allBoxes.get(allBoxes.size() - 1).getBoxType() == BoxType.SPACE)) {
0146:                    // Suppress repeated spaces. I really should make this into
0147:                    // an assertion and make it easier for clients of this method
0148:                    // to determine if we've already put a space box in so they
0149:                    // can avoid creating the box itself.
0150:                    return;
0151:                }
0152:
0153:                // XXX #109446 Ensure new box of another component is not put
0154:                // inbetween of two boxes belonging to other component.
0155:                if (prevBox != null) {
0156:                    Element newComponentRootElement = ModelViewMapper
0157:                            .findClosestComponentRootElement(webform, box
0158:                                    .getElement());
0159:                    Element prevComponentRootElement = ModelViewMapper
0160:                            .findClosestComponentRootElement(webform, prevBox
0161:                                    .getElement());
0162:                    if (newComponentRootElement != prevComponentRootElement) {
0163:                        CssBox tmpNextBox = getNextCssBox(allBoxes, prevBox);
0164:                        while (tmpNextBox != null) {
0165:                            Element nextComponentRootElement = ModelViewMapper
0166:                                    .findClosestComponentRootElement(webform,
0167:                                            tmpNextBox.getElement());
0168:                            if (prevComponentRootElement == nextComponentRootElement) {
0169:                                prevBox = tmpNextBox;
0170:                                nextBox = null;
0171:                                tmpNextBox = getNextCssBox(allBoxes, tmpNextBox);
0172:                            } else {
0173:                                break;
0174:                            }
0175:                        }
0176:                    }
0177:                }
0178:                if (nextBox != null) {
0179:                    Element newComponentRootElement = ModelViewMapper
0180:                            .findClosestComponentRootElement(webform, box
0181:                                    .getElement());
0182:                    Element nextComponentRootElement = ModelViewMapper
0183:                            .findClosestComponentRootElement(webform, nextBox
0184:                                    .getElement());
0185:                    if (newComponentRootElement != nextComponentRootElement) {
0186:                        CssBox tmpPrevBox = getPreviousCssBox(allBoxes, nextBox);
0187:                        while (tmpPrevBox != null) {
0188:                            Element prevComponentRootElement = ModelViewMapper
0189:                                    .findClosestComponentRootElement(webform,
0190:                                            tmpPrevBox.getElement());
0191:                            if (prevComponentRootElement == nextComponentRootElement) {
0192:                                prevBox = null;
0193:                                nextBox = tmpPrevBox;
0194:                                tmpPrevBox = getPreviousCssBox(allBoxes,
0195:                                        tmpPrevBox);
0196:                            } else {
0197:                                break;
0198:                            }
0199:                        }
0200:                    }
0201:                }
0202:
0203:                allBoxes.add(box, prevBox, nextBox);
0204:
0205:                // XXX #98826 Very suspicoius code leading to the issue.
0206:                // Wrong parentage, while the boxes in the 'allBoxes' BoxList are not the real chilren,
0207:                // the real chilidren are kept in the 'boxes' BoxList.
0208:                // However to comment out the nexst line doesn't work either, a messy impl.
0209:                box.setParent(this );
0210:                box.setPositionedBy(this );
0211:            }
0212:
0213:            private static CssBox getNextCssBox(BoxList boxList, CssBox cssBox) {
0214:                if (boxList == null || cssBox == null) {
0215:                    return null;
0216:                }
0217:
0218:                int boxIndex = boxList.indexOf(cssBox);
0219:                int nextBoxIndex = boxIndex < boxList.size() - 1 ? boxIndex + 1
0220:                        : -1;
0221:                if (nextBoxIndex == -1) {
0222:                    return null;
0223:                } else {
0224:                    return boxList.get(nextBoxIndex);
0225:                }
0226:            }
0227:
0228:            private static CssBox getPreviousCssBox(BoxList boxList,
0229:                    CssBox cssBox) {
0230:                if (boxList == null || cssBox == null) {
0231:                    return null;
0232:                }
0233:
0234:                int boxIndex = boxList.indexOf(cssBox);
0235:                int previousBoxIndex = boxIndex > 0 ? boxIndex - 1 : -1;
0236:                if (previousBoxIndex == -1) {
0237:                    return null;
0238:                } else {
0239:                    return boxList.get(previousBoxIndex);
0240:                }
0241:            }
0242:
0243:            /**
0244:             * Remove a box from the "master" box list, not the actual
0245:             * children list (which contains line boxes)
0246:             */
0247:            @Override
0248:            protected boolean removeBox(CssBox box) {
0249:                if (allBoxes == null) {
0250:                    ErrorManager.getDefault().log(
0251:                            "Unexpected removeBox " + box
0252:                                    + ": lbg already empty");
0253:
0254:                    return false;
0255:                } else {
0256:                    boolean ret = allBoxes.remove(box);
0257:
0258:                    //            // XXX #109306 Remove also sibling boxes representing the same element.
0259:                    //            // XXX Why they don't have common parent?
0260:                    //            Element element = box.getElement();
0261:                    //            if (element != null) {
0262:                    //                int size = allBoxes.size();
0263:                    //                List<CssBox> toRemove = new ArrayList<CssBox>();
0264:                    //                for (int i = 0; i < size; i++) {
0265:                    //                    CssBox siblingBox = allBoxes.get(i);
0266:                    //                    if (siblingBox == null) {
0267:                    //                        continue;
0268:                    //                    }
0269:                    //                    if (element == siblingBox.getElement()) {
0270:                    //                        toRemove.add(siblingBox);
0271:                    //                    }
0272:                    //                }
0273:                    //                for (CssBox siblingBoxToRemove : toRemove) {
0274:                    //                    allBoxes.remove(siblingBoxToRemove);
0275:                    //                }
0276:                    //            }
0277:
0278:                    if (allBoxes.size() == 0) {
0279:                        ContainerBox parent = getParent();
0280:                        // Linebox now empty - remove it
0281:                        if (parent != null) {
0282:                            parent.removeBox(this );
0283:                        }
0284:                    }
0285:
0286:                    return ret;
0287:                }
0288:            }
0289:
0290:            /** XXX #112576. */
0291:            @Override
0292:            protected CssBox[] getBoxesToRemove(CssBox toRemove) {
0293:                // XXX #109306 Remove also sibling boxes representing the same element.
0294:                // XXX Why they don't have common parent?
0295:                Element element = toRemove.getElement();
0296:                if (element != null) {
0297:                    int size = allBoxes.size();
0298:                    List<CssBox> boxesToRemove = new ArrayList<CssBox>();
0299:                    for (int i = 0; i < size; i++) {
0300:                        CssBox siblingBox = allBoxes.get(i);
0301:                        if (siblingBox == null) {
0302:                            continue;
0303:                        }
0304:                        // XXX #119975 Need to check parentage to be sure.
0305:                        if (isSameOrParentElementOf(element, siblingBox
0306:                                .getElement())) {
0307:                            boxesToRemove.add(siblingBox);
0308:                        }
0309:                    }
0310:                    return boxesToRemove.toArray(new CssBox[boxesToRemove
0311:                            .size()]);
0312:                }
0313:                return new CssBox[] { toRemove };
0314:            }
0315:
0316:            protected CssBox notifyChildResize(CssBox child,
0317:                    FormatContext context) {
0318:                int oldHeight = contentHeight;
0319:                relayout(context);
0320:
0321:                ContainerBox parent = getParent();
0322:                if (contentHeight != oldHeight) {
0323:                    return parent.notifyChildResize(this , context);
0324:                } else {
0325:                    // The linebox may be new; ensure that it's positioned
0326:                    parent.positionBox(this , context);
0327:                }
0328:
0329:                return this ;
0330:            }
0331:
0332:            /**
0333:             * Lays out ALL the children; should ONLY be called as part of updateLayout.
0334:             * @todo Find a way to enforce that.
0335:             */
0336:            protected void layoutChild(CssBox box, FormatContext context,
0337:                    boolean handleChildren) {
0338:                // The notifyChildResize call will do a relayout anyway
0339:
0340:                /*
0341:                if (handleChildren) {
0342:                relayout(context);
0343:                }
0344:                 */
0345:            }
0346:
0347:            /**
0348:             * NOTE: prevBox and nextBox refer to the siblings for
0349:             * the new LineBoxGroup to be created (if any), not where
0350:             * within the LineBoxGroup to add the inline box!
0351:             */
0352:            private void addToLineBox(FormatContext context, CssBox ibox) {
0353:                if (lineBox == null) {
0354:                    int maxWidth = context.getMaxWidth(this , targetY);
0355:                    int indent = 0;
0356:
0357:                    Element element = getElement();
0358:                    if ((super .getBoxCount() == 0) && (element != null)) {
0359:                        // First line box should look at the text-indent property
0360:                        //                indent = CssLookup.getLength(element, XhtmlCss.TEXT_INDENT_INDEX);
0361:                        indent = CssUtilities.getCssLength(element,
0362:                                XhtmlCss.TEXT_INDENT_INDEX);
0363:
0364:                        if (indent == AUTO) {
0365:                            indent = 0;
0366:                        }
0367:                    }
0368:
0369:                    lineBox = new LineBox(webform, element, maxWidth, indent);
0370:                    lineBox.setParent(this );
0371:                    lineBox.setContainingBlock(containingBlockX,
0372:                            containingBlockY, containingBlockWidth,
0373:                            containingBlockHeight);
0374:                }
0375:
0376:                lineBox.addBox(ibox, null, null);
0377:            }
0378:
0379:            /** Perform layout on the inline box contents.
0380:             * This typically means splitting it up into multiple
0381:             * sub-lineboxes.
0382:             */
0383:            public void relayout(FormatContext context) {
0384:                // TODO - look up width by subtracting widths of floats!
0385:                // But that means we need to know the current "y" coordinate
0386:                // we're targeted for.
0387:                if (allBoxes == null) {
0388:                    return;
0389:                }
0390:
0391:                // TODO - instead of recreating the line box each time,
0392:                // simply diff and see if flow changes - if it doesn't,
0393:                // we're golden
0394:                removeBoxes();
0395:
0396:                targetY = 0;
0397:                lineBox = null; // redundant?
0398:
0399:                // Compute final size
0400:                // Since the LineBoxGroup is an anonymous box, it doesn't have margins
0401:                // and can't have AUTO etc. set on it, so we simply sum up the children
0402:                // sizes
0403:                contentWidth = 0;
0404:                contentHeight = 0;
0405:
0406:                relayoutChildren(context, allBoxes, getElement());
0407:
0408:                finishLine(context);
0409:
0410:                //finishing relatives has been moved to ContainerBox
0411:                //now is time to shift relative boxes around
0412:                //note, though, that all the browsers paint relative boxes 
0413:                //on top (in front) of other boxes, as if they had a greater z-index.
0414:                //This is, kind of, against the spec, which says (9.9):
0415:                //"Boxes with the same stack level in a stacking context 
0416:                //are stacked bottom-to-top according to document tree order."
0417:                //if we were implementing the spec the same way as browsers, we would 
0418:                //finish relatives after all inlines in the document.
0419:                //finishRelatives(context);
0420:
0421:                width = contentWidth;
0422:                height = contentHeight;
0423:            }
0424:
0425:            private void relayoutChildren(FormatContext context, BoxList list,
0426:                    Element element) {
0427:                if (list == null) {
0428:                    return;
0429:                }
0430:
0431:                int n = list.size();
0432:                boolean wrap = true;
0433:
0434:                if (element != null) {
0435:                    //            Value v = CssLookup.getValue(element, XhtmlCss.WHITE_SPACE_INDEX);
0436:                    CssValue cssV = CssProvider.getEngineService()
0437:                            .getComputedValueForElement(element,
0438:                                    XhtmlCss.WHITE_SPACE_INDEX);
0439:                    //            wrap = v == CssValueConstants.NORMAL_VALUE;
0440:                    wrap = CssProvider.getValueService().isNormalValue(cssV);
0441:                }
0442:
0443:                // XXX #113899 Keeps processed (fixing the ordering) children.
0444:                List<CssBox> processedChildren = new ArrayList<CssBox>();
0445:
0446:                for (int i = 0; i < n; i++) {
0447:                    CssBox box = list.get(i);
0448:
0449:                    if (processedChildren.contains(box)) {
0450:                        continue;
0451:                    }
0452:
0453:                    //relative boxes are similar to float boxes
0454:                    if (box.getBoxType() == BoxType.FLOAT
0455:                            || box.getBoxType() == BoxType.RELATIVE) {
0456:                        if (box.isInlineBox() && !box.isReplacedBox()
0457:                                && box instanceof  ContainerBox
0458:                                && box.getBoxType() != BoxType.FLOAT) { // XXX #99707 Excluding floats from here.
0459:                            LineBox oldLineBox = lineBox;
0460:                            int oldTargetY = targetY;
0461:                            int oldContentWidth = contentWidth;
0462:                            int oldContentHeight = contentHeight;
0463:                            int indent = 0; // XXX Can you have indents here?
0464:                            lineBox = new LineBox(webform, box.getElement(),
0465:                                    containingBlockWidth, indent);
0466:                            lineBox.isFloated = box.getBoxType() == BoxType.FLOAT;
0467:                            lineBox.setParent(this );
0468:                            lineBox.setContainingBlock(containingBlockX,
0469:                                    containingBlockY, containingBlockWidth,
0470:                                    containingBlockHeight);
0471:                            relayoutChildren(context, ((ContainerBox) box)
0472:                                    .getBoxList(), box.getElement());
0473:                            finishLine(context);
0474:                            lineBox = oldLineBox;
0475:                            targetY = oldTargetY;
0476:                            contentWidth = oldContentWidth;
0477:                            contentHeight = oldContentHeight;
0478:                        } else {
0479:                            if (box.getBoxType() == BoxType.RELATIVE) {
0480:                                super .layoutChild(box, context, true);
0481:                                //Ah, no. The float are to be added into the linebox
0482:                                //super.addBox(box, null, null);
0483:                                addToLineBox(context, box);
0484:                                //super.positionBox(box, context);
0485:                            } else {
0486:                                assert box.getBoxType() == BoxType.FLOAT;
0487:                                if (floats == null) {
0488:                                    floats = new ArrayList<CssBox>();
0489:                                }
0490:
0491:                                super .addBox(box, null, null);
0492:                                floats.add(box);
0493:                            }
0494:                        }
0495:
0496:                        // Floats at the beginning of the line should be processed right away so
0497:                        // they are positioned here, not after any other text on this line
0498:                        if ((lineBox == null) || lineBox.isEmpty()) {
0499:                            if (floats != null) { // XXX is this right if lineBox.isFloated?
0500:                                finishFloats(context);
0501:                            }
0502:                        }
0503:
0504:                        // Should we do any kind of content width update here?
0505:                    } else if (box.getBoxType() == BoxType.SPACE) {
0506:                        //if (lineBox != null) { // Ignore space at line beginning
0507:                        if (!wrap || (lineBox == null) || lineBox.isEmpty()
0508:                                || lineBox.canFit(context, box, targetY)) {
0509:                            addToLineBox(context, box);
0510:                        } else {
0511:                            finishLine(context);
0512:                            addToLineBox(context, box);
0513:                        }
0514:
0515:                        //}
0516:                    } else if (box.getBoxType() == BoxType.LINEBREAK) {
0517:                        // Break the line here
0518:                        addToLineBox(context, box);
0519:                        finishLine(context);
0520:
0521:                        if (context.floats != null) {
0522:                            //                    Value clear = CssLookup.getValue(box.getElement(), XhtmlCss.CLEAR_INDEX);
0523:                            CssValue cssClear = CssProvider.getEngineService()
0524:                                    .getComputedValueForElement(
0525:                                            box.getElement(),
0526:                                            XhtmlCss.CLEAR_INDEX);
0527:
0528:                            //                    if (clear != CssValueConstants.NONE_VALUE) {
0529:                            if (!CssProvider.getValueService().isNoneValue(
0530:                                    cssClear)) {
0531:                                int cleared = context.clear(cssClear, null);
0532:
0533:                                if (cleared > Integer.MIN_VALUE) {
0534:                                    int clearance = cleared
0535:                                            - (getAbsoluteY() + targetY);
0536:
0537:                                    if (clearance > 0) {
0538:                                        targetY += clearance;
0539:                                        contentHeight += clearance;
0540:                                        height += clearance;
0541:                                    }
0542:                                }
0543:                            }
0544:                        }
0545:                    } else if (!box.isReplacedBox()
0546:                            && box instanceof  ContainerBox
0547:                            // XXX #6494312 Hack!!! Faking support of inline table, letting it to fall back to else clause.
0548:                            // TODO Provide full support for inline tables.
0549:                            && !(box instanceof  TableBox)) {
0550:                        // TODO - if the box has dimensions (even without
0551:                        // contents), we still need to reserve space for it!!!
0552:                        //need to assign original container to all sub-boxes,
0553:                        //otherwise it will be lost.
0554:                        BoxList boxList = ((ContainerBox) box).getBoxList();
0555:
0556:                        if (boxList == null && box instanceof  LineBoxGroup) {
0557:                            boxList = ((LineBoxGroup) box).allBoxes;
0558:                        }
0559:
0560:                        if (boxList != null) {
0561:                            int boxListSize = boxList.size();
0562:                            for (int j = 0; j < boxListSize; j++) {
0563:                                boxList.get(j).originalInlineContainer = box;
0564:                            }
0565:
0566:                            //                // XXX #113899 Bad architecture, the textual nodes are assigned to line box group
0567:                            //                // which mihgt also be a parent of container which holds the other silings (non-textual) of the textual nodes.
0568:                            //                // That causes incorrect ordering of the boxes comparing to the original element structure.
0569:                            //                // Here trying to hack it, i.e. to put the thing into original order.
0570:                            //                for (int j = 0; j < boxListSize; j++) {
0571:                            //                    CssBox boxListBox = boxList.get(j);
0572:                            //                    CssBox nextBoxListBox = j + 1 < boxListSize ? boxList.get(j + 1) : null;
0573:                            //                    if (boxListBox instanceof ContainerBox && boxListBox.getBoxCount() == 0) {
0574:                            //                        // Could be a placeholder
0575:                            //                        Element boxListBoxElement = boxListBox.getElement();
0576:                            //                        for (int k = i + 1; k < n; k++) {
0577:                            //                            CssBox nextSibling = list.get(k);
0578:                            //                            if (boxListBoxElement == nextSibling.getElement()) {
0579:                            //                                // XXX #109446 Don't add if it is already in.
0580:                            //                                if (boxList.indexOf(nextSibling) == -1) {
0581:                            //                                    // XXX Place the next sibling to the place holder position.
0582:                            //                                    boxList.add(nextSibling, boxListBox, nextBoxListBox);
0583:                            //                                }
0584:                            //                                processedChildren.add(nextSibling);
0585:                            //                            }
0586:                            //                        }
0587:                            //                    }
0588:                            //                }
0589:
0590:                            relayoutChildren(context, boxList, box.getElement());
0591:                        }
0592:                    } else {
0593:                        boolean formatContent = true;
0594:
0595:                        if (box.getBoxType() == BoxType.TEXT) {
0596:                            formatContent = false;
0597:                        } else if (box.getBoxType() == BoxType.SPACE) {
0598:                            formatContent = false;
0599:                        } // XXX what about replaced boxes
0600:
0601:                        if (formatContent) {
0602:                            // We need to do this later if we support complicated boxes in
0603:                            // inline context --- for now just initialize
0604:                            //box.initialize();
0605:                            //box.relayout(context);
0606:                            super .layoutChild(box, context, true);
0607:
0608:                            //No: positionBox(box, context);
0609:                            // XXX #113117 To be sure also the position is set.
0610:                            positionBox(box, context);
0611:                        }
0612:
0613:                        if (!wrap || (lineBox == null) || lineBox.isEmpty()
0614:                                || lineBox.canFit(context, box, targetY)) {
0615:                            addToLineBox(context, box);
0616:                        } else {
0617:                            finishLine(context);
0618:                            addToLineBox(context, box);
0619:                        }
0620:                    }
0621:                }
0622:            }
0623:
0624:            private void finishLine(FormatContext context) {
0625:                if ((lineBox == null) || lineBox.isEmpty()) {
0626:                    if (floats != null) { // XXX is this right if lineBox.isFloated?
0627:                        finishFloats(context);
0628:                    }
0629:
0630:                    return;
0631:                }
0632:
0633:                int lineHeight = lineBox.applyVerticalAlignments();
0634:
0635:                if (lineHeight == 0) {
0636:                    if (metrics != null) {
0637:                        lineHeight = metrics.getHeight();
0638:                    } else {
0639:                        ErrorManager
0640:                                .getDefault()
0641:                                .log(
0642:                                        "Big hack in computing line height for linebox!");
0643:                        lineHeight = 14;
0644:                    }
0645:                }
0646:
0647:                lineBox.contentWidth = lineBox.getActualWidth();
0648:                lineBox.contentHeight = lineHeight;
0649:                lineBox.width = lineBox.contentWidth;
0650:                lineBox.height = lineBox.contentHeight;
0651:
0652:                // Do after setWidth
0653:                // XXX #117399 To render the list within float correctly.
0654:                // XXX #117400 If there is float parent, skip.
0655:                //        if (!lineBox.isFloated) {
0656:                int leftEdge;
0657:                if (lineBox.isFloated || hasFloatParent(lineBox)) {
0658:                    // XXX #117871 Fixing the alignments inside floats.
0659:                    leftEdge = 0;
0660:                } else {
0661:                    leftEdge = context.getLeftEdge(lineBox, this , targetY,
0662:                            lineHeight); // Pass in getParent() instead?
0663:                }
0664:                lineBox
0665:                        .applyHorizontalAlignments(leftEdge, lineHeight,
0666:                                context);
0667:
0668:                if (lineBox.contentWidth > contentWidth) {
0669:                    contentWidth = lineBox.contentWidth;
0670:                }
0671:
0672:                contentHeight += lineBox.contentHeight;
0673:
0674:                if (lineBox.getX() == UNINITIALIZED) {
0675:                    lineBox.setX(0);
0676:                }
0677:
0678:                lineBox.setY(targetY);
0679:                super .addBox(lineBox, null, null);
0680:                targetY += lineHeight;
0681:
0682:                if ((lineBox != null) && lineBox.isFloated) {
0683:                    if (floats == null) {
0684:                        floats = new ArrayList<CssBox>();
0685:                    }
0686:
0687:                    floats.add(lineBox);
0688:                    lineBox = null;
0689:                } else if (floats != null) {
0690:                    lineBox = null;
0691:                    finishFloats(context);
0692:                } else {
0693:                    lineBox = null;
0694:                }
0695:            }
0696:
0697:            private static boolean hasFloatParent(CssBox cssBox) {
0698:                if (cssBox == null) {
0699:                    return false;
0700:                }
0701:
0702:                CssBox parentBox = cssBox.getParent();
0703:                while (parentBox != null) {
0704:                    if (parentBox.getBoxType() == BoxType.FLOAT) {
0705:                        return true;
0706:                    }
0707:                    parentBox = parentBox.getParent();
0708:                }
0709:                return false;
0710:            }
0711:
0712:            void finishRelatives(FormatContext context) {
0713:                //walk though all relative boxes and shift them
0714:                int n = allBoxes.size();
0715:
0716:                for (int i = 0; i < n; i++) {
0717:                    CssBox child = allBoxes.get(i);
0718:                    if (child.getBoxType() == BoxType.RELATIVE) {
0719:                        //in many cases, height of the container is not known 
0720:                        //by the time relitive box gets positioned
0721:                        //so, first define a containing block again
0722:                        super .setContainingBlock(child, context);
0723:                        //then, need to recalculate the properties
0724:                        Element childElement = child.getElement();
0725:                        CssProvider.getEngineService()
0726:                                .uncomputeValueForElement(childElement,
0727:                                        XhtmlCss.LEFT_INDEX);
0728:                        CssProvider.getEngineService()
0729:                                .uncomputeValueForElement(childElement,
0730:                                        XhtmlCss.RIGHT_INDEX);
0731:                        CssProvider.getEngineService()
0732:                                .uncomputeValueForElement(childElement,
0733:                                        XhtmlCss.TOP_INDEX);
0734:                        CssProvider.getEngineService()
0735:                                .uncomputeValueForElement(childElement,
0736:                                        XhtmlCss.BOTTOM_INDEX);
0737:                        child.left = CssUtilities.getCssLength(childElement,
0738:                                XhtmlCss.LEFT_INDEX);
0739:                        child.right = CssUtilities.getCssLength(childElement,
0740:                                XhtmlCss.RIGHT_INDEX);
0741:                        child.top = CssUtilities.getCssLength(childElement,
0742:                                XhtmlCss.TOP_INDEX);
0743:                        child.bottom = CssUtilities.getCssLength(childElement,
0744:                                XhtmlCss.BOTTOM_INDEX);
0745:                        if (child.left == AUTO) {
0746:                            if (child.right == AUTO) {
0747:                                child.left = 0;
0748:                                child.right = 0;
0749:                            } else {
0750:                                child.left = -child.right;
0751:                            }
0752:                        } else {
0753:                            if (child.right == AUTO) {
0754:                                child.right = -child.left;
0755:                            } else {
0756:                                //overconstrained
0757:                                child.right = -child.left;
0758:                            }
0759:                        }
0760:                        if (child.top == AUTO) {
0761:                            if (child.bottom == AUTO) {
0762:                                child.top = 0;
0763:                                child.bottom = 0;
0764:                            } else {
0765:                                child.top = -child.bottom;
0766:                            }
0767:                        } else {
0768:                            if (child.bottom == AUTO) {
0769:                                child.bottom = -child.top;
0770:                            } else {
0771:                                //overconstrained
0772:                                child.bottom = -child.top;
0773:                            }
0774:                        }
0775:                        int newX = child.getX() + child.left;
0776:                        int newY = child.getY() + child.top;
0777:                        child.setLocation(newX, newY);
0778:                    }
0779:                }
0780:            }
0781:
0782:            private void finishFloats(FormatContext context) {
0783:                if (floats != null) {
0784:                    for (int i = 0, n = floats.size(); i < n; i++) {
0785:                        CssBox box = floats.get(i);
0786:
0787:                        if (box.getBoxType() != BoxType.LINEBOX) {
0788:                            // XXX true here - what if we're doing this layout as part
0789:                            // of a child notify - in that case we shouldn't relayout the children!
0790:                            super .layoutChild(box, context, true);
0791:
0792:                            // XXX #113117 To be sure also the position is set.
0793:                            positionBox(box, context); // TEMP
0794:                        }
0795:
0796:                        int theY = targetY;
0797:                        //if the line box is not the first one, and there's space 
0798:                        //for a float in the one above, shift the float up 
0799:                        //if(linebox != null)
0800:                        if (box.isClearBox()/* && findClearContainer(box) == null*/) {
0801:                            //"clear" float box needs to be positioned below any floating box
0802:                            //on the left/right/both depending on the "clear" property value
0803:                            //so, let's find the floating box positioned previously
0804:                            //with the biggest getAbsoluteY() + getHeight() value.
0805:                            ///is there a container which is "clear" itself?
0806:                            //9.5.2: It may be that the element itself has floating descendants; 
0807:                            //the 'clear' property has no effect on those
0808:                            //now let's adjust the targetY value 
0809:                            CssBox prev = context.getPrevFloatingForClear(box);
0810:                            if (prev != null) {
0811:                                //this box is "clear" and there are floats above it.
0812:                                int newY = context.adjustY(prev.getHeight()
0813:                                        + prev.bottomMargin + prev.topMargin,
0814:                                        prev, this )
0815:                                        + box.topMargin;
0816:                                theY = Math.max(targetY, newY);
0817:                            }
0818:                        } else {
0819:                            //9.5.1. #5
0820:                            //The outer top of a floating box may not be higher than the outer top 
0821:                            //of any block or floated box generated by an element earlier in the source document.
0822:                            CssBox prev = context.getPrevFloatingForFloat(box);
0823:                            if (prev != null) {
0824:                                int newY = context.adjustY(0, prev, this );
0825:                                theY = Math.max(targetY, newY);
0826:                            }
0827:                        }
0828:
0829:                        //now lets check if the floats fits here
0830:                        //9.5.1 #7
0831:                        //A left-floating box that has another left-floating
0832:                        //box to its left may not have its right outer edge to the right
0833:                        //of its containing block's right edge. (Loosely: a left float
0834:                        //may not stick out at the right edge, unless it is already
0835:                        //as far to the left as possible.) An analogous rule holds
0836:                        //for right-floating elements.
0837:                        if (context.getMaxWidth(box, this , theY, box
0838:                                .getHeight()) < box.getWidth()) {
0839:                            //move it to the new line, then
0840:                            CssBox prev = context
0841:                                    .getLowestFloatingForFloat(box);
0842:                            if (prev != null) {
0843:                                int newY = context.adjustY(prev.getHeight(),
0844:                                        prev, this );
0845:                                theY = Math.max(targetY, newY);
0846:                            }
0847:                        }
0848:
0849:                        positionFloatBox(theY, box, context);
0850:                        //                positionFloatBox(targetY, box, context);
0851:                    }
0852:                }
0853:
0854:                floats = null;
0855:            }
0856:
0857:            //    static CssBox findClearContainer(CssBox box) {
0858:            //        CssBox parent = box;
0859:            //        while((parent = parent.getParent()) != null) {
0860:            //            CssValue cssClear = CssProvider.getEngineService().
0861:            //                    getComputedValueForElement(parent.getElement(), XhtmlCss.CLEAR_INDEX);
0862:            //            
0863:            //            if(CssProvider.getValueService().isBothValue(cssClear) ||
0864:            //                    CssProvider.getValueService().isLeftValue(cssClear) ||
0865:            //                    CssProvider.getValueService().isRightValue(cssClear))
0866:            //                return(parent);
0867:            //        }
0868:            //        return(null);
0869:            //    }
0870:
0871:            // XXX why isn't this reusing the ContainerBox positionFloatBox code?
0872:            private void positionFloatBox(int py, CssBox box,
0873:                    FormatContext context) {
0874:                box.effectiveTopMargin = 0; // XXX ?
0875:                box.effectiveBottomMargin = 0;
0876:
0877:                CssBox parentBox = box.getParent();
0878:                assert parentBox != null;
0879:                assert parentBox == this ;
0880:
0881:                //        Value floating = CssLookup.getValue(box.getElement(), XhtmlCss.FLOAT_INDEX);
0882:                CssValue cssFloating = CssProvider.getEngineService()
0883:                        .getComputedValueForElement(box.getElement(),
0884:                                XhtmlCss.FLOAT_INDEX);
0885:                boolean leftSide;
0886:
0887:                //        if (floating == CssValueConstants.LEFT_VALUE) {
0888:                if (CssProvider.getValueService().isLeftValue(cssFloating)) {
0889:                    leftSide = true;
0890:                    //        } else {
0891:                    //            assert floating == CssValueConstants.RIGHT_VALUE;
0892:                } else if (CssProvider.getValueService().isRightValue(
0893:                        cssFloating)) {
0894:
0895:                    // None not permitted since we wouldn't have identified a
0896:                    // float boxtype in the first place in BoxType.getBoxType
0897:                    leftSide = false;
0898:                } else {
0899:                    ErrorManager.getDefault().notify(
0900:                            ErrorManager.INFORMATIONAL,
0901:                            new IllegalStateException(
0902:                                    "Unexpected floating value, cssFloating="
0903:                                            + cssFloating));
0904:                    return;
0905:                }
0906:
0907:                // Add/position floating box: its margins do NOT collapse!!
0908:                box.effectiveTopMargin = box.topMargin;
0909:                box.effectiveBottomMargin = box.bottomMargin;
0910:
0911:                // Locate the floating box at the next linebox position
0912:                int px;
0913:
0914:                if (leftSide) {
0915:                    px = context.getLeftEdge(box, this , py, box.getHeight());
0916:                } else {
0917:                    px = context.getRightEdge(box, this , py, box.getHeight())
0918:                            - box.getWidth();
0919:                }
0920:
0921:                box.setLocation(px, py);
0922:
0923:                // Further layout operations need to know about this float box
0924:                // so lineboxes can be shortened
0925:                context.addFloat(px, py, box, leftSide);
0926:
0927:                //context.floating = oldFloating;
0928:            }
0929:
0930:            /**
0931:             * {@inheritDoc}
0932:             *
0933:             * @todo Update this to do logic parallel to {@link relayoutChildren}, e.g.
0934:             *   when child is a non-replaced ContainerBox process its BoxList using the
0935:             *   below logic rather than just call its getPrefMinWidth method which does
0936:             *   not have LineBoxGroup semantics. Similarly, handle floating boxes
0937:             *   specially.
0938:             */
0939:            public int getPrefMinWidth() {
0940:                if (allBoxes == null) {
0941:                    return 0;
0942:                }
0943:
0944:                boolean wrap = true;
0945:
0946:                Element element = getElement();
0947:                if (element != null) {
0948:                    //            Value v = CssLookup.getValue(element, XhtmlCss.WHITE_SPACE_INDEX);
0949:                    CssValue cssV = CssProvider.getEngineService()
0950:                            .getComputedValueForElement(element,
0951:                                    XhtmlCss.WHITE_SPACE_INDEX);
0952:                    //            wrap = v == CssValueConstants.NORMAL_VALUE;
0953:                    wrap = CssProvider.getValueService().isNormalValue(cssV);
0954:                }
0955:
0956:                if (wrap) {
0957:                    int largest = 0;
0958:                    int n = allBoxes.size();
0959:
0960:                    for (int i = 0; i < n; i++) {
0961:                        CssBox child = allBoxes.get(i);
0962:                        int min;
0963:
0964:                        if (child.getBoxType() == BoxType.LINEBREAK) {
0965:                            min = 0;
0966:                        } else {
0967:                            min = child.getPrefMinWidth();
0968:                        }
0969:
0970:                        if (min > largest) {
0971:                            largest = min;
0972:                        }
0973:                    }
0974:
0975:                    return largest;
0976:                } else {
0977:                    BoxList list = allBoxes;
0978:                    int max = 0;
0979:                    int line = 0;
0980:                    int n = list.size();
0981:
0982:                    for (int i = 0; i < n; i++) {
0983:                        CssBox child = list.get(i);
0984:
0985:                        if (child.getBoxType() == BoxType.LINEBREAK) {
0986:                            // Break line - start from scratch
0987:                            line = 0;
0988:                        } else {
0989:                            line += child.getPrefMinWidth();
0990:                        }
0991:
0992:                        if (line > max) {
0993:                            max = line;
0994:                        }
0995:                    }
0996:
0997:                    return max;
0998:                }
0999:            }
1000:
1001:            /**
1002:             * {@inheritDoc}
1003:             *
1004:             * @todo Update this to do logic parallel to {@link relayoutChildren}, e.g.
1005:             *   when child is a non-replaced ContainerBox process its BoxList using the
1006:             *   below logic rather than just call its getPrefWidth method which does
1007:             *   not have LineBoxGroup semantics. Similarly, handle floating boxes
1008:             *   specially.
1009:             */
1010:            public int getPrefWidth() {
1011:                return getPrefWidth(allBoxes);
1012:            }
1013:
1014:            protected int getPrefWidth(BoxList list) {
1015:                if (list == null) {
1016:                    return 0;
1017:                }
1018:
1019:                //for the sake of those floats, that belong to this line box group
1020:                //(not to a line box), and have width in %
1021:                //contentWidth = getParent().contentWidth;
1022:
1023:                int max = 0;
1024:                int line = 0;
1025:                int n = list.size();
1026:
1027:                for (int i = 0; i < n; i++) {
1028:                    CssBox child = list.get(i);
1029:
1030:                    if (child.getBoxType() == BoxType.LINEBREAK) {
1031:                        // Break line - start from scratch
1032:                        line = 0;
1033:                    } else {
1034:                        line += child.getPrefWidth();
1035:                    }
1036:
1037:                    if (line > max) {
1038:                        max = line;
1039:                    }
1040:                }
1041:
1042:                return max;
1043:            }
1044:
1045:            protected void initializeHorizontalWidths(FormatContext context) {
1046:                if (allBoxes == null) {
1047:                    return;
1048:                }
1049:
1050:                for (int i = 0, n = allBoxes.size(); i < n; i++) {
1051:                    CssBox box = allBoxes.get(i);
1052:
1053:                    // We don't care about absolute/fixed children!
1054:                    if (box.getBoxType().isAbsolutelyPositioned()) {
1055:                        // Can this happen in a linebox?
1056:                        continue;
1057:                    }
1058:
1059:                    box.initializeHorizontalWidths(context);
1060:                }
1061:            }
1062:
1063:            void computeHorizontalLengths(FormatContext context) {
1064:                // LineBoxes are anonymous, so they should have no "auto" settings
1065:                // on them
1066:            }
1067:
1068:            void computeVerticalLengths(FormatContext context) {
1069:                //actually, it's not the lineboxgroup that needs to include the floats - 
1070:                //it's linebox's container. The code moved into getSizeWithFloats(FormatContext)
1071:                /*
1072:                // if the box (the contained of LineBoxGroup) is a floating box itself
1073:                //its size should include nested floats. All the browsers do so.
1074:                CssValue cssFloating = CssProvider.getEngineService().getComputedValueForElement(this.getElement(), XhtmlCss.FLOAT_INDEX);
1075:                if (CssProvider.getValueService().isLeftValue(cssFloating) ||
1076:                        CssProvider.getValueService().isRightValue(cssFloating)) {
1077:                    //here we need to look for all boxes whos "float" property is set
1078:                    boolean foundAFloatBox = false;
1079:                    
1080:                    int top = Integer.MAX_VALUE;
1081:                    int bottom = Integer.MIN_VALUE;
1082:                    int n = getBoxCount();
1083:                    
1084:                    for (int i = 0; i < n; i++) {
1085:                        CssBox child = getBox(i);
1086:                        
1087:                        cssFloating = CssProvider.getEngineService().getComputedValueForElement(child.getElement(), XhtmlCss.FLOAT_INDEX);
1088:                        
1089:                        if (CssProvider.getValueService().isLeftValue(cssFloating) ||
1090:                                CssProvider.getValueService().isRightValue(cssFloating)) {
1091:                            
1092:                            if (child.getY() < top) {
1093:                                top = child.getY();
1094:                            }
1095:                            
1096:                            if ((child.getY() + child.getHeight()) > bottom) {
1097:                                bottom = child.getY() + child.getHeight();
1098:                            }
1099:                            
1100:                            foundAFloatBox = true;
1101:                        }
1102:                    }
1103:                    if(foundAFloatBox) {
1104:                        if (top != Integer.MAX_VALUE) {
1105:                            contentHeight = bottom - top;
1106:                        }
1107:                    }
1108:                }
1109:                 */
1110:            }
1111:
1112:            int getSizeWithFloats() {
1113:                // if the box (the contained of LineBoxGroup) is a floating box itself
1114:                //its size should include nested floats. All the browsers do so.
1115:                CssValue cssFloating = CssProvider.getEngineService()
1116:                        .getComputedValueForElement(this .getElement(),
1117:                                XhtmlCss.FLOAT_INDEX);
1118:                if (CssProvider.getValueService().isLeftValue(cssFloating)
1119:                        || CssProvider.getValueService().isRightValue(
1120:                                cssFloating)) {
1121:                    //here we need to look for all boxes whos "float" property is set
1122:                    boolean foundAFloatBox = false;
1123:
1124:                    int top = Integer.MAX_VALUE;
1125:                    int bottom = Integer.MIN_VALUE;
1126:                    int n = getBoxCount();
1127:
1128:                    for (int i = 0; i < n; i++) {
1129:                        CssBox child = getBox(i);
1130:
1131:                        cssFloating = CssProvider.getEngineService()
1132:                                .getComputedValueForElement(child.getElement(),
1133:                                        XhtmlCss.FLOAT_INDEX);
1134:
1135:                        if (CssProvider.getValueService().isLeftValue(
1136:                                cssFloating)
1137:                                || CssProvider.getValueService().isRightValue(
1138:                                        cssFloating)) {
1139:                            if (child.getY() < top) {
1140:                                top = child.getY();
1141:                            }
1142:                            if ((child.getY() + child.getHeight()) > bottom) {
1143:                                bottom = child.getY() + child.getHeight();
1144:                            }
1145:                            foundAFloatBox = true;
1146:                        }
1147:                    }
1148:                    if (foundAFloatBox) {
1149:                        if (bottom != Integer.MAX_VALUE) {
1150:                            return bottom - top;
1151:                        }
1152:                    }
1153:                }
1154:                return 0;
1155:            }
1156:
1157:            /** Split this linebox, creating a new linebox containing all
1158:             * the elements following the child box "lastBox"; the new
1159:             * line box will containg the remaining elements, and this
1160:             * line box will be truncated to only contain the elements
1161:             * up to lastBox.
1162:             */
1163:            LineBoxGroup split(
1164:                    org.netbeans.modules.visualweb.css2.CssBox lastBox) {
1165:                // Find the box to be inserted
1166:                assert allBoxes != null;
1167:
1168:                int pos = 0;
1169:                int n = allBoxes.size();
1170:
1171:                for (; pos < n; pos++) {
1172:                    if (allBoxes.get(pos) == lastBox) {
1173:                        break;
1174:                    }
1175:                }
1176:
1177:                assert pos < n;
1178:                pos++;
1179:
1180:                LineBoxGroup split = new LineBoxGroup(webform, getElement(),
1181:                        metrics);
1182:                int remainder = n - pos;
1183:                split.allBoxes = new BoxList(remainder + 4); // XXX good default? Do statistics.
1184:
1185:                for (int i = pos; i < n; i++) {
1186:                    split.allBoxes.add(allBoxes.get(i), null, null);
1187:                }
1188:
1189:                // Fix parent pointers
1190:                for (int i = 0; i < remainder; i++) {
1191:                    split.allBoxes.get(i).setParent(split);
1192:                    split.allBoxes.get(i).setPositionedBy(split);
1193:                }
1194:
1195:                allBoxes.truncate(pos);
1196:
1197:                return split;
1198:            }
1199:
1200:            //    // XXX TODO JSF specific, replace with the latter method.
1201:            //    public void computeRectangles(DesignBean component, List list) {
1202:            //        // Look through my line boxes, and for each item, walk back up the parent chain
1203:            //        // looking for the given live bean. When found, the leaf is added to the bounds.
1204:            //        Rectangle bounds = null;
1205:            //
1206:            //        for (int i = 0, n = getBoxCount(); i < n; i++) {
1207:            //            // LineBoxGroups contain mostly LineBoxes, but can have floats too
1208:            //            CssBox box = getBox(i);
1209:            //
1210:            //            if (box instanceof LineBox) {
1211:            //                LineBox lb = (LineBox)box;
1212:            //
1213:            //                for (int j = 0, m = lb.getBoxCount(); j < m; j++) {
1214:            //                    CssBox leaf = lb.getBox(j);
1215:            //
1216:            //                    // Is it conceivable that a single line context will have
1217:            //                    // multiple separate segments for different live beans? If so
1218:            //                    // I guess I should only join rectangles for -contiguous-
1219:            //                    // sections of boxes
1220:            //                    if (hasComponentAncestor(leaf, component)) {
1221:            //                        // Yessss
1222:            //                        Rectangle r =
1223:            //                            new Rectangle(leaf.getAbsoluteX(), leaf.getAbsoluteY(),
1224:            //                                leaf.getWidth(), leaf.getHeight());
1225:            //
1226:            //                        if (bounds == null) {
1227:            //                            // allocations get mutated by later
1228:            //                            // transformations so I've gotta make a copy
1229:            //                            bounds = r;
1230:            //                        } else {
1231:            //                            bounds.add(r);
1232:            //                        }
1233:            //
1234:            //                        // We don't break here - multiple items in the line box group
1235:            //                        // may be descendants and we want to include all in the bounds
1236:            //                        // computation
1237:            //                    }
1238:            //                }
1239:            //            } else {
1240:            //                assert box.getBoxType() == BoxType.FLOAT || box.getBoxType() == BoxType.RELATIVE;
1241:            //                box.computeRectangles(component, list);
1242:            //            }
1243:            //        }
1244:            //
1245:            //        if (bounds != null) {
1246:            //            list.add(bounds);
1247:            //        }
1248:            //    }
1249:
1250:            // XXX TODO This will replace the above.
1251:            public void computeRectangles(Element componentRootElement,
1252:                    List<Rectangle> list) {
1253:                // Look through my line boxes, and for each item, walk back up the parent chain
1254:                // looking for the given live bean. When found, the leaf is added to the bounds.
1255:                Rectangle bounds = null;
1256:
1257:                for (int i = 0, n = getBoxCount(); i < n; i++) {
1258:                    // LineBoxGroups contain mostly LineBoxes, but can have floats too
1259:                    CssBox box = getBox(i);
1260:
1261:                    if (box instanceof  LineBox) {
1262:                        LineBox lb = (LineBox) box;
1263:
1264:                        for (int j = 0, m = lb.getBoxCount(); j < m; j++) {
1265:                            CssBox leaf = lb.getBox(j);
1266:
1267:                            // Is it conceivable that a single line context will have
1268:                            // multiple separate segments for different live beans? If so
1269:                            // I guess I should only join rectangles for -contiguous-
1270:                            // sections of boxes
1271:                            Element element = leaf == null ? null : leaf
1272:                                    .getElement();
1273:                            if (isSameOrParentElementOf(componentRootElement,
1274:                                    element)
1275:                                    || hasComponentAncestor(leaf,
1276:                                            componentRootElement)) {
1277:                                // Yessss
1278:                                Rectangle r = new Rectangle(
1279:                                        leaf.getAbsoluteX(), leaf
1280:                                                .getAbsoluteY(), leaf
1281:                                                .getWidth(), leaf.getHeight());
1282:
1283:                                if (bounds == null) {
1284:                                    // allocations get mutated by later
1285:                                    // transformations so I've gotta make a copy
1286:                                    bounds = r;
1287:                                } else {
1288:                                    bounds.add(r);
1289:                                }
1290:
1291:                                // We don't break here - multiple items in the line box group
1292:                                // may be descendants and we want to include all in the bounds
1293:                                // computation
1294:                            }
1295:                        }
1296:                    } else {
1297:                        assert box.getBoxType() == BoxType.FLOAT
1298:                                || box.getBoxType() == BoxType.RELATIVE;
1299:                        box.computeRectangles(componentRootElement, list);
1300:                    }
1301:                }
1302:
1303:                if (bounds != null) {
1304:                    list.add(bounds);
1305:                }
1306:            }
1307:
1308:            //    // XXX TODO JSF specific, replace with the latter method.
1309:            //    public Rectangle computeBounds(DesignBean component, Rectangle bounds) {
1310:            //        // Look through my line boxes, and for each item, walk back up the parent chain
1311:            //        // looking for the given live bean. When found, the leaf is added to the bounds.
1312:            //        for (int i = 0, n = getBoxCount(); i < n; i++) {
1313:            //            // LineBoxGroups contain mostly LineBoxes, but can have floats too
1314:            //            CssBox box = getBox(i);
1315:            //
1316:            //            if (box instanceof LineBox) {
1317:            //                LineBox lb = (LineBox)box;
1318:            //
1319:            //                for (int j = 0, m = lb.getBoxCount(); j < m; j++) {
1320:            //                    CssBox leaf = lb.getBox(j);
1321:            //
1322:            //                    if (hasComponentAncestor(leaf, component)) {
1323:            //                        // Yessss
1324:            //                        Rectangle r =
1325:            //                            new Rectangle(leaf.getAbsoluteX(), leaf.getAbsoluteY(),
1326:            //                                leaf.getWidth(), leaf.getHeight());
1327:            //
1328:            //                        if (bounds == null) {
1329:            //                            // allocations get mutated by later
1330:            //                            // transformations so I've gotta make a copy
1331:            //                            bounds = r;
1332:            //                        } else {
1333:            //                            bounds.add(r);
1334:            //                        }
1335:            //
1336:            //                        // We don't break here - multiple items in the line box group
1337:            //                        // may be descendants and we want to include all in the bounds
1338:            //                        // computation
1339:            //                    }
1340:            //                }
1341:            //            } else {
1342:            //                assert box.getBoxType() == BoxType.FLOAT || box.getBoxType() == BoxType.RELATIVE;
1343:            //                bounds = box.computeBounds(component, bounds);
1344:            //            }
1345:            //        }
1346:            //
1347:            //        return bounds;
1348:            //    }
1349:
1350:            // XXX TODO This will replace the above.
1351:            public Rectangle computeBounds(Element componentRootElement,
1352:                    Rectangle bounds) {
1353:                // Look through my line boxes, and for each item, walk back up the parent chain
1354:                // looking for the given live bean. When found, the leaf is added to the bounds.
1355:                for (int i = 0, n = getBoxCount(); i < n; i++) {
1356:                    // LineBoxGroups contain mostly LineBoxes, but can have floats too
1357:                    CssBox box = getBox(i);
1358:
1359:                    if (box instanceof  LineBox) {
1360:                        LineBox lb = (LineBox) box;
1361:
1362:                        for (int j = 0, m = lb.getBoxCount(); j < m; j++) {
1363:                            CssBox leaf = lb.getBox(j);
1364:
1365:                            Element element = leaf == null ? null : leaf
1366:                                    .getElement();
1367:                            if (isSameOrParentElementOf(componentRootElement,
1368:                                    element)
1369:                                    || hasComponentAncestor(leaf,
1370:                                            componentRootElement)) {
1371:                                // Yessss
1372:                                Rectangle r = new Rectangle(
1373:                                        leaf.getAbsoluteX(), leaf
1374:                                                .getAbsoluteY(), leaf
1375:                                                .getWidth(), leaf.getHeight());
1376:
1377:                                if (bounds == null) {
1378:                                    // allocations get mutated by later
1379:                                    // transformations so I've gotta make a copy
1380:                                    bounds = r;
1381:                                } else {
1382:                                    bounds.add(r);
1383:                                }
1384:
1385:                                // We don't break here - multiple items in the line box group
1386:                                // may be descendants and we want to include all in the bounds
1387:                                // computation
1388:                            }
1389:                        }
1390:                    } else {
1391:                        assert box.getBoxType() == BoxType.FLOAT
1392:                                || box.getBoxType() == BoxType.RELATIVE;
1393:                        bounds = box
1394:                                .computeBounds(componentRootElement, bounds);
1395:                    }
1396:                }
1397:
1398:                return bounds;
1399:            }
1400:
1401:            //    // TODO JSF specific, this needs to be replaced by the latter method.
1402:            //    /** Return true iff the given leaf has a box as an ancestor (but below
1403:            //      * this LineBoxGroup) that corresponds to the given live bean */
1404:            //    private boolean hasComponentAncestor(CssBox leaf, DesignBean component) {
1405:            //        while ((leaf != null) && (leaf != this)) {
1406:            ////            if (leaf.getDesignBean() == component) {
1407:            //            if (getMarkupDesignBeanForCssBox(leaf) == component) {
1408:            //                return true;
1409:            //            }
1410:            //
1411:            //            leaf = leaf.getParent();
1412:            //        }
1413:            //
1414:            //        return false;
1415:            //    }
1416:
1417:            // TODO This will replace the above method.
1418:            /** Return true iff the given leaf has a box as an ancestor (but below
1419:             * this LineBoxGroup) that corresponds to the given live bean */
1420:            private boolean hasComponentAncestor(CssBox leaf,
1421:                    Element componentRootElement) {
1422:                while ((leaf != null) && (leaf != this )) {
1423:                    //            if (leaf.getDesignBean() == component) {
1424:                    //            if (getElementForComponentRootCssBox(leaf) == componentRootElement) {
1425:                    // XXX #107084 There needs to be a way how to find a component for
1426:                    // the line box type of boxes, which otherwise don't have a component root element.
1427:                    // Before it was working only thanks to 'broken' hierarchy, the parent was different (ContainerBox)
1428:                    // than the actual box (LineBoxGroup) having one (TextBox) as its child.
1429:                    if (leaf.getElement() == componentRootElement) {
1430:                        return true;
1431:                    }
1432:
1433:                    leaf = leaf.getParent();
1434:                }
1435:
1436:                return false;
1437:            }
1438:
1439:            // XXX #118287 Also when the root box is not part of the tree (see also #107084).
1440:            private static boolean isSameOrParentElementOf(
1441:                    Element parentElement, Element element) {
1442:                if (parentElement == null || element == null) {
1443:                    return false;
1444:                }
1445:
1446:                Node node = element;
1447:                while (node != null) {
1448:                    if (node == parentElement) {
1449:                        return true;
1450:                    }
1451:                    node = node.getParentNode();
1452:                }
1453:                return false;
1454:            }
1455:
1456:            /** FOR TESTSUITE ONLY! */
1457:            public BoxList getManagedBoxes() {
1458:                return allBoxes;
1459:            }
1460:
1461:            protected void paintBackground(Graphics g, int x, int y) {
1462:                //LayeredHighlighter h = doc.getWebForm().getPane().getHighlighter();
1463:                //h.paintLayeredHighlights(g, p0, p1, a, tc, this);
1464:                DesignerPane pane = webform.getPane();
1465:
1466:                if (pane == null) {
1467:                    return; // TESTSUITE
1468:                }
1469:
1470:                //        DesignerCaret caret = pane.getCaret();
1471:                //        if ((caret != null) && caret.hasSelection()) {
1472:                if (pane.hasCaretSelection()) {
1473:                    // Determine if the range intersects our line box group
1474:                    //            Position sourceCaretBegin = caret.getFirstPosition();
1475:                    //            DomPosition sourceCaretBegin = caret.getFirstPosition();
1476:                    DomPosition sourceCaretBegin = pane.getFirstPosition();
1477:
1478:                    // XXX I ought to have a cached method on the caret for obtaining the rendered
1479:                    // location!
1480:                    //            Position caretBegin = sourceCaretBegin.getRenderedPosition();
1481:                    //            Position sourceCaretEnd = caret.getLastPosition();
1482:                    //            Position caretEnd = sourceCaretEnd.getRenderedPosition();
1483:                    DomPosition caretBegin = sourceCaretBegin
1484:                            .getRenderedPosition();
1485:
1486:                    //            DomPosition sourceCaretEnd = caret.getLastPosition();
1487:                    DomPosition sourceCaretEnd = pane.getLastPosition();
1488:
1489:                    DomPosition caretEnd = sourceCaretEnd.getRenderedPosition();
1490:
1491:                    Node firstNode = findFirstNode();
1492:
1493:                    if (firstNode == null) {
1494:                        return;
1495:                    }
1496:
1497:                    Node lastNode = findLastNode();
1498:                    Node caretBeginNode = caretBegin.getNode();
1499:
1500:                    if (caretBeginNode == null) {
1501:                        return;
1502:                    }
1503:
1504:                    Node caretEndNode = caretEnd.getNode();
1505:
1506:                    if (caretEndNode == null) {
1507:                        return;
1508:                    }
1509:
1510:                    //            int r1 =
1511:                    //                Position.compareBoundaryPoints(caretBeginNode, caretBegin.getOffset(), lastNode,
1512:                    //                    10000);
1513:                    int r1 = webform.compareBoundaryPoints(caretBeginNode,
1514:                            caretBegin.getOffset(), lastNode, 10000);
1515:
1516:                    //            int r2 =
1517:                    //                Position.compareBoundaryPoints(caretEndNode, caretEnd.getOffset(), firstNode, 0);
1518:                    int r2 = webform.compareBoundaryPoints(caretEndNode,
1519:                            caretEnd.getOffset(), firstNode, 0);
1520:
1521:                    if ((r1 >= 0) && (r2 <= 0)) {
1522:                        PageBox pageBox = pane.getPageBox();
1523:
1524:                        // TODO I should make sure modelToView uses the render nodes!
1525:                        //                Rectangle p0 = pageBox.modelToView(sourceCaretBegin);
1526:                        //                Rectangle p1 = pageBox.modelToView(sourceCaretEnd);
1527:                        Rectangle p0 = ModelViewMapper.modelToView(pageBox,
1528:                                sourceCaretBegin);
1529:                        Rectangle p1 = ModelViewMapper.modelToView(pageBox,
1530:                                sourceCaretEnd);
1531:
1532:                        if ((p0 != null) && (p1 != null)) {
1533:                            if ((p1.y < p0.y)
1534:                                    || ((p0.y == p1.y) && (p1.x < p0.x))) {
1535:                                // Swap to make sure mark comes visually before dot
1536:                                Rectangle temp = p0;
1537:                                p0 = p1;
1538:                                p1 = temp;
1539:                            }
1540:
1541:                            g.setColor(pane.getSelectionColor());
1542:
1543:                            if (p0.y == p1.y) {
1544:                                // same line, render a rectangle
1545:                                // No - shouldn't include the width on p1!
1546:                                p1.width = 0;
1547:
1548:                                Rectangle r = p0.union(p1);
1549:
1550:                                if ((r.y + r.height) < y) {
1551:                                    // CULL: This can happen when you have a component which gets
1552:                                    // replicated multiple times; for example, an output text
1553:                                    // in a data table. The output text DesignBean itself
1554:                                    // is repeated on multiple separate rows. For fast 
1555:                                    // modelToView computations for carets and such, I stash
1556:                                    // the box rendered for a DesignBean directly on the
1557:                                    // DesignBean itself. However, this means that it's the
1558:                                    // LAST box created for a DesignBean which has its
1559:                                    // position associated with the DesignBean. Thus, even
1560:                                    // though every single row in the data table could
1561:                                    // match the caret test above (when the caret is actually
1562:                                    // inside the LiveBean, as is the case for editing the
1563:                                    // value attribute of an output text), the position
1564:                                    // lookup for the node will have to choose one particular
1565:                                    // rendering of that node -- it currently uses the last one.
1566:                                    // Therefore, the position we've been assigned may not
1567:                                    // represent positions in this linebox, and if so, cull
1568:                                    // the painting since we could be overwriting foreground
1569:                                    // text on a previous line.
1570:                                    return;
1571:                                }
1572:
1573:                                g.fillRect(r.x, r.y, r.width, r.height);
1574:                            } else {
1575:                                // different lines
1576:                                if ((p1.y + p1.height) < y) {
1577:                                    // See comment CULL above
1578:                                    return;
1579:                                }
1580:
1581:                                int y2 = y + height;
1582:
1583:                                // Only paint regions that vertically intersect our box
1584:                                if (((p0.y + p0.height) > y) && (p0.y < y2)) {
1585:                                    int p0ToMarginWidth = (x + width) - p0.x;
1586:                                    int my1 = p0.y;
1587:                                    int my2 = my1 + p0.height;
1588:
1589:                                    if (my1 < y) {
1590:                                        my1 = y;
1591:                                    }
1592:
1593:                                    if (my2 > y2) {
1594:                                        my2 = y2;
1595:                                    }
1596:
1597:                                    g.fillRect(p0.x, my1, p0ToMarginWidth, my2
1598:                                            - my1);
1599:                                }
1600:
1601:                                if ((p0.y + p0.height) != p1.y) {
1602:                                    int my1 = p0.y + p0.height;
1603:                                    int myh = p1.y - (p0.y + p0.height);
1604:                                    int my2 = my1 + myh;
1605:
1606:                                    if ((my2 > y) && (my1 < y2)) {
1607:                                        // Clip to current box size
1608:                                        if (my2 > y2) {
1609:                                            my2 = y2;
1610:                                        }
1611:
1612:                                        if (my1 < y) {
1613:                                            my1 = y;
1614:                                        }
1615:
1616:                                        g.fillRect(x, my1, width, my2 - my1);
1617:                                    }
1618:                                }
1619:
1620:                                if (((p1.y + p1.height) > y) && (p1.y < y2)) {
1621:                                    int my1 = p1.y;
1622:                                    int my2 = my1 + p1.height;
1623:
1624:                                    if (my1 < y) {
1625:                                        my1 = y;
1626:                                    }
1627:
1628:                                    if (my2 > y2) {
1629:                                        my2 = y2;
1630:                                    }
1631:
1632:                                    g.fillRect(x, my1, (p1.x - x), my2 - my1);
1633:                                }
1634:                            }
1635:                        }
1636:                    }
1637:                }
1638:            }
1639:
1640:            /**
1641:             * Paint the linebox. This is overiding super because while we
1642:             * don't need the clipping in ContainerBox, we also need to
1643:             * change background painting.
1644:             * The issue is that let's say we have a bunch of text boxes
1645:             * in a linebox with backgrounds. Selection-range painting, which
1646:             * is done here in LineBoxGroup, needs to happen AFTER the textboxes
1647:             * have drawn their backgrounds, but BEFORE they paint their text
1648:             * foregrounds!
1649:             *
1650:             * So TextBoxes and LineBoxes have been modified to not paint their
1651:             * backgrounds as part of paint. And here LineBoxGroup will first
1652:             * paint its LineBox backgrounds, then the selection, then its
1653:             * LineBox foregrounds/text.
1654:             */
1655:            public void paint(Graphics g, int px, int py) {
1656:                px += getX();
1657:                py += getY();
1658:
1659:                // Box model quirk: my coordinate system is based on the visual
1660:                // extents of the boxes - e.g. location and size of the border
1661:                // edge.  Because of this, when visually traversing the hierarchy,
1662:                // I need to add in the margins.
1663:                px += leftMargin;
1664:                py += effectiveTopMargin;
1665:
1666:                if ((Math.abs(px) > 50000) || (Math.abs(py) > 50000)
1667:                        || (Math.abs(width) > 50000)
1668:                        || (Math.abs(height) > 50000)) {
1669:                    //            g.setColor(java.awt.Color.RED);
1670:                    //            g.drawString("Fatal Painting Error: box " + this.toString(), 0,
1671:                    //                g.getFontMetrics().getHeight());
1672:                    // XXX Improving the above error handling.
1673:                    // TODO Why is actually this state invalid?
1674:                    ErrorManager.getDefault()
1675:                            .notify(
1676:                                    ErrorManager.INFORMATIONAL,
1677:                                    new IllegalStateException(
1678:                                            "Fatal painting error:" // NOI18N
1679:                                                    + "\nbad box="
1680:                                                    + this  // NOI18N
1681:                                                    + "\nparent of bad box="
1682:                                                    + this .getParent())); // NOI18N
1683:
1684:                    return;
1685:                }
1686:
1687:                // Paint children backgrounds -- before our own selection
1688:                for (int i = 0, n = getBoxCount(); i < n; i++) {
1689:                    CssBox box = getBox(i);
1690:
1691:                    if (box.getBoxType() == BoxType.LINEBOX) {
1692:                        box.paintBackground(g, px, py);
1693:                    } // other boxes will do their own background painting
1694:                }
1695:
1696:                paintBackground(g, px, py);
1697:
1698:                // Paint children foregrounds
1699:                for (int i = 0, n = getBoxCount(); i < n; i++) {
1700:                    CssBox box = getBox(i);
1701:                    CssBox positionParent = box.getPositionedBy();
1702:
1703:                    // XXX is this possible for LineBoxes ? I don't think so...
1704:                    // Could optimize out. LineBoxes can't be positioned by
1705:                    // anyone but the LineBoxGroup directly.
1706:                    if (positionParent != this ) {
1707:                        // Not positioned by us - need to compute the
1708:                        // positioning parent's absolute position
1709:                        box.paint(g, positionParent.getAbsoluteX(),
1710:                                positionParent.getAbsoluteY());
1711:                    } else {
1712:                        box.paint(g, px, py);
1713:                    }
1714:                }
1715:
1716:                if (CssBox.paintSpaces) {
1717:                    g.setColor(Color.CYAN);
1718:                    g.drawRect(getAbsoluteX(), getAbsoluteY(), width, height);
1719:                }
1720:            }
1721:
1722:            /** Locate the first node that is included in this linebox */
1723:            private Node findFirstNode() {
1724:                for (int i = 0, n = allBoxes.size(); i < n; i++) {
1725:                    CssBox box = allBoxes.get(i);
1726:
1727:                    if (box.getBoxType() == BoxType.TEXT) {
1728:                        return ((TextBox) box).getNode();
1729:                    } else if (box.getBoxType() == BoxType.SPACE) {
1730:                        return ((SpaceBox) box).getNode();
1731:                    } else if (box.getElement() != null) {
1732:                        return box.getElement();
1733:                    }
1734:                }
1735:
1736:                return null;
1737:            }
1738:
1739:            /** Locate the last node that is included in this linebox */
1740:            private Node findLastNode() {
1741:                for (int i = allBoxes.size() - 1; i >= 0; i--) {
1742:                    CssBox box = allBoxes.get(i);
1743:
1744:                    if (box.getBoxType() == BoxType.TEXT) {
1745:                        return ((TextBox) box).getNode();
1746:                    } else if (box.getBoxType() == BoxType.SPACE) {
1747:                        return ((SpaceBox) box).getNode();
1748:                    } else if (box.getElement() != null) {
1749:                        return box.getElement();
1750:                    }
1751:                }
1752:
1753:                return null;
1754:            }
1755:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.