001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.visualweb.css2;
042:
043: import java.util.List;
044: import org.netbeans.modules.visualweb.api.designer.cssengine.CssProvider;
045: import org.netbeans.modules.visualweb.api.designer.cssengine.CssValue;
046: import org.netbeans.modules.visualweb.api.designer.cssengine.CssValueService;
047: import org.netbeans.modules.visualweb.api.designer.cssengine.XhtmlCss;
048: import java.util.ArrayList;
049:
050: /**
051: * FormatContext used during layout/formatting of CSS2 boxes
052: *
053: * @todo For now I've made the fields public. Might consider
054: * using accessors and mutators.
055: * @todo Should I use float/double instead of ints? CSS2 calls
056: * for that, but...
057: *
058: * @author Tor Norbye
059: */
060: public class FormatContext {
061: public ViewportBox initialCB; // Initial containing block / viewport
062: public int initialWidth; // Width of the initial containing block
063: public int initialHeight; // Height of the initial containing block
064: public LineBox lineBox; // XXX SHOULD REMOVE!
065:
066: //public Element element;
067: public boolean floating; // whether or not the currently formatted box is a floating box
068: public List<FloatingBoxInfo> floats;
069:
070: /*
071: public String toString() {
072: return "FormatContext[" +
073: lineBox +
074: "]";
075: }
076: */
077: public void addFloat(int x, int y, CssBox box, boolean leftSide) {
078: if (floats == null) {
079: floats = new ArrayList<FloatingBoxInfo>(4);
080: }
081:
082: FloatingBoxInfo info = new FloatingBoxInfo(x, y, box, leftSide);
083: floats.add(info);
084: }
085:
086: /** Return the maximum x coordinate available - this is the right edge
087: * of the containing block, minus the widths of any floats overlapping
088: * this line.
089: * (Actually, since floats could overlap, it returns the
090: * leftmost coordinate of any float overlapping this line that is
091: * floated to the right, minus the rightmost coordinate of any
092: * float overlapping this line that is floated to the left...) */
093: int getMaxWidth(CssBox parent, int y) {
094: return (getMaxWidth(null, parent, y, 0));
095: }
096:
097: /** Return the maximum x coordinate available - this is the right edge
098: * of the containing block, minus the widths of any floats overlapping
099: * this line.
100: * @param y - lineBox top.
101: * @param height - linebox height
102: */
103: int getMaxWidth(CssBox cssBox, CssBox parent, int y, int height) {
104: // XXX Here's an idea. Look for a common parent (between the current
105: // formatting box and the floating box), and translate
106: // coordinate systems appropriately so the coordinates match!
107: int result = parent.containingBlockWidth;
108:
109: if (floating || (floats == null)) {
110: return result;
111: }
112:
113: int rightEdge = result;
114: int leftEdge = 0;
115:
116: for (int i = 0, n = floats.size(); i < n; i++) {
117: FloatingBoxInfo info = floats.get(i);
118: CssBox box = info.box;
119:
120: // XXX #117840 Check for parentage, and skip if this float is child of the examined box.
121: if (box == cssBox || isParentOf(cssBox, box)) {
122: continue;
123: }
124:
125: if (canAdjustY(parent, box.getParent())) {
126: int yp = adjustY(y, parent, box.getParent());
127:
128: if ((yp >= info.y)
129: && (yp < (info.y + box.getHeight()))
130: || //top is within
131: (yp + height >= info.y)
132: && (yp + height < (info.y + box.getHeight()))
133: || // bottom is within
134: (yp + height <= info.y)
135: && (yp + height > (info.y + box.getHeight())) // float is within
136: ) {
137: if (info.leftSide) {
138: int boxRightEdge = info.x + box.getWidth();
139:
140: if (boxRightEdge > leftEdge) {
141: leftEdge = boxRightEdge;
142: }
143: } else {
144: if (info.x < result) {
145: rightEdge = info.x;
146: }
147: }
148: }
149: }
150: }
151:
152: //this could happen while trying to computate space available for
153: //other floats
154: //if ((rightEdge - leftEdge) < 0) {
155: // ErrorManager.getDefault().log("Float computation: Unexpected problem");
156: //}
157:
158: //return result-1;
159: return rightEdge - leftEdge;
160: }
161:
162: /** Return the minimum x coordinate available - this is the left edge
163: * of the containing block, plus the widths of any floats overlapping
164: * this line.
165: * (Actually, since floats could overlap, it returns the
166: * rightmost coordinate of any float overlapping this line that is
167: * floated to the left.
168: */
169: int getLeftEdge(CssBox cssBox, CssBox parent, int y, int height) {
170: // When formatting a floating box, don't look for other floating
171: // boxes!
172: if (floating) {
173: //return 0;
174: return parent.leftMargin + parent.leftBorderWidth
175: + parent.leftPadding;
176: }
177:
178: int leftEdge = 0;
179: int n = (floats != null) ? floats.size() : 0;
180:
181: for (int i = 0; i < n; i++) {
182: FloatingBoxInfo info = floats.get(i);
183:
184: if (!info.leftSide) {
185: continue;
186: }
187:
188: CssBox box = info.box;
189:
190: // XXX #117400 Skip if the cssBox is parent of this float.
191: if (isParentOf(cssBox, box)) {
192: continue;
193: }
194:
195: // Find out if y, in the "parent" coordinate system,
196: // "intersect" the box (which is in its own coordinate system
197: // which may be different from the parent one)
198: int yp = adjustY(y, parent, box.getParent());
199:
200: if (((yp + height) > info.y)
201: && (yp < (info.y + box.getHeight()))) {
202: // XXX #117789 One needs to take into account also the margins, borders, paddings.
203: CssBox closest = findCommonAncestor(cssBox, box);
204: int cssBoxAccumulatedLefts = 0;
205: int floatBoxAccumulatedHorizontals = 0;
206: if (closest != null) {
207: cssBoxAccumulatedLefts = computeAccumulatedLefts(
208: cssBox, closest);
209: floatBoxAccumulatedHorizontals = computeAccumulatedHorizontals(
210: box, closest);
211: }
212:
213: int boxRightEdge = info.x + box.getWidth();
214:
215: // if (boxRightEdge > leftEdge) {
216: // leftEdge = boxRightEdge;
217: // }
218: if ((boxRightEdge + floatBoxAccumulatedHorizontals) > (leftEdge + cssBoxAccumulatedLefts)) {
219: leftEdge = boxRightEdge;
220: }
221: }
222: }
223:
224: // XXX should I add these in before the comparisons?
225: return leftEdge + parent.leftMargin + parent.leftBorderWidth
226: + parent.leftPadding;
227: }
228:
229: /** Get accumulated left margins, border widths, padding
230: * up to the parentBox (excluding). */
231: private static int computeAccumulatedLefts(CssBox cssBox,
232: CssBox parentBox) {
233: int accumulatedLefts = 0;
234: while (cssBox != null) {
235: if (cssBox == parentBox) {
236: break;
237: }
238: int leftM = cssBox.leftMargin;
239: if (leftM != CssBox.UNINITIALIZED && leftM != CssBox.AUTO) {
240: accumulatedLefts += leftM;
241: }
242: int leftB = cssBox.leftBorderWidth;
243: if (leftB != CssBox.UNINITIALIZED && leftB != CssBox.AUTO) {
244: accumulatedLefts += leftB;
245: }
246: int leftP = cssBox.leftPadding;
247: if (leftP != CssBox.UNINITIALIZED && leftP != CssBox.AUTO) {
248: accumulatedLefts += leftP;
249: }
250: cssBox = cssBox.getParent();
251: }
252: return accumulatedLefts;
253: }
254:
255: /** Gets accumulated horizontal (left and right) margins, border widths, padding
256: * up to the parentBox (excluding). */
257: private static int computeAccumulatedHorizontals(CssBox cssBox,
258: CssBox parentBox) {
259: int accumulatedHorizontals = 0;
260: while (cssBox != null) {
261: if (cssBox == parentBox) {
262: break;
263: }
264: int leftM = cssBox.leftMargin;
265: if (leftM != CssBox.UNINITIALIZED && leftM != CssBox.AUTO) {
266: accumulatedHorizontals += leftM;
267: }
268: int rightM = cssBox.rightMargin;
269: if (rightM != CssBox.UNINITIALIZED && rightM != CssBox.AUTO) {
270: accumulatedHorizontals += rightM;
271: }
272: int leftB = cssBox.leftBorderWidth;
273: if (leftB != CssBox.UNINITIALIZED && leftB != CssBox.AUTO) {
274: accumulatedHorizontals += leftB;
275: }
276: int rightB = cssBox.rightBorderWidth;
277: if (rightB != CssBox.UNINITIALIZED && rightB != CssBox.AUTO) {
278: accumulatedHorizontals += rightB;
279: }
280: int leftP = cssBox.leftPadding;
281: if (leftP != CssBox.UNINITIALIZED && leftP != CssBox.AUTO) {
282: accumulatedHorizontals += leftP;
283: }
284: int rightP = cssBox.rightPadding;
285: if (rightP != CssBox.UNINITIALIZED && rightP != CssBox.AUTO) {
286: accumulatedHorizontals += rightP;
287: }
288: cssBox = cssBox.getParent();
289: }
290: return accumulatedHorizontals;
291: }
292:
293: /**
294: * Given a coordinate in yBox, convert it to a coordinate
295: * in floatParent. Remember that each coordinate is relative to
296: * its parent, so this method essentially finds the nearest
297: * common ancestor box, computes the y coordinate value relative
298: * to that ancestor, it also computes the y coordinate of
299: * the floatParent, and subtracts the yBox from the floatParent
300: * y to compute the y value relative to the floatParent.
301: * (It would be conceptually easier to just call getAbsoluteY()
302: * on both boxes, subtract the difference and add y. But we cannot
303: * call getAbsoluteY() on these boxes here because we are in the
304: * middle of the layout and beyond the float parent the boxes may
305: * not yet be positioned so we'll include UNINITIALIZED constants
306: * in the computation and get wrong results.
307: */
308: int adjustY(int y, CssBox yBox, CssBox floatParent) {
309: // Compute the common ancestor
310: if (yBox == floatParent) {
311: return y;
312: } else {
313: CssBox closest = findCommonAncestor(yBox, floatParent);
314:
315: if (closest == null) {
316: assert false : yBox + ";" + floatParent;
317:
318: return y;
319: }
320:
321: int yb = y;
322:
323: while (yBox != closest) {
324: // XXX #123611 Another case of fatal painting error.
325: // yb += yBox.getY();
326: int yPos = yBox.getY();
327: if (yPos == CssBox.UNINITIALIZED || yPos == CssBox.AUTO) {
328: // break;
329: } else {
330: yb += yBox.getY();
331: }
332: //yBox = yBox.getParent();
333: yBox = yBox.getPositionedBy();
334: // XXX TODO add in margins?
335: }
336:
337: int yf = 0;
338:
339: while (floatParent != closest) {
340: // XXX #123611 Another case of fatal painting error.
341: // yf += floatParent.getY();
342: int yPos = floatParent.getY();
343: if (yPos == CssBox.UNINITIALIZED || yPos == CssBox.AUTO) {
344: // break;
345: } else {
346: yf += floatParent.getY();
347: }
348:
349: //floatParent = floatParent.getParent();
350: floatParent = floatParent.getPositionedBy();
351: // XXX TODO add in margins?
352: }
353:
354: return yb - yf;
355: }
356: }
357:
358: /* Find the closest common ancestor of a and b */
359: private CssBox findCommonAncestor(CssBox a, CssBox b) {
360: for (CssBox outer = a; outer != null; outer = outer.getParent()) {
361: for (CssBox inner = b; inner != null; inner = inner
362: .getParent()) {
363: if (inner == outer) {
364: return inner;
365: }
366: }
367: }
368:
369: return null;
370: }
371:
372: /** Return the maximum x coordinate available - this is the right edge
373: * of the containing block, minus the widths of any floats overlapping
374: * this line.
375: * (Actually, since floats could overlap, it returns the
376: * leftmost coordinate of any float overlapping this line that is
377: * floated to the right.
378: */
379: int getRightEdge(CssBox cssBox, CssBox parent, int y, int height) {
380: // When formatting a floating box, don't look for other floating
381: // boxes!
382: if (floating) {
383: return parent.containingBlockWidth - parent.rightMargin
384: - parent.rightBorderWidth - parent.rightPadding;
385: }
386:
387: int rightEdge = parent.containingBlockWidth;
388: int n = (floats != null) ? floats.size() : 0;
389:
390: for (int i = 0; i < n; i++) {
391: FloatingBoxInfo info = floats.get(i);
392:
393: if (info.leftSide) {
394: continue;
395: }
396:
397: CssBox box = info.box;
398:
399: // XXX #117400 Skip if the cssBox is parent of the float.
400: if (isParentOf(cssBox, box)) {
401: continue;
402: }
403:
404: int yp = adjustY(y, parent, box.getParent());
405:
406: if (((yp + height) > info.y)
407: && (yp < (info.y + box.getHeight()))) {
408: // XXX #117789 One needs to take into account also the margins, borders, paddings.
409: CssBox closest = findCommonAncestor(cssBox, box);
410: int cssBoxAccumulatedHorizontals = 0;
411: int floatBoxAccumulatedLefts = 0;
412: if (closest != null) {
413: cssBoxAccumulatedHorizontals = computeAccumulatedHorizontals(
414: cssBox, closest);
415: floatBoxAccumulatedLefts = computeAccumulatedLefts(
416: box, closest);
417: }
418:
419: int boxLeftEdge = info.x;
420:
421: if ((boxLeftEdge + floatBoxAccumulatedLefts) < (rightEdge + cssBoxAccumulatedHorizontals)) {
422: rightEdge = boxLeftEdge;
423: }
424: }
425: }
426:
427: return rightEdge - parent.rightMargin - parent.rightBorderWidth
428: - parent.rightPadding;
429: }
430:
431: private static boolean isParentOf(CssBox parentBox, CssBox cssBox) {
432: if (parentBox == null || cssBox == null) {
433: return false;
434: }
435:
436: CssBox parent = cssBox.getParent();
437: while (parent != null) {
438: if (parent == parentBox) {
439: return true;
440: }
441: parent = parent.getParent();
442: }
443: return false;
444: }
445:
446: /**
447: * Compute the clearance for a particular y position (compute how much
448: * we have to add to it to clear all the floating boxes on the given
449: * side(s)), as well as removing floats from the list.
450: * @param side The side to be cleared
451: * @param ignoreChildren If not null, ignore any floats that are children of this
452: * given box
453: * @return the absolute y position of the cleared area. Will return Integer.MIN_VALUE
454: * if nothing had to be cleared.
455: */
456: public int clear(CssValue cssSide, CssBox ignoreChildren) {
457: int n = (floats != null) ? floats.size() : 0;
458:
459: if (n == 0) {
460: return Integer.MIN_VALUE;
461: }
462:
463: int cleared = Integer.MIN_VALUE;
464:
465: for (int i = 0; i < n; i++) {
466: FloatingBoxInfo info = floats.get(i);
467:
468: if (ignoreChildren != null) {
469: CssBox curr = info.box;
470: boolean isChild = false;
471:
472: while (curr != null) {
473: if (curr == ignoreChildren) {
474: isChild = true;
475:
476: break;
477: }
478:
479: curr = curr.getParent();
480: }
481:
482: if (isChild) {
483: // TODO - should I skip the float list removal below?
484: continue;
485: }
486: }
487:
488: // if (((side == CssValueConstants.LEFT_VALUE) && !info.leftSide) ||
489: // ((side == CssValueConstants.RIGHT_VALUE) && info.leftSide)) {
490: if ((CssProvider.getValueService().isLeftValue(cssSide) && !info.leftSide)
491: || (CssProvider.getValueService().isRightValue(
492: cssSide) && info.leftSide)) {
493: continue;
494: }
495:
496: CssBox box = info.box;
497: int bottom = box.getAbsoluteY() + box.getHeight();
498:
499: if (bottom > cleared) {
500: cleared = bottom;
501: }
502: }
503:
504: // Remove items from the clear list that are no longer in flow "scope".
505: // E.g. if we've cleared items in the list we no longer have to check for
506: // them.
507: boolean skip = false;
508:
509: // if (side != CssValueConstants.BOTH_VALUE) {
510: if (CssProvider.getValueService().isBothValue(cssSide)) {
511: for (int i = 0; i < n; i++) {
512: FloatingBoxInfo info = floats.get(i);
513:
514: // if (((side == CssValueConstants.LEFT_VALUE) && !info.leftSide) ||
515: // ((side == CssValueConstants.RIGHT_VALUE) && info.leftSide)) {
516: if ((CssProvider.getValueService().isLeftValue(cssSide) && !info.leftSide)
517: || (CssProvider.getValueService().isRightValue(
518: cssSide) && info.leftSide)) {
519: skip = true;
520:
521: continue;
522: }
523: }
524: }
525:
526: if (skip) {
527: // Gotta remove just some from the float list, not all
528: for (int i = 0; i < n; i++) {
529: FloatingBoxInfo info = floats.get(i);
530:
531: // if (((side == CssValueConstants.LEFT_VALUE) && !info.leftSide) ||
532: // ((side == CssValueConstants.RIGHT_VALUE) && info.leftSide)) {
533: if ((CssProvider.getValueService().isLeftValue(cssSide) && !info.leftSide)
534: || (CssProvider.getValueService().isRightValue(
535: cssSide) && info.leftSide)) {
536: floats.remove(info);
537: }
538: }
539:
540: if (floats.size() == 0) {
541: floats = null;
542: }
543: } else {
544: floats = null;
545: }
546:
547: return cleared;
548: }
549:
550: private boolean isImportantFloat(CssBox flt, boolean left,
551: boolean right) {
552: CssValue cssFloating = CssProvider.getEngineService()
553: .getComputedValueForElement(flt.getElement(),
554: XhtmlCss.FLOAT_INDEX);
555: CssValueService service = CssProvider.getValueService();
556: return (left && service.isLeftValue(cssFloating) || right
557: && service.isRightValue(cssFloating));
558: }
559:
560: /**
561: * Depending on "clear" property of the box, looks for a previous floating box
562: * on either or both sides of the containing block.
563: * left
564: * The top margin of the generated box is increased enough that the top border edge
565: * is below the bottom outer edge of any left-floating boxes
566: * that resulted from elements earlier in the source document.
567: * This is not the most efficient algorithm perhaps. We can instead look for a lowest
568: * line box containing a float and then took a longer float within it.
569: * However, this algorithm looks right.
570: */
571: CssBox getPrevFloatingForClear(CssBox box) {
572: if (!box.isClearBox()) {
573: //the box has no "clear" property
574: return (null);
575: }
576:
577: CssValue clearValue = CssProvider.getEngineService()
578: .getComputedValueForElement(box.getElement(),
579: XhtmlCss.CLEAR_INDEX);
580: CssValueService service = CssProvider.getValueService();
581:
582: return (getLowestBottom(box,
583: (service.isLeftValue(clearValue) || service
584: .isBothValue(clearValue)), (service
585: .isRightValue(clearValue) || service
586: .isBothValue(clearValue))));
587: }
588:
589: CssBox getLowestFloatingForFloat(CssBox box) {
590:
591: CssValue floatValue = CssProvider.getEngineService()
592: .getComputedValueForElement(box.getElement(),
593: XhtmlCss.FLOAT_INDEX);
594: CssValueService service = CssProvider.getValueService();
595:
596: return (getLowestBottom(box, true, true));
597: //return(getLowestBottom(box, service.isLeftValue(floatValue), service.isRightValue(floatValue)));
598: }
599:
600: private CssBox getLowestBottom(CssBox box, boolean left,
601: boolean right) {
602: int n = (floats != null) ? floats.size() : 0;
603:
604: if (n == 0) {
605: return null;
606: }
607:
608: CssBox clearContainerBox = findClearContainer(box);
609:
610: int maxNextPosition = Integer.MIN_VALUE;
611: int yAdj;
612: CssBox yBox, result = null;
613: for (int i = 0; i < n; i++) {
614: FloatingBoxInfo info = floats.get(i);
615: if (info.box == box
616: || parentOf(box, info.box)
617: || (clearContainerBox != null && parentOf(info.box,
618: clearContainerBox))) {
619: return (result);
620: }
621: if (canAdjustY(info.box, box.getPositionedBy())) {
622: if (isImportantFloat(info.box, left, right)) {
623: yAdj = adjustY(0, info.box, box.getPositionedBy())
624: + info.box.getHeight();
625: if (yAdj > maxNextPosition) {
626: maxNextPosition = yAdj;
627: result = info.box;
628: }
629: }
630: }
631: }
632: return (result);
633: }
634:
635: private static CssBox findClearContainer(CssBox box) {
636: CssBox parent = box;
637: while ((parent = parent.getParent()) != null) {
638: CssValue cssClear = CssProvider.getEngineService()
639: .getComputedValueForElement(parent.getElement(),
640: XhtmlCss.CLEAR_INDEX);
641:
642: if (CssProvider.getValueService().isBothValue(cssClear)
643: || CssProvider.getValueService().isLeftValue(
644: cssClear)
645: || CssProvider.getValueService().isRightValue(
646: cssClear))
647: return (parent);
648: }
649: return (null);
650: }
651:
652: private CssBox getLowestTop(CssBox box) {
653: int n = (floats != null) ? floats.size() : 0;
654:
655: if (n == 0) {
656: return null;
657: }
658:
659: int maxNextPosition = Integer.MIN_VALUE;
660: int yAdj;
661: CssBox result = null;
662: for (int i = 0; i < n; i++) {
663: FloatingBoxInfo info = floats.get(i);
664: // XXX #117400 If this is parent of the float stop.
665: if (info.box == box) {
666: // if(info.box == box || isParentOf(box, info.box)) {
667: return (result);
668: }
669: if (isParentOf(box, info.box)) {
670: continue;
671: }
672: if (canAdjustY(info.box, box.getPositionedBy())) {
673: yAdj = adjustY(0, info.box, box.getPositionedBy());
674: // XXX #117400 Use the parent float.
675: // if(yAdj > maxNextPosition) {
676: if (yAdj > maxNextPosition
677: || isParentOf(info.box, result)) {
678: maxNextPosition = yAdj;
679: result = info.box;
680: }
681: }
682: }
683: return (result);
684: }
685:
686: /*
687: * Checks if all parents are positioned up to common parent.
688: */
689: private boolean canAdjustY(CssBox box1, CssBox box2) {
690: CssBox closest = findCommonAncestor(box1, box2);
691: while (box1 != closest) {
692: if (box1.getY() == CssBox.UNINITIALIZED) {
693: return false;
694: }
695: box1 = box1.getPositionedBy();
696: }
697: while (box2 != closest) {
698: if (box2.getY() == CssBox.UNINITIALIZED) {
699: return false;
700: }
701: box2 = box2.getPositionedBy();
702: }
703: return (true);
704: }
705:
706: private boolean parentOf(CssBox container, CssBox box) {
707: CssBox parent = box;
708: while ((parent = parent.getParent()) != null) {
709: if (parent == container) {
710: return (true);
711: }
712: }
713: return (false);
714: }
715:
716: /**
717: * Looks for a previous floating box
718: */
719: CssBox getPrevFloatingForFloat(CssBox box) {
720: int n = (floats != null) ? floats.size() : 0;
721:
722: if (n == 0) {
723: return null;
724: }
725:
726: //the code below does not work
727: //in some cases some of the floats may not be positioned vertically yet,
728: //so it is not enough just to look on the previous box -
729: //we really have to find a lowest top between the already positioned
730: //ones
731: /*
732: CssBox lastOne = null;
733: for (int i = 0; i < n; i++) {
734: FloatingBoxInfo info = (FloatingBoxInfo)floats.get(i);
735: if(info.box == box || parentOf(box, info.box)) {
736: return(lastOne);
737: }
738: lastOne = info.box;
739: }
740: */
741: return (getLowestTop(box));
742: }
743: }
|