Back to index

lightning-sunbird  0.9+nobinonly
nsBoxFrame.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* vim: set ts=2 sw=2 et tw=80: */
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is Mozilla Communicator client code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Pierre Phaneuf <pp@ludusdesign.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 //
00041 // Eric Vaughan
00042 // Netscape Communications
00043 //
00044 // See documentation in associated header file
00045 //
00046 
00047 // How boxes layout
00048 // ----------------
00049 // Boxes layout a bit differently than html. html does a bottom up layout. Where boxes do a top down.
00050 // 1) First thing a box does it goes out and askes each child for its min, max, and preferred sizes.
00051 // 2) It then adds them up to determine its size.
00052 // 3) If the box was asked to layout it self intrinically it will layout its children at their preferred size
00053 //    otherwise it will layout the child at the size it was told to. It will squeeze or stretch its children if 
00054 //    Necessary.
00055 //
00056 // However there is a catch. Some html components like block frames can not determine their preferred size. 
00057 // this is their size if they were layed out intrinsically. So the box will flow the child to determine this can
00058 // cache the value.
00059 
00060 // Boxes and Incremental Reflow
00061 // ----------------------------
00062 // Boxes layout out top down by adding up their childrens min, max, and preferred sizes. Only problem is if a incremental
00063 // reflow occurs. The preferred size of a child deep in the hierarchy could change. And this could change
00064 // any number of syblings around the box. Basically any children in the reflow chain must have their caches cleared
00065 // so when asked for there current size they can relayout themselves. 
00066 
00067 #include "nsBoxLayoutState.h"
00068 #include "nsBoxFrame.h"
00069 #include "nsStyleContext.h"
00070 #include "nsPresContext.h"
00071 #include "nsCOMPtr.h"
00072 #include "nsUnitConversion.h"
00073 #include "nsINameSpaceManager.h"
00074 #include "nsHTMLAtoms.h"
00075 #include "nsXULAtoms.h"
00076 #include "nsIContent.h"
00077 #include "nsSpaceManager.h"
00078 #include "nsHTMLParts.h"
00079 #include "nsIViewManager.h"
00080 #include "nsIView.h"
00081 #include "nsIPresShell.h"
00082 #include "nsFrameNavigator.h"
00083 #include "nsCSSRendering.h"
00084 #include "nsIServiceManager.h"
00085 #include "nsIBoxLayout.h"
00086 #include "nsSprocketLayout.h"
00087 #include "nsIDocument.h"
00088 #include "nsIBindingManager.h"
00089 #include "nsIScrollableFrame.h"
00090 #include "nsWidgetsCID.h"
00091 #include "nsLayoutAtoms.h"
00092 #include "nsCSSAnonBoxes.h"
00093 #include "nsIScrollableView.h"
00094 #include "nsHTMLContainerFrame.h"
00095 #include "nsIWidget.h"
00096 #include "nsIEventStateManager.h"
00097 #include "nsIDOMDocument.h"
00098 #include "nsIDOMElement.h"
00099 #include "nsITheme.h"
00100 #include "nsTransform2D.h"
00101 #include "nsIEventListenerManager.h"
00102 #include "nsIEventStateManager.h"
00103 #include "nsIDOMEvent.h"
00104 #include "nsIPrivateDOMEvent.h"
00105 #include "nsContentUtils.h"
00106 
00107 // Needed for Print Preview
00108 #include "nsIDocument.h"
00109 #include "nsIURI.h"
00110 
00111 
00112 static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
00113 
00114 //define DEBUG_REDRAW
00115 
00116 #define DEBUG_SPRING_SIZE 8
00117 #define DEBUG_BORDER_SIZE 2
00118 #define COIL_SIZE 8
00119 
00120 //#define TEST_SANITY
00121 
00122 #ifdef DEBUG_rods
00123 //#define DO_NOISY_REFLOW
00124 #endif
00125 
00126 #ifdef DEBUG_LAYOUT
00127 PRBool nsBoxFrame::gDebug = PR_FALSE;
00128 nsIBox* nsBoxFrame::mDebugChild = nsnull;
00129 #endif
00130 
00131 nsresult
00132 NS_NewBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoot, nsIBoxLayout* aLayoutManager)
00133 {
00134   NS_PRECONDITION(aNewFrame, "null OUT ptr");
00135   if (nsnull == aNewFrame) {
00136     return NS_ERROR_NULL_POINTER;
00137   }
00138   nsBoxFrame* it = new (aPresShell) nsBoxFrame(aPresShell, aIsRoot, aLayoutManager);
00139 
00140   if (nsnull == it)
00141     return NS_ERROR_OUT_OF_MEMORY;
00142 
00143   *aNewFrame = it;
00144 
00145   return NS_OK;
00146   
00147 } // NS_NewBoxFrame
00148 
00149 nsBoxFrame::nsBoxFrame(nsIPresShell* aPresShell, PRBool aIsRoot, nsIBoxLayout* aLayoutManager)
00150   : mMouseThrough(unset)
00151 {
00152   mState |= NS_FRAME_IS_BOX;
00153   mState |= NS_STATE_IS_HORIZONTAL;
00154   mState |= NS_STATE_AUTO_STRETCH;
00155 
00156   if (aIsRoot) 
00157      mState |= NS_STATE_IS_ROOT;
00158 
00159   mValign = vAlign_Top;
00160   mHalign = hAlign_Left;
00161   
00162   // if no layout manager specified us the static sprocket layout
00163   nsCOMPtr<nsIBoxLayout> layout = aLayoutManager;
00164 
00165   if (layout == nsnull) {
00166     NS_NewSprocketLayout(aPresShell, layout);
00167   }
00168 
00169   SetLayoutManager(layout);
00170 
00171   NeedsRecalc();
00172 }
00173 
00174 nsBoxFrame::~nsBoxFrame()
00175 {
00176 }
00177 
00178 NS_IMETHODIMP
00179 nsBoxFrame::GetVAlign(Valignment& aAlign)
00180 {
00181    aAlign = mValign;
00182    return NS_OK;
00183 }
00184 
00185 NS_IMETHODIMP
00186 nsBoxFrame::GetHAlign(Halignment& aAlign)
00187 {
00188    aAlign = mHalign;
00189    return NS_OK;
00190 }
00191 
00192 NS_IMETHODIMP
00193 nsBoxFrame::SetInitialChildList(nsPresContext* aPresContext,
00194                                 nsIAtom*        aListName,
00195                                 nsIFrame*       aChildList)
00196 {
00197   nsresult r = nsContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList);
00198   if (r == NS_OK) {
00199     // initialize our list of infos.
00200     nsBoxLayoutState state(aPresContext->PresShell());
00201     CheckBoxOrder(state);
00202     if (mLayoutManager)
00203       mLayoutManager->ChildrenSet(this, state, mFrames.FirstChild());
00204   } else {
00205     NS_WARNING("Warning add child failed!!\n");
00206   }
00207 
00208   return r;
00209 }
00210 
00214 NS_IMETHODIMP
00215 nsBoxFrame::Init(nsPresContext*  aPresContext,
00216                  nsIContent*      aContent,
00217                  nsIFrame*        aParent,
00218                  nsStyleContext*  aContext,
00219                  nsIFrame*        aPrevInFlow)
00220 {
00221   mPresContext = aPresContext;
00222 
00223   nsresult  rv = nsContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
00224   NS_ENSURE_SUCCESS(rv, rv);
00225 
00226   // see if we need a widget. Get our parent. Querty interface the parent we are given. 
00227   if (aParent && aParent->IsBoxFrame()) {
00228     PRBool needsWidget = PR_FALSE;
00229     aParent->ChildrenMustHaveWidgets(needsWidget);
00230     if (needsWidget) {
00231         rv = nsHTMLContainerFrame::CreateViewForFrame(this, nsnull, PR_TRUE);
00232         NS_ENSURE_SUCCESS(rv, rv);
00233 
00234         nsIView* view = GetView();
00235         if (!view->HasWidget())
00236            view->CreateWidget(kWidgetCID);   
00237     }
00238   }
00239 
00240   CacheAttributes();
00241 
00242 #ifdef DEBUG_LAYOUT
00243     // if we are root and this
00244   if (mState & NS_STATE_IS_ROOT) 
00245       GetDebugPref(aPresContext);
00246 #endif
00247 
00248   mMouseThrough = unset;
00249 
00250   UpdateMouseThrough();
00251 
00252   // register access key
00253   rv = RegUnregAccessKey(aPresContext, PR_TRUE);
00254 
00255   return rv;
00256 }
00257 
00258 void nsBoxFrame::UpdateMouseThrough()
00259 {
00260   if (mContent) {
00261     nsAutoString value;
00262     if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, nsXULAtoms::mousethrough, value)) {
00263         if (value.EqualsLiteral("never"))
00264           mMouseThrough = never;
00265         else if (value.EqualsLiteral("always"))
00266           mMouseThrough = always;
00267       
00268     }
00269   }
00270 }
00271 
00272 NS_IMETHODIMP
00273 nsBoxFrame::GetMouseThrough(PRBool& aMouseThrough)
00274 {
00275   switch(mMouseThrough)
00276   {
00277     case always:
00278       aMouseThrough = PR_TRUE;
00279       return NS_OK;
00280     case never:
00281       aMouseThrough = PR_FALSE;      
00282       return NS_OK;
00283     case unset:
00284     {
00285       if (mParent && mParent->IsBoxFrame())
00286         return mParent->GetMouseThrough(aMouseThrough);
00287       else {
00288         aMouseThrough = PR_FALSE;      
00289         return NS_OK;
00290       }
00291     }
00292   }
00293 
00294   return NS_ERROR_FAILURE;
00295 }
00296 
00297 void
00298 nsBoxFrame::CacheAttributes()
00299 {
00300   /*
00301   printf("Caching: ");
00302   DumpBox(stdout);
00303   printf("\n");
00304    */
00305 
00306   mValign = vAlign_Top;
00307   mHalign = hAlign_Left;
00308 
00309   PRBool orient = PR_FALSE;
00310   GetInitialOrientation(orient); 
00311   if (orient)
00312     mState |= NS_STATE_IS_HORIZONTAL;
00313   else
00314     mState &= ~NS_STATE_IS_HORIZONTAL;
00315 
00316   PRBool normal = PR_TRUE;
00317   GetInitialDirection(normal); 
00318   if (normal)
00319     mState |= NS_STATE_IS_DIRECTION_NORMAL;
00320   else
00321     mState &= ~NS_STATE_IS_DIRECTION_NORMAL;
00322 
00323   GetInitialVAlignment(mValign);
00324   GetInitialHAlignment(mHalign);
00325   
00326   PRBool equalSize = PR_FALSE;
00327   GetInitialEqualSize(equalSize); 
00328   if (equalSize)
00329         mState |= NS_STATE_EQUAL_SIZE;
00330     else
00331         mState &= ~NS_STATE_EQUAL_SIZE;
00332 
00333   PRBool autostretch = mState & NS_STATE_AUTO_STRETCH;
00334   GetInitialAutoStretch(autostretch);
00335   if (autostretch)
00336         mState |= NS_STATE_AUTO_STRETCH;
00337      else
00338         mState &= ~NS_STATE_AUTO_STRETCH;
00339 
00340 
00341 #ifdef DEBUG_LAYOUT
00342   PRBool debug = mState & NS_STATE_SET_TO_DEBUG;
00343   PRBool debugSet = GetInitialDebug(debug); 
00344   if (debugSet) {
00345         mState |= NS_STATE_DEBUG_WAS_SET;
00346         if (debug)
00347             mState |= NS_STATE_SET_TO_DEBUG;
00348         else
00349             mState &= ~NS_STATE_SET_TO_DEBUG;
00350   } else {
00351         mState &= ~NS_STATE_DEBUG_WAS_SET;
00352   }
00353 #endif
00354 }
00355 
00356 #ifdef DEBUG_LAYOUT
00357 PRBool
00358 nsBoxFrame::GetInitialDebug(PRBool& aDebug)
00359 {
00360   nsAutoString value;
00361 
00362   nsCOMPtr<nsIContent> content;
00363   GetContentOf(getter_AddRefs(content));
00364 
00365   if (!content)
00366     return PR_FALSE;
00367 
00368 
00369   if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, nsXULAtoms::debug, value)) {
00370       if (value.EqualsLiteral("true")) {
00371           aDebug = PR_TRUE;
00372           return PR_TRUE;
00373       } else if (value.EqualsLiteral("false")) {
00374           aDebug = PR_FALSE;
00375           return PR_TRUE;
00376       }
00377   }
00378 
00379   return PR_FALSE;
00380 }
00381 #endif
00382 
00383 PRBool
00384 nsBoxFrame::GetInitialHAlignment(nsBoxFrame::Halignment& aHalign)
00385 {
00386   nsAutoString value;
00387 
00388   nsCOMPtr<nsIContent> content;
00389   GetContentOf(getter_AddRefs(content));
00390   if (!content)
00391     return PR_FALSE;
00392 
00393   if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, nsHTMLAtoms::align, value)) {
00394     // XXXdwh Everything inside this if statement is deprecated code.
00395     if (value.EqualsLiteral("left")) {
00396         aHalign = nsBoxFrame::hAlign_Left;
00397         return PR_TRUE;
00398     } else if (value.EqualsLiteral("right")) {
00399         aHalign = nsBoxFrame::hAlign_Right;
00400         return PR_TRUE;
00401     }
00402   }
00403       
00404   // Now that the deprecated stuff is out of the way, we move on to check the appropriate 
00405   // attribute.  For horizontal boxes, we are checking the PACK attribute.  For vertical boxes
00406   // we are checking the ALIGN attribute.
00407   nsresult res;
00408   if (IsHorizontal())
00409     res = content->GetAttr(kNameSpaceID_None, nsXULAtoms::pack, value);
00410   else res = content->GetAttr(kNameSpaceID_None, nsHTMLAtoms::align, value);
00411   if (res == NS_CONTENT_ATTR_HAS_VALUE) {
00412     if (value.EqualsLiteral("start")) {
00413         aHalign = nsBoxFrame::hAlign_Left;
00414         return PR_TRUE;
00415     } else if (value.EqualsLiteral("center")) {
00416         aHalign = nsBoxFrame::hAlign_Center;
00417         return PR_TRUE;
00418     } else if (value.EqualsLiteral("end")) {
00419         aHalign = nsBoxFrame::hAlign_Right;
00420         return PR_TRUE;
00421     }
00422 
00423     // The attr was present but had a nonsensical value. Revert to the default.
00424     return PR_FALSE;
00425   }
00426 
00427   // Now that we've checked for the attribute it's time to check CSS.  For 
00428   // horizontal boxes we're checking PACK.  For vertical boxes we are checking
00429   // ALIGN.
00430   const nsStyleXUL* boxInfo = GetStyleXUL();
00431   if (IsHorizontal()) {
00432     switch (boxInfo->mBoxPack) {
00433       case NS_STYLE_BOX_PACK_START:
00434         aHalign = nsBoxFrame::hAlign_Left;
00435         return PR_TRUE;
00436       case NS_STYLE_BOX_PACK_CENTER:
00437         aHalign = nsBoxFrame::hAlign_Center;
00438         return PR_TRUE;
00439       case NS_STYLE_BOX_PACK_END:
00440         aHalign = nsBoxFrame::hAlign_Right;
00441         return PR_TRUE;
00442       default: // Nonsensical value. Just bail.
00443         return PR_FALSE;
00444     }
00445   }
00446   else {
00447     switch (boxInfo->mBoxAlign) {
00448       case NS_STYLE_BOX_ALIGN_START:
00449         aHalign = nsBoxFrame::hAlign_Left;
00450         return PR_TRUE;
00451       case NS_STYLE_BOX_ALIGN_CENTER:
00452         aHalign = nsBoxFrame::hAlign_Center;
00453         return PR_TRUE;
00454       case NS_STYLE_BOX_ALIGN_END:
00455         aHalign = nsBoxFrame::hAlign_Right;
00456         return PR_TRUE;
00457       default: // Nonsensical value. Just bail.
00458         return PR_FALSE;
00459     }
00460   }
00461 
00462   return PR_FALSE;
00463 }
00464 
00465 PRBool
00466 nsBoxFrame::GetInitialVAlignment(nsBoxFrame::Valignment& aValign)
00467 {
00468 
00469   nsAutoString value;
00470 
00471   nsCOMPtr<nsIContent> content;
00472   GetContentOf(getter_AddRefs(content));
00473   if (!content)
00474     return PR_FALSE;
00475 
00476   if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, nsHTMLAtoms::valign, value)) {
00477     if (value.EqualsLiteral("top")) {
00478         aValign = nsBoxFrame::vAlign_Top;
00479         return PR_TRUE;
00480     } else if (value.EqualsLiteral("baseline")) {
00481         aValign = nsBoxFrame::vAlign_BaseLine;
00482         return PR_TRUE;
00483     } else if (value.EqualsLiteral("middle")) {
00484         aValign = nsBoxFrame::vAlign_Middle;
00485         return PR_TRUE;
00486     } else if (value.EqualsLiteral("bottom")) {
00487         aValign = nsBoxFrame::vAlign_Bottom;
00488         return PR_TRUE;
00489     }
00490   }
00491 
00492   // Now that the deprecated stuff is out of the way, we move on to check the appropriate 
00493   // attribute.  For horizontal boxes, we are checking the ALIGN attribute.  For vertical boxes
00494   // we are checking the PACK attribute.
00495   nsresult res;
00496   if (IsHorizontal())
00497     res = content->GetAttr(kNameSpaceID_None, nsHTMLAtoms::align, value);
00498   else res = content->GetAttr(kNameSpaceID_None, nsXULAtoms::pack, value);
00499   if (res == NS_CONTENT_ATTR_HAS_VALUE) {
00500     if (value.EqualsLiteral("start")) {
00501         aValign = nsBoxFrame::vAlign_Top;
00502         return PR_TRUE;
00503     } else if (value.EqualsLiteral("center")) {
00504         aValign = nsBoxFrame::vAlign_Middle;
00505         return PR_TRUE;
00506     } else if (value.EqualsLiteral("baseline")) {
00507         aValign = nsBoxFrame::vAlign_BaseLine;
00508         return PR_TRUE;
00509     } else if (value.EqualsLiteral("end")) {
00510         aValign = nsBoxFrame::vAlign_Bottom;
00511         return PR_TRUE;
00512     }
00513     // The attr was present but had a nonsensical value. Revert to the default.
00514     return PR_FALSE;
00515   }
00516 
00517   // Now that we've checked for the attribute it's time to check CSS.  For 
00518   // horizontal boxes we're checking ALIGN.  For vertical boxes we are checking
00519   // PACK.
00520   const nsStyleXUL* boxInfo = GetStyleXUL();
00521   if (IsHorizontal()) {
00522     switch (boxInfo->mBoxAlign) {
00523       case NS_STYLE_BOX_ALIGN_START:
00524         aValign = nsBoxFrame::vAlign_Top;
00525         return PR_TRUE;
00526       case NS_STYLE_BOX_ALIGN_CENTER:
00527         aValign = nsBoxFrame::vAlign_Middle;
00528         return PR_TRUE;
00529       case NS_STYLE_BOX_ALIGN_BASELINE:
00530         aValign = nsBoxFrame::vAlign_BaseLine;
00531         return PR_TRUE;
00532       case NS_STYLE_BOX_ALIGN_END:
00533         aValign = nsBoxFrame::vAlign_Bottom;
00534         return PR_TRUE;
00535       default: // Nonsensical value. Just bail.
00536         return PR_FALSE;
00537     }
00538   }
00539   else {
00540     switch (boxInfo->mBoxPack) {
00541       case NS_STYLE_BOX_PACK_START:
00542         aValign = nsBoxFrame::vAlign_Top;
00543         return PR_TRUE;
00544       case NS_STYLE_BOX_PACK_CENTER:
00545         aValign = nsBoxFrame::vAlign_Middle;
00546         return PR_TRUE;
00547       case NS_STYLE_BOX_PACK_END:
00548         aValign = nsBoxFrame::vAlign_Bottom;
00549         return PR_TRUE;
00550       default: // Nonsensical value. Just bail.
00551         return PR_FALSE;
00552     }
00553   }
00554 
00555   return PR_FALSE;
00556 }
00557 
00558 /* Returns true if it was set.
00559  */
00560 void
00561 nsBoxFrame::GetInitialOrientation(PRBool& aIsHorizontal)
00562 {
00563  // see if we are a vertical or horizontal box.
00564   nsAutoString value;
00565 
00566   nsCOMPtr<nsIContent> content;
00567   GetContentOf(getter_AddRefs(content));
00568 
00569   if (!content)
00570     return;
00571 
00572   // Check the style system first.
00573   const nsStyleXUL* boxInfo = GetStyleXUL();
00574   if (boxInfo->mBoxOrient == NS_STYLE_BOX_ORIENT_HORIZONTAL)
00575     aIsHorizontal = PR_TRUE;
00576   else 
00577     aIsHorizontal = PR_FALSE;
00578 
00579   // Now see if we have an attribute.  The attribute overrides
00580   // the style system value.
00581   if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, nsXULAtoms::orient, value)) {
00582     if (value.EqualsLiteral("vertical"))
00583       aIsHorizontal = PR_FALSE;
00584     else if (value.EqualsLiteral("horizontal"))
00585      aIsHorizontal = PR_TRUE;
00586   }
00587 }
00588 
00589 void
00590 nsBoxFrame::GetInitialDirection(PRBool& aIsNormal)
00591 {
00592   nsAutoString value;
00593   nsCOMPtr<nsIContent> content;
00594   GetContentOf(getter_AddRefs(content));
00595 
00596   if (!content)
00597     return;
00598 
00599   if (IsHorizontal()) {
00600     // For horizontal boxes only, we initialize our value based off the CSS 'direction' property.
00601     // This means that BiDI users will end up with horizontally inverted chrome.
00602     aIsNormal = (GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR); // If text runs RTL then so do we.
00603   }
00604   else
00605     aIsNormal = PR_TRUE; // Assume a normal direction in the vertical case.
00606 
00607   // Now check the style system to see if we should invert aIsNormal.
00608   const nsStyleXUL* boxInfo = GetStyleXUL();
00609   if (boxInfo->mBoxDirection == NS_STYLE_BOX_DIRECTION_REVERSE)
00610     aIsNormal = !aIsNormal; // Invert our direction.
00611   
00612   // Now see if we have an attribute.  The attribute overrides
00613   // the style system value.
00614   if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, nsXULAtoms::dir, value)) {
00615     if (value.EqualsLiteral("reverse"))
00616       aIsNormal = !aIsNormal; // Invert our direction.
00617     else if (value.EqualsLiteral("ltr"))
00618       aIsNormal = PR_TRUE;
00619     else if (value.EqualsLiteral("rtl"))
00620       aIsNormal = PR_FALSE;
00621   }
00622 }
00623 
00624 /* Returns true if it was set.
00625  */
00626 PRBool
00627 nsBoxFrame::GetInitialEqualSize(PRBool& aEqualSize)
00628 {
00629  // see if we are a vertical or horizontal box.
00630   nsAutoString value;
00631 
00632   nsCOMPtr<nsIContent> content;
00633   GetContentOf(getter_AddRefs(content));
00634 
00635   if (!content)
00636      return PR_FALSE;
00637 
00638   if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, nsXULAtoms::equalsize, value))
00639   {
00640       if (value.EqualsLiteral("always")) {
00641          aEqualSize = PR_TRUE;
00642          return PR_TRUE;
00643       }
00644   } 
00645 
00646   return PR_FALSE;
00647 }
00648 
00649 /* Returns true if it was set.
00650  */
00651 PRBool
00652 nsBoxFrame::GetInitialAutoStretch(PRBool& aStretch)
00653 {
00654   nsAutoString value;
00655 
00656   nsCOMPtr<nsIContent> content;
00657   GetContentOf(getter_AddRefs(content));
00658 
00659   if (!content)
00660      return PR_FALSE;
00661   
00662   // Check the align attribute.
00663   if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, nsHTMLAtoms::align, value)) {
00664     aStretch = value.EqualsLiteral("stretch");
00665     return PR_TRUE;
00666   }
00667 
00668   // Check the CSS box-align property.
00669   const nsStyleXUL* boxInfo = GetStyleXUL();
00670   aStretch = (boxInfo->mBoxAlign == NS_STYLE_BOX_ALIGN_STRETCH);
00671 
00672   return PR_TRUE;
00673 }
00674 
00675 
00676 NS_IMETHODIMP
00677 nsBoxFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild)
00678 {
00679    // if we receive a ReflowDirtyChild it is because there is an HTML frame 
00680    // just inside us. So must find the adaptor that contains the child and
00681    // tell it that things are dirty.
00682    nsBoxLayoutState state(aPresShell->GetPresContext());
00683 
00684    nsIBox* box = nsnull;
00685    GetChildBox(&box);
00686    while (box)
00687    {
00688      if (box == aChild) {
00689        box->MarkDirty(state);
00690        return RelayoutDirtyChild(state, box);
00691      }
00692 
00693      box->GetNextBox(&box);
00694    }
00695 
00696    NS_ERROR("Could not find an adaptor!");
00697    return NS_OK;
00698 }
00699 
00700 NS_IMETHODIMP
00701 nsBoxFrame::DidReflow(nsPresContext*           aPresContext,
00702                       const nsHTMLReflowState*  aReflowState,
00703                       nsDidReflowStatus         aStatus)
00704 {
00705   nsFrameState preserveBits =
00706     mState & (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN);
00707   nsresult rv = nsFrame::DidReflow(aPresContext, aReflowState, aStatus);
00708   mState |= preserveBits;
00709   return rv;
00710 }
00711 
00712 #ifdef DO_NOISY_REFLOW
00713 static int myCounter = 0;
00714 static void printSize(char * aDesc, nscoord aSize) 
00715 {
00716   printf(" %s: ", aDesc);
00717   if (aSize == NS_UNCONSTRAINEDSIZE) {
00718     printf("UC");
00719   } else {
00720     printf("%d", aSize);
00721   }
00722 }
00723 #endif
00724 
00730 PRBool
00731 nsBoxFrame::IsInitialReflowForPrintPreview(nsBoxLayoutState& aState, 
00732                                            PRBool& aIsChrome)
00733 {
00734   aIsChrome = PR_FALSE;
00735   const nsHTMLReflowState* reflowState = aState.GetReflowState();
00736   if (reflowState->reason == eReflowReason_Initial) {
00737     // See if we are doing Print Preview
00738     if (aState.PresContext()->Type() == nsPresContext::eContext_PrintPreview) {
00739       // Now, get the current URI to see if we doing chrome
00740       nsIPresShell *presShell = aState.PresShell();
00741       if (!presShell) return PR_FALSE;
00742       nsIDocument *doc = presShell->GetDocument();
00743       if (!doc) return PR_FALSE;
00744       nsIURI *uri = doc->GetDocumentURI();
00745       if (!uri) return PR_FALSE;
00746       uri->SchemeIs("chrome", &aIsChrome);
00747       return PR_TRUE;
00748     }
00749   }
00750   return PR_FALSE;
00751 }
00752 
00753 NS_IMETHODIMP
00754 nsBoxFrame::Reflow(nsPresContext*          aPresContext,
00755                    nsHTMLReflowMetrics&     aDesiredSize,
00756                    const nsHTMLReflowState& aReflowState,
00757                    nsReflowStatus&          aStatus)
00758 {
00759   // If you make changes to this method, please keep nsLeafBoxFrame::Reflow
00760   // in sync, if the changes are applicable there.
00761 
00762   DO_GLOBAL_REFLOW_COUNT("nsBoxFrame", aReflowState.reason);
00763   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
00764 
00765   NS_ASSERTION(aReflowState.mComputedWidth >=0 && aReflowState.mComputedHeight >= 0, "Computed Size < 0");
00766 
00767 #ifdef DO_NOISY_REFLOW
00768   printf("\n-------------Starting BoxFrame Reflow ----------------------------\n");
00769   printf("%p ** nsBF::Reflow %d R: ", this, myCounter++);
00770   switch (aReflowState.reason) {
00771     case eReflowReason_Initial:
00772       printf("Ini");break;
00773     case eReflowReason_Incremental:
00774       printf("Inc");break;
00775     case eReflowReason_Resize:
00776       printf("Rsz");break;
00777     case eReflowReason_StyleChange:
00778       printf("Sty");break;
00779     case eReflowReason_Dirty:
00780       printf("Drt ");
00781       break;
00782     default:printf("<unknown>%d", aReflowState.reason);break;
00783   }
00784   
00785   printSize("AW", aReflowState.availableWidth);
00786   printSize("AH", aReflowState.availableHeight);
00787   printSize("CW", aReflowState.mComputedWidth);
00788   printSize("CH", aReflowState.mComputedHeight);
00789 
00790   printf(" *\n");
00791 
00792 #endif
00793 
00794   aStatus = NS_FRAME_COMPLETE;
00795 
00796   // create the layout state
00797   nsBoxLayoutState state(aPresContext, aReflowState, aDesiredSize);
00798 
00799   // coelesce reflows if we are root.
00800   state.HandleReflow(this);
00801   
00802   nsSize computedSize(aReflowState.mComputedWidth,aReflowState.mComputedHeight);
00803 
00804   nsMargin m;
00805   m = aReflowState.mComputedBorderPadding;
00806   // GetBorderAndPadding(m);
00807 
00808   nsSize prefSize(0,0);
00809 
00810   // if we are told to layout intrinic then get our preferred size.
00811   if (computedSize.width == NS_INTRINSICSIZE || computedSize.height == NS_INTRINSICSIZE) {
00812      nsSize minSize(0,0);
00813      nsSize maxSize(0,0);
00814      GetPrefSize(state, prefSize);
00815      GetMinSize(state,  minSize);
00816      GetMaxSize(state,  maxSize);
00817      BoundsCheck(minSize, prefSize, maxSize);
00818   }
00819 
00820   // get our desiredSize
00821   if (aReflowState.mComputedWidth == NS_INTRINSICSIZE) {
00822     computedSize.width = prefSize.width;
00823   } else {
00824     computedSize.width += m.left + m.right;
00825   }
00826 
00827   if (aReflowState.mComputedHeight == NS_INTRINSICSIZE) {
00828     computedSize.height = prefSize.height;
00829   } else {
00830     computedSize.height += m.top + m.bottom;
00831   }
00832 
00833   // handle reflow state min and max sizes
00834 
00835   if (computedSize.width > aReflowState.mComputedMaxWidth)
00836     computedSize.width = aReflowState.mComputedMaxWidth;
00837 
00838   if (computedSize.height > aReflowState.mComputedMaxHeight)
00839     computedSize.height = aReflowState.mComputedMaxHeight;
00840 
00841   if (computedSize.width < aReflowState.mComputedMinWidth)
00842     computedSize.width = aReflowState.mComputedMinWidth;
00843 
00844   if (computedSize.height < aReflowState.mComputedMinHeight)
00845     computedSize.height = aReflowState.mComputedMinHeight;
00846 
00847   nsRect r(mRect.x, mRect.y, computedSize.width, computedSize.height);
00848 
00849   SetBounds(state, r);
00850  
00851   // layout our children
00852   Layout(state);
00853   
00854   // ok our child could have gotten bigger. So lets get its bounds
00855   
00856   // get the ascent
00857   nscoord ascent = mRect.height;
00858 
00859   // getting the ascent could be a lot of work. Don't get it if
00860   // we are the root. The viewport doesn't care about it.
00861   if (!(mState & NS_STATE_IS_ROOT)) {
00862     // Only call GetAscent when not doing Initial reflow while in PP
00863     // or when it is Initial reflow while in PP and a chrome doc
00864     // If called again with initial reflow it crashes because the 
00865     // frames are fully constructed (I think).
00866     PRBool isChrome;
00867     PRBool isInitialPP = IsInitialReflowForPrintPreview(state, isChrome);
00868     if (!isInitialPP || (isInitialPP && isChrome)) {
00869       GetAscent(state, ascent);
00870     }
00871   }
00872 
00873   aDesiredSize.width  = mRect.width;
00874   aDesiredSize.height = mRect.height;
00875   aDesiredSize.ascent = ascent;
00876   aDesiredSize.descent = mRect.height - ascent;
00877 
00878   // NS_FRAME_OUTSIDE_CHILDREN is set in SetBounds() above
00879   if (mState & NS_FRAME_OUTSIDE_CHILDREN) {
00880     nsRect* overflowArea = GetOverflowAreaProperty();
00881     NS_ASSERTION(overflowArea, "Failed to set overflow area property");
00882     aDesiredSize.mOverflowArea = *overflowArea;
00883   }
00884 
00885   if(aDesiredSize.mFlags & NS_REFLOW_CALC_MAX_WIDTH) {
00886     aDesiredSize.mMaximumWidth = prefSize.width;
00887   }
00888 
00889   // max sure the max element size reflects
00890   // our min width
00891   nscoord* maxElementWidth = state.GetMaxElementWidth();
00892   if (maxElementWidth)
00893   {
00894      nsSize minSize(0,0);
00895      GetMinSize(state,  minSize);
00896        if (aReflowState.mStylePosition->mWidth.GetUnit() == eStyleUnit_Percent ||
00897            (mRect.width > minSize.width &&
00898            aReflowState.mComputedWidth == NS_INTRINSICSIZE))
00899          *maxElementWidth = minSize.width;
00900      else
00901        *maxElementWidth = mRect.width;
00902   }
00903 #ifdef DO_NOISY_REFLOW
00904   {
00905     printf("%p ** nsBF(done) W:%d H:%d  ", this, aDesiredSize.width, aDesiredSize.height);
00906 
00907     if (maxElementSize) {
00908       printf("MW:%d\n", *maxElementWidth); 
00909     } else {
00910       printf("MW:?\n"); 
00911     }
00912 
00913   }
00914 #endif
00915 
00916   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
00917   return NS_OK;
00918 }
00919 
00920 NS_IMETHODIMP
00921 nsBoxFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
00922 {
00923   if (!DoesNeedRecalc(mPrefSize)) {
00924      aSize = mPrefSize;
00925      return NS_OK;
00926   }
00927 
00928 #ifdef DEBUG_LAYOUT
00929   PropagateDebug(aBoxLayoutState);
00930 #endif
00931 
00932   nsresult rv = NS_OK;
00933   aSize.width = 0;
00934   aSize.height = 0;
00935 
00936   PRBool collapsed = PR_FALSE;
00937   IsCollapsed(aBoxLayoutState, collapsed);
00938   if (collapsed) {
00939     return NS_OK;
00940   }
00941 
00942   // if the size was not completely redefined in CSS then ask our children
00943   if (!nsIBox::AddCSSPrefSize(aBoxLayoutState, this, aSize))
00944   {
00945     aSize.width = 0;
00946     aSize.height = 0;
00947 
00948     if (mLayoutManager) {
00949       rv = mLayoutManager->GetPrefSize(this, aBoxLayoutState, aSize);
00950       nsIBox::AddCSSPrefSize(aBoxLayoutState, this, aSize);
00951     } else
00952       rv = nsBox::GetPrefSize(aBoxLayoutState, aSize);
00953   }
00954 
00955   nsSize minSize(0,0);
00956   nsSize maxSize(0,0);
00957   GetMinSize(aBoxLayoutState, minSize);
00958   GetMaxSize(aBoxLayoutState, maxSize);
00959 
00960   BoundsCheck(minSize, aSize, maxSize);
00961 
00962   mPrefSize = aSize;
00963  
00964   return rv;
00965 }
00966 
00967 NS_IMETHODIMP
00968 nsBoxFrame::GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent)
00969 {
00970   if (!DoesNeedRecalc(mAscent)) {
00971      aAscent = mAscent;
00972      return NS_OK;
00973   }
00974 
00975 #ifdef DEBUG_LAYOUT
00976   PropagateDebug(aBoxLayoutState);
00977 #endif
00978 
00979   nsresult rv = NS_OK;
00980   aAscent = 0;
00981 
00982   PRBool collapsed = PR_FALSE;
00983   IsCollapsed(aBoxLayoutState, collapsed);
00984   if (collapsed)
00985     return NS_OK;
00986 
00987   if (mLayoutManager)
00988     rv = mLayoutManager->GetAscent(this, aBoxLayoutState, aAscent);
00989   else
00990     rv = nsBox::GetAscent(aBoxLayoutState, aAscent);
00991 
00992   mAscent = aAscent;
00993  
00994   return rv;
00995 }
00996 
00997 NS_IMETHODIMP
00998 nsBoxFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
00999 {
01000   if (!DoesNeedRecalc(mMinSize)) {
01001      aSize = mMinSize;
01002      return NS_OK;
01003   }
01004 
01005 #ifdef DEBUG_LAYOUT
01006   PropagateDebug(aBoxLayoutState);
01007 #endif
01008 
01009   nsresult rv = NS_OK;
01010 
01011   aSize.SizeTo(0, 0);
01012 
01013   PRBool collapsed = PR_FALSE;
01014   IsCollapsed(aBoxLayoutState, collapsed);
01015   if (collapsed)
01016     return NS_OK;
01017 
01018   // if the size was not completely redefined in CSS then ask our children
01019   if (!nsIBox::AddCSSMinSize(aBoxLayoutState, this, aSize))
01020   {
01021     aSize.width = 0;
01022     aSize.height = 0;
01023 
01024     if (mLayoutManager) {
01025       rv = mLayoutManager->GetMinSize(this, aBoxLayoutState, aSize);
01026       nsIBox::AddCSSMinSize(aBoxLayoutState, this, aSize);
01027     } else {
01028       rv = nsBox::GetMinSize(aBoxLayoutState, aSize);
01029     }
01030   }
01031   
01032   mMinSize = aSize;
01033 
01034   return rv;
01035 }
01036 
01037 NS_IMETHODIMP
01038 nsBoxFrame::GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
01039 {
01040   if (!DoesNeedRecalc(mMaxSize)) {
01041      aSize = mMaxSize;
01042      return NS_OK;
01043   }
01044 
01045 #ifdef DEBUG_LAYOUT
01046   PropagateDebug(aBoxLayoutState);
01047 #endif
01048 
01049   nsresult rv = NS_OK;
01050 
01051   aSize.SizeTo(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
01052 
01053   PRBool collapsed = PR_FALSE;
01054   IsCollapsed(aBoxLayoutState, collapsed);
01055   if (collapsed)
01056     return NS_OK;
01057 
01058   // if the size was not completely redefined in CSS then ask our children
01059   if (!nsIBox::AddCSSMaxSize(aBoxLayoutState, this, aSize))
01060   {
01061     aSize.width = NS_INTRINSICSIZE;
01062     aSize.height = NS_INTRINSICSIZE;
01063 
01064     if (mLayoutManager) {
01065       rv = mLayoutManager->GetMaxSize(this, aBoxLayoutState, aSize);
01066       nsIBox::AddCSSMaxSize(aBoxLayoutState, this, aSize);
01067     } else {
01068       rv = nsBox::GetMaxSize(aBoxLayoutState, aSize);
01069     }
01070   }
01071 
01072   mMaxSize = aSize;
01073 
01074   return rv;
01075 }
01076 
01077 NS_IMETHODIMP
01078 nsBoxFrame::GetFlex(nsBoxLayoutState& aBoxLayoutState, nscoord& aFlex)
01079 {
01080   if (!DoesNeedRecalc(mFlex)) {
01081      aFlex = mFlex;
01082      return NS_OK;
01083   }
01084 
01085   nsresult rv = NS_OK;
01086 
01087   mFlex = 0;
01088   rv = nsBox::GetFlex(aBoxLayoutState, mFlex);
01089   aFlex = mFlex;
01090 
01091   return rv;
01092 }
01093 
01098 NS_IMETHODIMP
01099 nsBoxFrame::DoLayout(nsBoxLayoutState& aState)
01100 {
01101   PRUint32 oldFlags = aState.LayoutFlags();
01102   aState.SetLayoutFlags(0);
01103 
01104   nsresult rv = NS_OK;
01105   if (mLayoutManager)
01106     rv = mLayoutManager->Layout(this, aState);
01107 
01108   aState.SetLayoutFlags(oldFlags);
01109 
01110   return rv;
01111 }
01112 
01113 NS_IMETHODIMP
01114 nsBoxFrame::Destroy(nsPresContext* aPresContext)
01115 {
01116   // unregister access key
01117   RegUnregAccessKey(aPresContext, PR_FALSE);
01118 
01119   // clean up the container box's layout manager and child boxes
01120   SetLayoutManager(nsnull);
01121 
01122   return nsContainerFrame::Destroy(aPresContext);
01123 } 
01124 
01125 #ifdef DEBUG_LAYOUT
01126 NS_IMETHODIMP
01127 nsBoxFrame::SetDebug(nsBoxLayoutState& aState, PRBool aDebug)
01128 {
01129   // see if our state matches the given debug state
01130   PRBool debugSet = mState & NS_STATE_CURRENTLY_IN_DEBUG;
01131   PRBool debugChanged = (!aDebug && debugSet) || (aDebug && !debugSet);
01132 
01133   // if it doesn't then tell each child below us the new debug state
01134   if (debugChanged)
01135   {
01136      if (aDebug) {
01137          mState |= NS_STATE_CURRENTLY_IN_DEBUG;
01138      } else {
01139          mState &= ~NS_STATE_CURRENTLY_IN_DEBUG;
01140      }
01141  
01142      SetDebugOnChildList(aState, mFirstChild, aDebug);
01143 
01144      NeedsRecalc();
01145   }
01146 
01147   return NS_OK;
01148 }
01149 #endif
01150 
01151 NS_IMETHODIMP
01152 nsBoxFrame::NeedsRecalc()
01153 {
01154   SizeNeedsRecalc(mPrefSize);
01155   SizeNeedsRecalc(mMinSize);
01156   SizeNeedsRecalc(mMaxSize);
01157   CoordNeedsRecalc(mFlex);
01158   CoordNeedsRecalc(mAscent);
01159   return NS_OK;
01160 }
01161 
01162 NS_IMETHODIMP
01163 nsBoxFrame::RemoveFrame(nsIAtom*        aListName,
01164                         nsIFrame*       aOldFrame)
01165 {
01166   NS_PRECONDITION(!aListName, "We don't support out-of-flow kids");
01167   nsPresContext* presContext = GetPresContext();
01168   nsBoxLayoutState state(presContext);
01169 
01170   // remove the child frame
01171   mFrames.RemoveFrame(aOldFrame);
01172 
01173   // notify the layout manager
01174   if (mLayoutManager)
01175     mLayoutManager->ChildrenRemoved(this, state, aOldFrame);
01176 
01177   // destroy the child frame
01178   aOldFrame->Destroy(presContext);
01179 
01180   // mark us dirty and generate a reflow command
01181   MarkDirtyChildren(state);
01182   MarkDirty(state);
01183   return NS_OK;
01184 }
01185 
01186 NS_IMETHODIMP
01187 nsBoxFrame::InsertFrames(nsIAtom*        aListName,
01188                          nsIFrame*       aPrevFrame,
01189                          nsIFrame*       aFrameList)
01190 {
01191    NS_PRECONDITION(!aListName, "We don't support out-of-flow kids");
01192    nsBoxLayoutState state(GetPresContext());
01193 
01194    // insert the child frames
01195    mFrames.InsertFrames(this, aPrevFrame, aFrameList);
01196 
01197    // notify the layout manager
01198    if (mLayoutManager)
01199      mLayoutManager->ChildrenInserted(this, state, aPrevFrame, aFrameList);
01200 
01201 #ifdef DEBUG_LAYOUT
01202    // if we are in debug make sure our children are in debug as well.
01203    if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
01204        SetDebugOnChildList(state, mFrames.FirstChild(), PR_TRUE);
01205 #endif
01206 
01207    // mark us dirty and generate a reflow command
01208    MarkDirtyChildren(state);
01209    MarkDirty(state);
01210    return NS_OK;
01211 }
01212 
01213 
01214 NS_IMETHODIMP
01215 nsBoxFrame::AppendFrames(nsIAtom*        aListName,
01216                          nsIFrame*       aFrameList)
01217 {
01218    NS_PRECONDITION(!aListName, "We don't support out-of-flow kids");
01219    nsBoxLayoutState state(GetPresContext());
01220 
01221    // append the new frames
01222    mFrames.AppendFrames(this, aFrameList);
01223 
01224    // notify the layout manager
01225    if (mLayoutManager)
01226      mLayoutManager->ChildrenAppended(this, state, aFrameList);
01227 
01228 #ifdef DEBUG_LAYOUT
01229    // if we are in debug make sure our children are in debug as well.
01230    if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
01231        SetDebugOnChildList(state, mFrames.FirstChild(), PR_TRUE);
01232 #endif
01233 
01234    MarkDirtyChildren(state);
01235    MarkDirty(state);
01236    return NS_OK;
01237 }
01238 
01239 
01240 
01241 NS_IMETHODIMP
01242 nsBoxFrame::AttributeChanged(nsIContent* aChild,
01243                              PRInt32 aNameSpaceID,
01244                              nsIAtom* aAttribute,
01245                              PRInt32 aModType)
01246 {
01247   nsresult rv = nsContainerFrame::AttributeChanged(aChild, aNameSpaceID, 
01248                                                    aAttribute, aModType);
01249 
01250   // Ignore 'width', 'height', 'screenX', 'screenY' and 'sizemode' on a
01251   // <window>.
01252   nsIAtom *tag = mContent->Tag();
01253   if ((tag == nsXULAtoms::window ||
01254        tag == nsXULAtoms::page ||
01255        tag == nsXULAtoms::dialog ||
01256        tag == nsXULAtoms::wizard) &&
01257       (nsXULAtoms::width == aAttribute ||
01258        nsXULAtoms::height == aAttribute ||
01259        nsXULAtoms::screenX == aAttribute ||
01260        nsXULAtoms::screenY == aAttribute ||
01261        nsXULAtoms::sizemode == aAttribute)) {
01262     return rv;
01263   }
01264 
01265   if (aAttribute == nsHTMLAtoms::width       ||
01266       aAttribute == nsHTMLAtoms::height      ||
01267       aAttribute == nsHTMLAtoms::align       ||
01268       aAttribute == nsHTMLAtoms::valign      ||
01269       aAttribute == nsHTMLAtoms::left        ||
01270       aAttribute == nsHTMLAtoms::top         ||
01271       aAttribute == nsXULAtoms::minwidth     ||
01272       aAttribute == nsXULAtoms::maxwidth     ||
01273       aAttribute == nsXULAtoms::minheight    ||
01274       aAttribute == nsXULAtoms::maxheight    ||
01275       aAttribute == nsXULAtoms::flex         ||
01276       aAttribute == nsXULAtoms::orient       ||
01277       aAttribute == nsXULAtoms::pack         ||
01278       aAttribute == nsXULAtoms::dir          ||
01279       aAttribute == nsXULAtoms::mousethrough ||
01280       aAttribute == nsXULAtoms::equalsize) {
01281 
01282     if (aAttribute == nsHTMLAtoms::align  ||
01283         aAttribute == nsHTMLAtoms::valign ||
01284         aAttribute == nsXULAtoms::orient  ||
01285         aAttribute == nsXULAtoms::pack    ||
01286 #ifdef DEBUG_LAYOUT
01287         aAttribute == nsXULAtoms::debug   ||
01288 #endif
01289         aAttribute == nsXULAtoms::dir) {
01290 
01291       mValign = nsBoxFrame::vAlign_Top;
01292       mHalign = nsBoxFrame::hAlign_Left;
01293 
01294       PRBool orient = PR_TRUE;
01295       GetInitialOrientation(orient); 
01296       if (orient)
01297         mState |= NS_STATE_IS_HORIZONTAL;
01298       else
01299         mState &= ~NS_STATE_IS_HORIZONTAL;
01300 
01301       PRBool normal = PR_TRUE;
01302       GetInitialDirection(normal);
01303       if (normal)
01304         mState |= NS_STATE_IS_DIRECTION_NORMAL;
01305       else
01306         mState &= ~NS_STATE_IS_DIRECTION_NORMAL;
01307 
01308       GetInitialVAlignment(mValign);
01309       GetInitialHAlignment(mHalign);
01310 
01311       PRBool equalSize = PR_FALSE;
01312       GetInitialEqualSize(equalSize); 
01313       if (equalSize)
01314         mState |= NS_STATE_EQUAL_SIZE;
01315       else
01316         mState &= ~NS_STATE_EQUAL_SIZE;
01317 
01318 #ifdef DEBUG_LAYOUT
01319       PRBool debug = mState & NS_STATE_SET_TO_DEBUG;
01320       PRBool debugSet = GetInitialDebug(debug);
01321       if (debugSet) {
01322         mState |= NS_STATE_DEBUG_WAS_SET;
01323 
01324         if (debug)
01325           mState |= NS_STATE_SET_TO_DEBUG;
01326         else
01327           mState &= ~NS_STATE_SET_TO_DEBUG;
01328       } else {
01329         mState &= ~NS_STATE_DEBUG_WAS_SET;
01330       }
01331 #endif
01332 
01333       PRBool autostretch = mState & NS_STATE_AUTO_STRETCH;
01334       GetInitialAutoStretch(autostretch);
01335       if (autostretch)
01336         mState |= NS_STATE_AUTO_STRETCH;
01337       else
01338         mState &= ~NS_STATE_AUTO_STRETCH;
01339     }
01340     else if (aAttribute == nsHTMLAtoms::left ||
01341              aAttribute == nsHTMLAtoms::top) {
01342       mState &= ~NS_STATE_STACK_NOT_POSITIONED;
01343     }
01344     else if (aAttribute == nsXULAtoms::mousethrough) {
01345       UpdateMouseThrough();
01346     }
01347 
01348     nsBoxLayoutState state(GetPresContext());
01349     MarkDirty(state);
01350   }
01351   else if (aAttribute == nsXULAtoms::ordinal) {
01352     nsBoxLayoutState state(GetPresContext()->PresShell());
01353     nsIBox* parent;
01354     GetParentBox(&parent);
01355     // If our parent is not a box, there's not much we can do... but in that
01356     // case our ordinal doesn't matter anyway, so that's ok.
01357     // Also don't bother with popup frames since they are kept on the 
01358     // nsGkAtoms::popupList and RelayoutChildAtOrdinal() only handles
01359     // principal children.
01360     if (parent && !(GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
01361         GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_POPUP) {
01362       parent->RelayoutChildAtOrdinal(state, this);
01363       parent->MarkDirty(state);
01364     }
01365   }
01366   // If the accesskey changed, register for the new value
01367   // The old value has been unregistered in nsXULElement::SetAttr
01368   else if (aAttribute == nsXULAtoms::accesskey) {
01369     RegUnregAccessKey(GetPresContext(), PR_TRUE);
01370   }
01371 
01372   return rv;
01373 }
01374 
01375 
01376 #ifdef DEBUG_COELESCED
01377 static PRInt32 StyleCoelesced = 0;
01378 #endif
01379 
01380 PRBool
01381 nsBoxFrame::HasStyleChange()
01382 {
01383   return mState & NS_STATE_STYLE_CHANGE;
01384 }
01385 
01386 void
01387 nsBoxFrame::SetStyleChangeFlag(PRBool aDirty)
01388 {
01389   nsBox::SetStyleChangeFlag(aDirty);
01390 
01391   if (aDirty)
01392      mState |= (NS_STATE_STYLE_CHANGE);
01393   else 
01394      mState &= ~NS_STATE_STYLE_CHANGE;
01395 }
01396 
01397 #ifdef DEBUG_LAYOUT
01398 void
01399 nsBoxFrame::GetDebugPref(nsPresContext* aPresContext)
01400 {
01401     gDebug = nsContentUtils::GetBoolPref("xul.debug.box");
01402 }
01403 #endif
01404 
01405 NS_IMETHODIMP
01406 nsBoxFrame::Paint(nsPresContext*      aPresContext,
01407                   nsIRenderingContext& aRenderingContext,
01408                   const nsRect&        aDirtyRect,
01409                   nsFramePaintLayer    aWhichLayer,
01410                   PRUint32             aFlags)
01411 {
01412   // if collapsed nothing is drawn
01413   if (GetStyleVisibility()->mVisible == NS_STYLE_VISIBILITY_COLLAPSE) 
01414     return NS_OK;
01415 
01416   if (NS_FRAME_IS_UNFLOWABLE & mState) {
01417     return NS_OK;
01418   }
01419 
01420   if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
01421     PaintSelf(aPresContext, aRenderingContext, aDirtyRect, 0, PR_FALSE);
01422   }
01423 
01424   if (GetType() == nsLayoutAtoms::rootFrame) {
01425     // We are wrapping the root frame of a XUL document. We
01426     // need to check the pres shell to find out if painting is locked
01427     // down (because we're still in the early stages of document
01428     // and frame construction.  If painting is locked down, then we
01429     // do not paint our children.  
01430     PRBool paintingSuppressed = PR_FALSE;
01431     aPresContext->PresShell()->IsPaintingSuppressed(&paintingSuppressed);
01432     if (paintingSuppressed)
01433       return NS_OK;
01434   }
01435 
01436   // Now paint the kids. Note that child elements have the opportunity to
01437   // override the visibility property and display even if their parent is
01438   // hidden.  Don't paint our children if the theme object is a leaf.
01439   const nsStyleDisplay* display = GetStyleDisplay();
01440   if (!(display->mAppearance && nsBox::gTheme && 
01441         gTheme->ThemeSupportsWidget(aPresContext, this, display->mAppearance) &&
01442         !gTheme->WidgetIsContainer(display->mAppearance)))
01443     PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
01444 
01445   // see if we have to draw a selection frame around this container
01446   return nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
01447 }
01448 
01453 void
01454 nsBoxFrame::PaintChild(nsPresContext*      aPresContext,
01455                        nsIRenderingContext& aRenderingContext,
01456                        const nsRect&        aDirtyRect,
01457                        nsIFrame*            aFrame,
01458                        nsFramePaintLayer    aWhichLayer,
01459                        PRUint32             aFlags)
01460 {
01461   // if collapsed don't paint the child.
01462   if (aFrame->GetStyleVisibility()->mVisible == NS_STYLE_VISIBILITY_COLLAPSE)
01463      return;
01464 
01465   if (!aFrame->HasView()) {
01466     nsRect kidRect = aFrame->GetRect();
01467  
01468     nsRect damageArea;
01469     PRBool overlap;
01470     // Compute the intersection of the dirty rect and the childs
01471     // rect (both are in our coordinate space). This limits the
01472     // damageArea to just the portion that intersects the childs
01473     // rect.
01474     overlap = damageArea.IntersectRect(aDirtyRect, kidRect); 
01475 
01476     if (overlap) {
01477       // Translate damage area into the kids coordinate
01478       // system. Translate rendering context into the kids
01479       // coordinate system.
01480       damageArea.x -= kidRect.x;
01481       damageArea.y -= kidRect.y;
01482 
01483       {
01484         nsIRenderingContext::AutoPushTranslation
01485           translate(&aRenderingContext, kidRect.x, kidRect.y);
01486 
01487         // Paint the kid
01488         aFrame->Paint(aPresContext, aRenderingContext, damageArea, aWhichLayer);
01489       }
01490     }
01491   }
01492 }
01493 
01494 void
01495 nsBoxFrame::PaintChildren(nsPresContext*      aPresContext,
01496                           nsIRenderingContext& aRenderingContext,
01497                           const nsRect&        aDirtyRect,
01498                           nsFramePaintLayer    aWhichLayer,
01499                           PRUint32             aFlags)
01500 {
01501   nsMargin border;
01502   nsRect inner;
01503 
01504   GetBorder(border);
01505 
01506 #ifdef DEBUG_LAYOUT
01507   nsMargin debugBorder;
01508   nsMargin debugMargin;
01509   nsMargin debugPadding;
01510 
01511   if (mState & NS_STATE_CURRENTLY_IN_DEBUG) 
01512   {
01513         PRBool isHorizontal = IsHorizontal();
01514 
01515         GetDebugBorder(debugBorder);
01516         PixelMarginToTwips(aPresContext, debugBorder);
01517 
01518         GetDebugMargin(debugMargin);
01519         PixelMarginToTwips(aPresContext, debugMargin);
01520 
01521         GetDebugPadding(debugPadding);
01522         PixelMarginToTwips(aPresContext, debugPadding);
01523 
01524         GetContentRect(inner);
01525         inner.Deflate(debugMargin);
01526         inner.Deflate(border);
01527         //nsRect borderRect(inner);
01528 
01529         nscolor color;
01530         if (isHorizontal) {
01531           color = NS_RGB(0,0,255);
01532         } else {
01533           color = NS_RGB(255,0,0);
01534         }
01535 
01536         aRenderingContext.SetColor(color);
01537 
01538         //left
01539         nsRect r(inner);
01540         r.width = debugBorder.left;
01541         aRenderingContext.FillRect(r);
01542 
01543         // top
01544         r = inner;
01545         r.height = debugBorder.top;
01546         aRenderingContext.FillRect(r);
01547 
01548         //right
01549         r = inner;
01550         r.x = r.x + r.width - debugBorder.right;
01551         r.width = debugBorder.right;
01552         aRenderingContext.FillRect(r);
01553 
01554         //bottom
01555         r = inner;
01556         r.y = r.y + r.height - debugBorder.bottom;
01557         r.height = debugBorder.bottom;
01558         aRenderingContext.FillRect(r);
01559 
01560         
01561         // if we have dirty children or we are dirty 
01562         // place a green border around us.
01563         PRBool dirty = PR_FALSE;
01564         IsDirty(dirty);
01565         PRBool dirtyc = PR_FALSE;
01566         HasDirtyChildren(dirtyc);
01567 
01568         if (dirty || dirtyc) {
01569            IsDirty(dirty);
01570            HasDirtyChildren(dirty);
01571 
01572            nsRect dirtyr(inner);
01573            aRenderingContext.SetColor(NS_RGB(0,255,0));
01574            aRenderingContext.DrawRect(dirtyr);
01575            aRenderingContext.SetColor(color);
01576         }
01577   }
01578 #endif
01579 
01580   const nsStyleDisplay* disp = GetStyleDisplay();
01581 
01582   // Child elements have the opportunity to override the visibility property
01583   // of their parent and display even if the parent is hidden
01584 
01585   nsRect r(0,0,mRect.width, mRect.height);
01586   PRBool hasClipped = PR_FALSE;
01587   
01588   // If overflow is hidden then set the clip rect so that children
01589   // don't leak out of us
01590   if (NS_STYLE_OVERFLOW_CLIP == disp->mOverflowX) {
01591     nsMargin im(0,0,0,0);
01592     GetInset(im);
01593     r.Deflate(im);
01594     r.Deflate(border);    
01595   }
01596 
01597   nsIBox* kid = nsnull;
01598   GetChildBox(&kid);
01599   while (nsnull != kid) {
01600     if (!hasClipped && NS_STYLE_OVERFLOW_CLIP == disp->mOverflowX) {
01601         // if we haven't already clipped and we should
01602         // check to see if the child is in out bounds. If not then
01603         // we begin clipping.
01604     
01605         // if our rect does not contain the childs then begin clipping
01606         if (!r.Contains(kid->GetRect())) {
01607             aRenderingContext.PushState();
01608             aRenderingContext.SetClipRect(r, nsClipCombine_kIntersect);
01609             hasClipped = PR_TRUE;
01610         }
01611     }
01612 
01613     PaintChild(aPresContext, aRenderingContext, aDirtyRect, kid, aWhichLayer);
01614 
01615     kid->GetNextBox(&kid);
01616   }
01617 
01618   if (hasClipped)
01619     aRenderingContext.PopState();
01620 
01621 #ifdef DEBUG_LAYOUT
01622   if (mState & NS_STATE_CURRENTLY_IN_DEBUG) 
01623   {
01624     nscoord onePixel = aPresContext->IntScaledPixelsToTwips(1);
01625     GetContentRect(r);
01626 
01627     if (NS_STYLE_OVERFLOW_CLIP == disp->mOverflowX) {
01628       GetDebugMargin(debugMargin);
01629       PixelMarginToTwips(aPresContext, debugMargin);
01630       r.Deflate(debugMargin);
01631     }
01632 
01633     hasClipped = PR_FALSE;
01634 
01635     GetChildBox(&kid);
01636     while (nsnull != kid) {
01637          if (!hasClipped && NS_STYLE_OVERFLOW_CLIP == disp->mOverflowX) {
01638             // if we haven't already clipped and we should
01639             // check to see if the child is in out bounds. If not then
01640             // we begin clipping.
01641     
01642             // if our rect does not contain the childs then begin clipping
01643             if (!r.Contains(kid->mRect)) {
01644                 aRenderingContext.PushState();
01645                 aRenderingContext.SetClipRect(r, nsClipCombine_kIntersect);
01646                 hasClipped = PR_TRUE;
01647             }
01648         }
01649         PRBool isHorizontal = IsHorizontal();
01650 
01651         nscoord x, y, borderSize, spacerSize;
01652         
01653         nsRect cr(kid->mRect);
01654         nsMargin margin;
01655         kid->GetMargin(margin);
01656         cr.Inflate(margin);
01657         
01658         if (isHorizontal) 
01659         {
01660             cr.y = inner.y;
01661             x = cr.x;
01662             y = cr.y + onePixel;
01663             spacerSize = debugBorder.top - onePixel*4;
01664         } else {
01665             cr.x = inner.x;
01666             x = cr.y;
01667             y = cr.x + onePixel;
01668             spacerSize = debugBorder.left - onePixel*4;
01669         }
01670 
01671         nsBoxLayoutState state(aPresContext);
01672         nscoord flex = 0;
01673         kid->GetFlex(state, flex);
01674 
01675         
01676         PRBool isCollapsed = PR_FALSE;
01677         kid->IsCollapsed(state, isCollapsed);
01678 
01679         if (!isCollapsed) {
01680           aRenderingContext.SetColor(NS_RGB(255,255,255));
01681 
01682           if (isHorizontal) 
01683               borderSize = cr.width;
01684           else 
01685               borderSize = cr.height;
01686         
01687           DrawSpacer(aPresContext, aRenderingContext, isHorizontal, flex, x, y, borderSize, spacerSize);
01688         }
01689 
01690         kid->GetNextBox(&kid);
01691     }
01692 
01693     if (hasClipped)
01694        aRenderingContext.PopState();
01695   }
01696 #endif
01697 }
01698 
01699 NS_IMETHODIMP_(nsrefcnt) 
01700 nsBoxFrame::AddRef(void)
01701 {
01702   return NS_OK;
01703 }
01704 
01705 NS_IMETHODIMP_(nsrefcnt)
01706 nsBoxFrame::Release(void)
01707 {
01708     return NS_OK;
01709 }
01710 
01711 NS_INTERFACE_MAP_BEGIN(nsBoxFrame)
01712   NS_INTERFACE_MAP_ENTRY(nsIBox)
01713 #ifdef NS_DEBUG
01714   NS_INTERFACE_MAP_ENTRY(nsIFrameDebug)
01715 #endif
01716   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBox)
01717 NS_INTERFACE_MAP_END_INHERITING(nsContainerFrame)
01718 
01719 #ifdef DEBUG_LAYOUT
01720 void
01721 nsBoxFrame::GetBoxName(nsAutoString& aName)
01722 {
01723    GetFrameName(aName);
01724 }
01725 #endif
01726 
01727 #ifdef DEBUG
01728 NS_IMETHODIMP
01729 nsBoxFrame::GetFrameName(nsAString& aResult) const
01730 {
01731   return MakeFrameName(NS_LITERAL_STRING("Box"), aResult);
01732 }
01733 #endif
01734 
01735 nsIAtom*
01736 nsBoxFrame::GetType() const
01737 {
01738   return nsLayoutAtoms::boxFrame;
01739 }
01740 
01741 #ifdef DEBUG_LAYOUT
01742 NS_IMETHODIMP
01743 nsBoxFrame::GetDebug(PRBool& aDebug)
01744 {
01745   aDebug = (mState & NS_STATE_CURRENTLY_IN_DEBUG);
01746   return NS_OK;
01747 }
01748 #endif
01749 
01750 NS_IMETHODIMP  
01751 nsBoxFrame::GetFrameForPoint(const nsPoint&    aPoint, 
01752                              nsFramePaintLayer aWhichLayer,    
01753                              nsIFrame**        aFrame)
01754 {   
01755   if (!mRect.Contains(aPoint))
01756     return NS_ERROR_FAILURE;
01757 
01758   const nsStyleVisibility* vis = GetStyleVisibility();
01759   if (vis->mVisible == NS_STYLE_VISIBILITY_COLLAPSE)
01760     return NS_ERROR_FAILURE;
01761 
01762   nsIView* view = nsnull;
01763   nsPoint originOffset;
01764   GetOriginToViewOffset(originOffset, &view);
01765 
01766 #ifdef DEBUG_LAYOUT
01767   // get the debug frame.
01768   if (view || (mState & NS_STATE_IS_ROOT))
01769   {
01770     nsIBox* box = nsnull;
01771     if (NS_SUCCEEDED(GetDebugBoxAt(aPoint, &box)) && box)
01772     {
01773       PRBool isDebug = PR_FALSE;
01774       box->GetDebug(isDebug);
01775       if (isDebug) {
01776         *aFrame = box;
01777         return NS_OK;
01778       }
01779     }
01780   }
01781 #endif
01782 
01783   nsIFrame *hit = nsnull;
01784   nsPoint tmp;
01785 
01786   *aFrame = nsnull;
01787   tmp.MoveTo(aPoint.x - mRect.x, aPoint.y - mRect.y);
01788 
01789   if (view)
01790     tmp += originOffset;
01791 
01792   nsIBox* kid = nsnull;
01793   GetChildBox(&kid);
01794   while (nsnull != kid) {
01795     GetFrameForPointChild(tmp, aWhichLayer, kid, hit != nsnull, &hit);
01796     kid->GetNextBox(&kid);
01797   }
01798   if (hit)
01799     *aFrame = hit;
01800 
01801   if (*aFrame) {
01802     return NS_OK;
01803   }
01804 
01805   // if no kids were hit then select us
01806   if (aWhichLayer == NS_FRAME_PAINT_LAYER_BACKGROUND && vis->IsVisible()) {
01807       *aFrame = this;
01808       return NS_OK;
01809   }
01810 
01811   return NS_ERROR_FAILURE;
01812 }
01813 
01814 /* virtual */ nsresult
01815 nsBoxFrame::GetFrameForPointChild(const nsPoint&    aPoint,
01816                                   nsFramePaintLayer aWhichLayer,    
01817                                   nsIFrame*         aChild,
01818                                   PRBool            aCheckMouseThrough,
01819                                   nsIFrame**        aFrame)
01820 {
01821   nsIFrame *hit = nsnull;
01822   nsresult rv =
01823     aChild->GetFrameForPoint(aPoint, aWhichLayer, &hit);
01824 
01825   if (NS_SUCCEEDED(rv) && hit) {
01826     rv = NS_ERROR_FAILURE;
01827     if (!aCheckMouseThrough) {
01828       *aFrame = hit;
01829       rv = NS_OK;
01830     }
01831     else
01832     {
01833       // If we had a lower frame for this point, check whether hit's box has
01834       // mouse through.  If so, stick with the lower frame that we found.
01835       PRBool isAdaptor = PR_FALSE;
01836       nsIBox *box = GetBoxForFrame(hit, isAdaptor);
01837       if (box) {
01838         PRBool mouseThrough = PR_FALSE;
01839         box->GetMouseThrough(mouseThrough);
01840         // if the child says it can never mouse though ignore it. 
01841         if (!mouseThrough) {
01842           *aFrame = hit;
01843           rv = NS_OK;
01844         }
01845       }
01846     }
01847   }
01848   return rv;
01849 }
01850 
01851 nsIBox*
01852 nsBoxFrame::GetBoxForFrame(nsIFrame* aFrame, PRBool& aIsAdaptor)
01853 {
01854   if (aFrame && !aFrame->IsBoxFrame())
01855     aIsAdaptor = PR_TRUE;
01856 
01857   return aFrame;
01858 }
01859 
01860 /*
01861 NS_IMETHODIMP
01862 nsBoxFrame::GetMouseThrough(PRBool& aMouseThrough)
01863 {
01864    const nsStyleBackground* color = GetStyleBackground();
01865    PRBool transparentBG = NS_STYLE_BG_COLOR_TRANSPARENT ==
01866                          (color->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT);
01867 
01868    if (!transparentBG)
01869       aMouseThrough = never;
01870    else
01871       return nsBox::GetMouseThrough(aMouseThrough);
01872 
01873    return NS_OK;
01874 }
01875 */
01876 
01877 
01878 
01879 
01880 NS_IMETHODIMP
01881 nsBoxFrame::GetCursor(const nsPoint&    aPoint,
01882                       nsIFrame::Cursor& aCursor)
01883 {
01884   /*
01885     #ifdef NS_DEBUG
01886     printf("Get Cursor: ");
01887                             nsFrame::ListTag(stdout, this);
01888     printf("\n");
01889                             
01890     #endif
01891  */
01892 
01893 #ifdef DEBUG_LAYOUT
01894     nsPoint newPoint;
01895     TranslateEventCoords(aPoint, newPoint);
01896     
01897     // if we are in debug and we are in the debug area
01898     // return our own cursor and dump the debug information.
01899     if (mState & NS_STATE_CURRENTLY_IN_DEBUG) 
01900     {
01901           // XXX aCursor is not yet inited??
01902           nsresult rv = DisplayDebugInfoFor(this, GetPresContext(), newPoint,
01903               aCursor.mCursor);
01904           if (rv == NS_OK)
01905              return rv;
01906     }
01907 #endif
01908 
01909     nsresult rv = nsContainerFrame::GetCursor(aPoint, aCursor);
01910 
01911     return rv;
01912 }
01913 
01914 
01915 //XXX the event come's in in view relative coords, but really should
01916 //be in frame relative coords by the time it hits our frame.
01917 
01918 // Translate an point that is relative to our view (or a containing
01919 // view) into a localized pixel coordinate that is relative to the
01920 // content area of this frame (inside the border+padding).
01921 void
01922 nsBoxFrame::TranslateEventCoords(const nsPoint& aPoint,
01923                                  nsPoint& aResult)
01924 {
01925   nscoord x = aPoint.x;
01926   nscoord y = aPoint.y;
01927 
01928   // If we have a view then the event coordinates are already relative
01929   // to this frame; otherwise we have to adjust the coordinates
01930   // appropriately.
01931   if (!HasView()) {
01932     nsPoint offset;
01933     nsIView* view;
01934     GetOffsetFromView(offset, &view);
01935     if (nsnull != view) {
01936       x -= offset.x;
01937       y -= offset.y;
01938     }
01939   }
01940 
01941   aResult.x = x;
01942   aResult.y = y;
01943  
01944 }
01945 
01946 
01947 nsresult 
01948 nsBoxFrame::GetContentOf(nsIContent** aContent)
01949 {
01950     // If we don't have a content node find a parent that does.
01951     nsIFrame *frame = this;
01952     while (frame) {
01953       *aContent = frame->GetContent();
01954       if (*aContent) {
01955         NS_ADDREF(*aContent);
01956         return NS_OK;
01957       }
01958 
01959       frame = frame->GetParent();
01960     }
01961 
01962     *aContent = nsnull;
01963     return NS_OK;
01964 }
01965 
01966 /*
01967 nsresult
01968 nsBoxFrame::PaintDebug(nsIBox*              aBox, 
01969                        nsPresContext*      aPresContext,
01970                        nsIRenderingContext& aRenderingContext,
01971                        const nsRect&        aDirtyRect,
01972                        nsFramePaintLayer    aWhichLayer)
01973 
01974 {
01975     
01976         PRBool isHorizontal = IsHorizontal();
01977 
01978         nscoord onePixel = aPresContext->IntScaledPixelsToTwips(1);
01979 
01980         nsMargin debugBorder(0,0,0,0);
01981         nsMargin debugMargin(0,0,0,0);
01982         nsMargin debugPadding(0,0,0,0);
01983 
01984         GetDebugBorder(debugBorder);
01985         PixelMarginToTwips(aPresContext, debugBorder);
01986 
01987         GetDebugMargin(debugMargin);
01988         PixelMarginToTwips(aPresContext, debugMargin);
01989 
01990         GetDebugPadding(debugPadding);
01991         PixelMarginToTwips(aPresContext, debugPadding);
01992 
01993         nsRect inner(0,0,0,0);
01994         aBox->GetContentRect(inner);
01995 
01996         inner.Deflate(debugMargin);
01997 
01998         //nsRect borderRect(inner);
01999 
02000         nscolor color;
02001         if (isHorizontal) {
02002           color = NS_RGB(0,0,255);
02003         } else {
02004           color = NS_RGB(255,0,0);
02005         }
02006         
02007         //left
02008         aRenderingContext.SetColor(color);
02009         nsRect r(inner);
02010         r.width = debugBorder.left;
02011         aRenderingContext.FillRect(r);
02012 
02013         // top
02014         r = inner;
02015         r.height = debugBorder.top;
02016         aRenderingContext.FillRect(r);
02017 
02018         //right
02019         r = inner;
02020         r.x = r.x + r.width - debugBorder.right;
02021         r.width = debugBorder.right;
02022         aRenderingContext.FillRect(r);
02023 
02024         //bottom
02025         r = inner;
02026         r.y = r.y + r.height - debugBorder.bottom;
02027         r.height = debugBorder.bottom;
02028         aRenderingContext.FillRect(r);
02029 
02030         // if we have dirty children or we are dirty 
02031         // place a green border around us.
02032         PRBool dirty = PR_FALSE;
02033         IsDirty(dirty);
02034         PRBool dirtyc = PR_FALSE;
02035         HasDirtyChildren(dirty);
02036 
02037         if (dirty || dirtyc) {
02038            nsRect dirtyr(inner);
02039            aRenderingContext.SetColor(NS_RGB(0,255,0));
02040            aRenderingContext.DrawRect(dirtyr);
02041         }
02042 
02043         // paint the spacers.
02044         nscoord x, y, borderSize, spacerSize;
02045         
02046         aRenderingContext.SetColor(NS_RGB(255,255,255));
02047         
02048         if (isHorizontal) 
02049         {
02050             x = inner.x;
02051             y = inner.y + onePixel;
02052             x += debugBorder.left;
02053             spacerSize = debugBorder.top - onePixel*4;
02054         } else {
02055             x = inner.y;
02056             y = inner.x + onePixel;
02057             x += debugBorder.top;
02058             spacerSize = debugBorder.left - onePixel*4;
02059         }
02060 
02061         nsIBox* box = nsnull;
02062         aBox->GetChildBox(&box);
02063         nsBoxLayoutState state(aPresContext);
02064 
02065         while (box) {
02066           nsSize size;
02067           GetFrameSizeWithMargin(box, size);
02068           PRBool isCollapsed = PR_FALSE;
02069           box->IsCollapsed(state, isCollapsed);
02070 
02071           if (!isCollapsed) {
02072                 if (isHorizontal) 
02073                     borderSize = size.width;
02074                 else 
02075                     borderSize = size.height;
02076 
02077              
02078 
02079                 nscoord flex = 0;
02080                 box->GetFlex(state, flex);
02081 
02082                 DrawSpacer(aPresContext, aRenderingContext, isHorizontal, flex, x, y, borderSize, spacerSize);
02083                 x += borderSize;
02084             }
02085             box->GetNextBox(&box);
02086         }
02087 
02088         return NS_OK;
02089 }
02090 */
02091 
02092 void
02093 nsBoxFrame::DrawLine(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x1, nscoord y1, nscoord x2, nscoord y2)
02094 {
02095     if (aHorizontal)
02096        aRenderingContext.DrawLine(x1,y1,x2,y2);
02097     else
02098        aRenderingContext.DrawLine(y1,x1,y2,x2);
02099 }
02100 
02101 void
02102 nsBoxFrame::FillRect(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x, nscoord y, nscoord width, nscoord height)
02103 {
02104     if (aHorizontal)
02105        aRenderingContext.FillRect(x,y,width,height);
02106     else
02107        aRenderingContext.FillRect(y,x,height,width);
02108 }
02109 
02110 void 
02111 nsBoxFrame::DrawSpacer(nsPresContext* aPresContext, nsIRenderingContext& aRenderingContext, PRBool aHorizontal, PRInt32 flex, nscoord x, nscoord y, nscoord size, nscoord spacerSize)
02112 {    
02113          nscoord onePixel = aPresContext->IntScaledPixelsToTwips(1);
02114 
02115      // if we do draw the coils
02116         int distance = 0;
02117         int center = 0;
02118         int offset = 0;
02119         int coilSize = COIL_SIZE*onePixel;
02120         int halfSpacer = spacerSize/2;
02121 
02122         distance = size;
02123         center = y + halfSpacer;
02124         offset = x;
02125 
02126         int coils = distance/coilSize;
02127 
02128         int halfCoilSize = coilSize/2;
02129 
02130         if (flex == 0) {
02131             DrawLine(aRenderingContext, aHorizontal, x,y + spacerSize/2, x + size, y + spacerSize/2);
02132         } else {
02133             for (int i=0; i < coils; i++)
02134             {
02135                    DrawLine(aRenderingContext, aHorizontal, offset, center+halfSpacer, offset+halfCoilSize, center-halfSpacer);
02136                    DrawLine(aRenderingContext, aHorizontal, offset+halfCoilSize, center-halfSpacer, offset+coilSize, center+halfSpacer);
02137 
02138                    offset += coilSize;
02139             }
02140         }
02141 
02142         FillRect(aRenderingContext, aHorizontal, x + size - spacerSize/2, y, spacerSize/2, spacerSize);
02143         FillRect(aRenderingContext, aHorizontal, x, y, spacerSize/2, spacerSize);
02144 
02145         //DrawKnob(aPresContext, aRenderingContext, x + size - spacerSize, y, spacerSize);
02146 }
02147 
02148 #ifdef DEBUG_LAYOUT
02149 void
02150 nsBoxFrame::GetDebugBorder(nsMargin& aInset)
02151 {
02152     aInset.SizeTo(2,2,2,2);
02153 
02154     if (IsHorizontal()) 
02155        aInset.top = 10;
02156     else 
02157        aInset.left = 10;
02158 }
02159 
02160 void
02161 nsBoxFrame::GetDebugMargin(nsMargin& aInset)
02162 {
02163     aInset.SizeTo(2,2,2,2);
02164 }
02165 
02166 void
02167 nsBoxFrame::GetDebugPadding(nsMargin& aPadding)
02168 {
02169     aPadding.SizeTo(2,2,2,2);
02170 }
02171 
02172 NS_IMETHODIMP 
02173 nsBoxFrame::GetInset(nsMargin& margin)
02174 {
02175   margin.SizeTo(0,0,0,0);
02176 
02177   if (mState & NS_STATE_CURRENTLY_IN_DEBUG) {
02178      nsMargin debugMargin(0,0,0,0);
02179      nsMargin debugBorder(0,0,0,0);
02180      nsMargin debugPadding(0,0,0,0);
02181      GetDebugBorder(debugBorder);
02182      PixelMarginToTwips(mPresContext, debugBorder);
02183      GetDebugMargin(debugMargin);
02184      PixelMarginToTwips(mPresContext, debugMargin);
02185      GetDebugMargin(debugPadding);
02186      PixelMarginToTwips(mPresContext, debugPadding);
02187      margin += debugBorder;
02188      margin += debugMargin;
02189      margin += debugPadding;
02190   }
02191 
02192   return NS_OK;
02193 }
02194 #endif
02195 
02196 void 
02197 nsBoxFrame::PixelMarginToTwips(nsPresContext* aPresContext, nsMargin& aMarginPixels)
02198 {
02199   nscoord onePixel = aPresContext->IntScaledPixelsToTwips(1);
02200   aMarginPixels.left   *= onePixel;
02201   aMarginPixels.right  *= onePixel;
02202   aMarginPixels.top    *= onePixel;
02203   aMarginPixels.bottom *= onePixel;
02204 }
02205 
02206 
02207 #ifdef DEBUG_LAYOUT
02208 void
02209 nsBoxFrame::GetValue(nsPresContext* aPresContext, const nsSize& a, const nsSize& b, char* ch) 
02210 {
02211     float p2t = aPresContext->ScaledPixelsToTwips();
02212 
02213     char width[100];
02214     char height[100];
02215     
02216     if (a.width == NS_INTRINSICSIZE)
02217         sprintf(width,"%s","INF");
02218     else 
02219         sprintf(width,"%d", nscoord(a.width/*/p2t*/));
02220     
02221     if (a.height == NS_INTRINSICSIZE)
02222         sprintf(height,"%s","INF");
02223     else 
02224         sprintf(height,"%d", nscoord(a.height/*/p2t*/));
02225     
02226 
02227     sprintf(ch, "(%s%s, %s%s)", width, (b.width != NS_INTRINSICSIZE ? "[SET]" : ""),
02228                     height, (b.height != NS_INTRINSICSIZE ? "[SET]" : ""));
02229 
02230 }
02231 
02232 void
02233 nsBoxFrame::GetValue(nsPresContext* aPresContext, PRInt32 a, PRInt32 b, char* ch) 
02234 {
02235     if (a == NS_INTRINSICSIZE)
02236       sprintf(ch, "%d[SET]", b);             
02237     else
02238       sprintf(ch, "%d", a);             
02239 }
02240 
02241 nsresult
02242 nsBoxFrame::DisplayDebugInfoFor(nsIBox*         aBox,
02243                                 nsPresContext* aPresContext,
02244                                 nsPoint&        aPoint,
02245                                 PRInt32&        aCursor)
02246 {
02247     nsBoxLayoutState state(aPresContext);
02248 
02249     nscoord x = aPoint.x;
02250     nscoord y = aPoint.y;
02251 
02252     // get the area inside our border but not our debug margins.
02253     nsRect insideBorder;
02254     aBox->GetContentRect(insideBorder);
02255     nsMargin border(0,0,0,0);
02256     aBox->GetBorderAndPadding(border);
02257     insideBorder.Deflate(border);
02258 
02259     PRBool isHorizontal = IsHorizontal();
02260 
02261     if (!insideBorder.Contains(nsPoint(x,y)))
02262         return NS_ERROR_FAILURE;
02263 
02264         //printf("%%%%%% inside box %%%%%%%\n");
02265 
02266         int count = 0;
02267         nsIBox* child = nsnull;
02268         aBox->GetChildBox(&child);
02269 
02270         nsMargin m;
02271         nsMargin m2;
02272         GetDebugBorder(m);
02273         PixelMarginToTwips(aPresContext, m);
02274 
02275         GetDebugMargin(m2);
02276         PixelMarginToTwips(aPresContext, m2);
02277 
02278         m += m2;
02279 
02280         if ((isHorizontal && y < insideBorder.y + m.top) ||
02281             (!isHorizontal && x < insideBorder.x + m.left)) {
02282             //printf("**** inside debug border *******\n");
02283             while (child) 
02284             {
02285                 const nsRect& r = child->mRect;
02286 
02287                 // if we are not in the child. But in the spacer above the child.
02288                 if ((isHorizontal && x >= r.x && x < r.x + r.width) ||
02289                     (!isHorizontal && y >= r.y && y < r.y + r.height)) {
02290                     aCursor = NS_STYLE_CURSOR_POINTER;
02291                        // found it but we already showed it.
02292                         if (mDebugChild == child)
02293                             return NS_OK;
02294 
02295                         if (aBox->GetContent()) {
02296                           printf("---------------\n");
02297                           DumpBox(stdout);
02298                           printf("\n");
02299                         }
02300 
02301                         if (child->GetContent()) {
02302                             printf("child #%d: ", count);
02303                             child->DumpBox(stdout);
02304                             printf("\n");
02305                         }
02306 
02307                         mDebugChild = child;
02308 
02309                         nsSize prefSizeCSS(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
02310                         nsSize minSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
02311                         nsSize maxSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
02312                         nscoord flexCSS = NS_INTRINSICSIZE;
02313 
02314                         nsSize prefSize(0, 0);
02315                         nsSize minSize (0, 0);
02316                         nsSize maxSize (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
02317                         nscoord flexSize = 0;
02318                         nscoord ascentSize = 0;
02319 
02320 
02321                         nsIBox::AddCSSPrefSize(state, child, prefSizeCSS);
02322                         nsIBox::AddCSSMinSize (state, child, minSizeCSS);
02323                         nsIBox::AddCSSMaxSize (state, child, maxSizeCSS);
02324                         nsIBox::AddCSSFlex    (state, child, flexCSS);
02325 
02326                         child->GetPrefSize(state, prefSize);
02327                         child->GetMinSize(state, minSize);
02328                         child->GetMaxSize(state, maxSize);
02329                         child->GetFlex(state, flexSize);
02330                         child->GetAscent(state, ascentSize);
02331 
02332                         char min[100];
02333                         char pref[100];
02334                         char max[100];
02335                         char calc[100];
02336                         char flex[100];
02337                         char ascent[100];
02338                       
02339                         nsSize actualSize;
02340                         GetFrameSizeWithMargin(child, actualSize);
02341                         nsSize actualSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
02342 
02343                         GetValue(aPresContext, minSize,  minSizeCSS, min);
02344                         GetValue(aPresContext, prefSize, prefSizeCSS, pref);
02345                         GetValue(aPresContext, maxSize,  maxSizeCSS, max);
02346                         GetValue(aPresContext, actualSize, actualSizeCSS, calc);
02347                         GetValue(aPresContext, flexSize,  flexCSS, flex);
02348                         GetValue(aPresContext, ascentSize,  NS_INTRINSICSIZE, ascent);
02349 
02350 
02351                         printf("min%s, pref%s, max%s, actual%s, flex=%s, ascent=%s\n\n", 
02352                             min,
02353                             pref,
02354                             max,
02355                             calc,
02356                             flex,
02357                             ascent
02358                         );
02359 
02360                         return NS_OK;   
02361                 }
02362 
02363               child->GetNextBox(&child);
02364               count++;
02365             }
02366         } else {
02367         }
02368 
02369         mDebugChild = nsnull;
02370 
02371         return NS_OK;
02372 }
02373 
02374 void
02375 nsBoxFrame::SetDebugOnChildList(nsBoxLayoutState& aState, nsIBox* aChild, PRBool aDebug)
02376 {
02377     nsIBox* child = nsnull;
02378      GetChildBox(&child);
02379      while (child)
02380      {
02381         child->SetDebug(aState, aDebug);
02382         child->GetNextBox(&child);
02383      }
02384 }
02385 #endif
02386 
02387 nsresult
02388 nsBoxFrame::GetFrameSizeWithMargin(nsIBox* aBox, nsSize& aSize)
02389 {
02390   nsRect rect(aBox->GetRect());
02391   nsMargin margin(0,0,0,0);
02392   aBox->GetMargin(margin);
02393   rect.Inflate(margin);
02394   aSize.width = rect.width;
02395   aSize.height = rect.height;
02396   return NS_OK;
02397 }
02398 
02402 nsresult
02403 nsBoxFrame::CreateViewForFrame(nsPresContext*  aPresContext,
02404                                nsIFrame*        aFrame,
02405                                nsStyleContext*  aStyleContext,
02406                                PRBool           aForce)
02407 {
02408   // If we don't yet have a view, see if we need a view
02409   if (!aFrame->HasView()) {
02410     PRInt32 zIndex = 0;
02411     PRBool  autoZIndex = PR_FALSE;
02412     PRBool  fixedBackgroundAttachment = PR_FALSE;
02413 
02414     const nsStyleBackground* bg;
02415     PRBool isCanvas;
02416     PRBool hasBG =
02417         nsCSSRendering::FindBackground(aPresContext, aFrame, &bg, &isCanvas);
02418     const nsStyleDisplay* disp = aStyleContext->GetStyleDisplay();
02419 
02420     if (disp->mOpacity != 1.0f) {
02421       NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
02422         ("nsBoxFrame::CreateViewForFrame: frame=%p opacity=%g",
02423          aFrame, disp->mOpacity));
02424       aForce = PR_TRUE;
02425     }
02426 
02427     // See if the frame has a fixed background attachment
02428     if (hasBG && bg->HasFixedBackground()) {
02429       aForce = PR_TRUE;
02430       fixedBackgroundAttachment = PR_TRUE;
02431     }
02432     
02433     // See if the frame is a scrolled frame
02434     if (!aForce) {
02435       if (aStyleContext->GetPseudoType() == nsCSSAnonBoxes::scrolledContent) {
02436         NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
02437           ("nsBoxFrame::CreateViewForFrame: scrolled frame=%p", aFrame));
02438         aForce = PR_TRUE;
02439       }
02440     }
02441 
02442     if (aForce) {
02443       // Create a view
02444       nsIFrame* parent = aFrame->GetAncestorWithView();
02445       NS_ASSERTION(parent, "GetAncestorWithView failed");
02446       nsIView* parentView = parent->GetView();
02447       NS_ASSERTION(parentView, "no parent with view");
02448       nsIViewManager* viewManager = parentView->GetViewManager();
02449       NS_ASSERTION(nsnull != viewManager, "null view manager");
02450 
02451       // Create a view
02452       nsIView *view = viewManager->CreateView(aFrame->GetRect(), parentView);
02453       if (view) {
02454         // If the frame has a fixed background attachment, then indicate that the
02455         // view's contents should be repainted and not bitblt'd
02456         if (fixedBackgroundAttachment) {
02457           viewManager->SetViewBitBltEnabled(view, PR_FALSE);
02458         }
02459         
02460         // Insert the view into the view hierarchy. If the parent view is a
02461         // scrolling view we need to do this differently
02462         nsIScrollableView*  scrollingView = parentView->ToScrollableView();
02463         if (scrollingView) {
02464           scrollingView->SetScrolledView(view);
02465         } else {
02466           viewManager->SetViewZIndex(view, autoZIndex, zIndex);
02467           // XXX put view last in document order until we can do better
02468           viewManager->InsertChild(parentView, view, nsnull, PR_TRUE);
02469         }
02470 
02471         // See if the view should be hidden
02472         PRBool  viewIsVisible = PR_TRUE;
02473         PRBool  viewHasTransparentContent =
02474             !isCanvas &&
02475             (!hasBG ||
02476              (bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT));
02477 
02478         const nsStyleVisibility* vis = aStyleContext->GetStyleVisibility();
02479         if (NS_STYLE_VISIBILITY_COLLAPSE == vis->mVisible) {
02480           viewIsVisible = PR_FALSE;
02481         }
02482         else if (NS_STYLE_VISIBILITY_HIDDEN == vis->mVisible) {
02483           // If it has a widget, hide the view because the widget can't deal with it
02484           if (view->HasWidget()) {
02485             viewIsVisible = PR_FALSE;
02486           }
02487           else {
02488             // If it's a container element, then leave the view visible, but
02489             // mark it as having transparent content. The reason we need to
02490             // do this is that child elements can override their parent's
02491             // hidden visibility and be visible anyway.
02492             //
02493             // Because this function is called before processing the content
02494             // object's child elements, we can't tell if it's a leaf by looking
02495             // at whether the frame has any child frames
02496             nsIContent* content = aFrame->GetContent();
02497 
02498             if (content && content->IsContentOfType(nsIContent::eELEMENT)) {
02499               // The view needs to be visible, but marked as having transparent
02500               // content
02501               viewHasTransparentContent = PR_TRUE;
02502             } else {
02503               // Go ahead and hide the view
02504               viewIsVisible = PR_FALSE;
02505             }
02506           }
02507         }
02508 
02509         if (viewIsVisible) {
02510           if (viewHasTransparentContent) {
02511             viewManager->SetViewContentTransparency(view, PR_TRUE);
02512           }
02513 
02514         } else {
02515           viewManager->SetViewVisibility(view, nsViewVisibility_kHide);
02516         }
02517 
02518         viewManager->SetViewOpacity(view, disp->mOpacity);
02519       }
02520 
02521       // Remember our view
02522       aFrame->SetView(view);
02523 
02524       NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
02525         ("nsBoxFrame::CreateViewForFrame: frame=%p view=%p",
02526          aFrame));
02527       if (!view)
02528         return NS_ERROR_OUT_OF_MEMORY;
02529     }
02530   }
02531   return NS_OK;
02532 }
02533 
02534 // If you make changes to this function, check its counterparts
02535 // in nsTextBoxFrame and nsAreaFrame
02536 nsresult
02537 nsBoxFrame::RegUnregAccessKey(nsPresContext* aPresContext, PRBool aDoReg)
02538 {
02539   // if we have no content, we can't do anything
02540   if (!mContent)
02541     return NS_ERROR_FAILURE;
02542 
02543   // find out what type of element this is
02544   nsIAtom *atom = mContent->Tag();
02545 
02546   // only support accesskeys for the following elements
02547   if (atom != nsXULAtoms::button &&
02548       atom != nsXULAtoms::toolbarbutton &&
02549       atom != nsXULAtoms::checkbox &&
02550       atom != nsXULAtoms::textbox &&
02551       atom != nsXULAtoms::tab &&
02552       atom != nsXULAtoms::radio) {
02553     return NS_OK;
02554   }
02555 
02556   nsAutoString accessKey;
02557   mContent->GetAttr(kNameSpaceID_None, nsXULAtoms::accesskey, accessKey);
02558 
02559   if (accessKey.IsEmpty())
02560     return NS_OK;
02561 
02562   // With a valid PresContext we can get the ESM 
02563   // and register the access key
02564   nsIEventStateManager *esm = aPresContext->EventStateManager();
02565 
02566   nsresult rv;
02567 
02568   PRUint32 key = accessKey.First();
02569   if (aDoReg)
02570     rv = esm->RegisterAccessKey(mContent, key);
02571   else
02572     rv = esm->UnregisterAccessKey(mContent, key);
02573 
02574   return rv;
02575 }
02576 
02577 void
02578 nsBoxFrame::FireDOMEventSynch(const nsAString& aDOMEventName, nsIContent *aContent)
02579 {
02580   nsIContent *content = aContent ? aContent : mContent;
02581   if (content && mPresContext) {
02582     // Fire a DOM event
02583     nsCOMPtr<nsIDOMEvent> event;
02584     nsCOMPtr<nsIEventListenerManager> manager;
02585     content->GetListenerManager(getter_AddRefs(manager));
02586     if (manager && NS_SUCCEEDED(manager->CreateEvent(mPresContext, nsnull,
02587                                                      NS_LITERAL_STRING("Events"),
02588                                                      getter_AddRefs(event)))) {
02589       event->InitEvent(aDOMEventName, PR_TRUE, PR_TRUE);
02590 
02591       nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));
02592       privateEvent->SetTrusted(PR_TRUE);
02593 
02594       PRBool defaultActionEnabled;
02595       mPresContext->EventStateManager()->
02596         DispatchNewEvent(content, event, &defaultActionEnabled);
02597     }
02598   }
02599 }
02600 
02601 void 
02602 nsBoxFrame::CheckBoxOrder(nsBoxLayoutState& aState)
02603 {
02604   // Run through our list of children and check whether we
02605   // need to sort them.  Count up the children at the same
02606   // time, since we're already traversing the list.
02607   PRBool orderBoxes = PR_FALSE;
02608   PRInt32 childCount = 0;
02609   nsIFrame *child = mFrames.FirstChild();
02610 
02611   while (child) {
02612     ++childCount;
02613 
02614     PRUint32 ordinal;
02615     child->GetOrdinal(aState, ordinal);
02616     if (ordinal != DEFAULT_ORDINAL_GROUP)
02617       orderBoxes = PR_TRUE;
02618 
02619     child = child->GetNextSibling();
02620   }
02621 
02622   if (!orderBoxes || childCount < 2)
02623     return;
02624 
02625   // Turn the child list into an array for sorting.
02626   nsIFrame** boxes = new nsIFrame*[childCount];
02627   nsIFrame* box = mFrames.FirstChild();
02628   nsIFrame** boxPtr = boxes;
02629   while (box) {
02630     *boxPtr++ = box;
02631     box = box->GetNextSibling();
02632   }
02633 
02634   // sort the array by ordinal group, selection sort
02635   // XXX this could use a more efficient sort
02636   PRInt32 i, j, min;
02637   PRUint32 minOrd, jOrd;
02638   for(i = 0; i < childCount; i++) {
02639     min = i;
02640     boxes[min]->GetOrdinal(aState, minOrd);
02641     for(j = i + 1; j < childCount; j++) {
02642       boxes[j]->GetOrdinal(aState, jOrd);
02643       if (jOrd < minOrd) {
02644         min = j;
02645         minOrd = jOrd;
02646       }
02647     }
02648     box = boxes[min];
02649     boxes[min] = boxes[i];
02650     boxes[i] = box;
02651   }
02652 
02653   // turn the array back into linked list, with first and last cached
02654   mFrames.SetFrames(boxes[0]);
02655   for (i = 0; i < childCount - 1; ++i)
02656     boxes[i]->SetNextSibling(boxes[i+1]);
02657 
02658   boxes[childCount-1]->SetNextSibling(nsnull);
02659   delete [] boxes;
02660 }
02661 
02662 NS_IMETHODIMP
02663 nsBoxFrame::SetLayoutManager(nsIBoxLayout* aLayout)
02664 {
02665   mLayoutManager = aLayout;
02666   return NS_OK;
02667 }
02668 
02669 NS_IMETHODIMP
02670 nsBoxFrame::GetLayoutManager(nsIBoxLayout** aLayout)
02671 {
02672   *aLayout = mLayoutManager;
02673   NS_IF_ADDREF(*aLayout);
02674   return NS_OK;
02675 }
02676 
02677 nsresult
02678 nsBoxFrame::LayoutChildAt(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect)
02679 {
02680   // get the current rect
02681   nsRect oldRect(aBox->GetRect());
02682   aBox->SetBounds(aState, aRect);
02683 
02684   PRBool dirty = PR_FALSE;
02685   PRBool dirtyChildren = PR_FALSE;
02686   aBox->IsDirty(dirty);
02687   aBox->HasDirtyChildren(dirtyChildren);
02688 
02689   PRBool layout = PR_TRUE;
02690   if (!(dirty || dirtyChildren) && aState.LayoutReason() != nsBoxLayoutState::Initial) 
02691      layout = PR_FALSE;
02692   
02693   if (layout || (oldRect.width != aRect.width || oldRect.height != aRect.height))  {
02694     return aBox->Layout(aState);
02695   }
02696 
02697   return NS_OK;
02698 }
02699 
02700 NS_IMETHODIMP
02701 nsBoxFrame::RelayoutChildAtOrdinal(nsBoxLayoutState& aState, nsIBox* aChild)
02702 {
02703   PRUint32 ord;
02704   aChild->GetOrdinal(aState, ord);
02705   
02706   nsIFrame *child = mFrames.FirstChild();
02707   nsIFrame *curPrevSib = nsnull, *newPrevSib = nsnull;
02708   PRBool foundPrevSib = PR_FALSE, foundNewPrevSib = PR_FALSE;
02709 
02710   while (child) {
02711     if (child == aChild)
02712       foundPrevSib = PR_TRUE;
02713     else if (!foundPrevSib)
02714       curPrevSib = child;
02715 
02716     PRUint32 ordCmp;
02717     child->GetOrdinal(aState, ordCmp);
02718     if (ord < ordCmp)
02719       foundNewPrevSib = PR_TRUE;
02720     else if (!foundNewPrevSib && child != aChild)
02721       newPrevSib = child;
02722 
02723     child->GetNextBox(&child);
02724   }
02725 
02726   NS_ASSERTION(foundPrevSib, "aChild not in frame list?");
02727 
02728   if (curPrevSib == newPrevSib) {
02729     // This box is not moving.
02730     return NS_OK;
02731   }
02732 
02733   // Take aChild out of its old position in the child list.
02734   if (curPrevSib)
02735     curPrevSib->SetNextSibling(aChild->GetNextSibling());
02736   else
02737     mFrames.SetFrames(aChild->GetNextSibling());
02738 
02739   nsIBox* newNextSib;
02740   if (newPrevSib) {
02741     // insert |aChild| between |newPrevSib| and its next sibling
02742     newNextSib = newPrevSib->GetNextSibling();
02743     newPrevSib->SetNextSibling(aChild);
02744   } else {
02745     // no |newPrevSib| found, so this box will become |mFirstChild|
02746     newNextSib = mFrames.FirstChild();
02747     mFrames.SetFrames(aChild);
02748   }
02749 
02750   aChild->SetNextSibling(newNextSib);
02751 
02752   return NS_OK;
02753 }
02754 
02755 NS_IMETHODIMP
02756 nsBoxFrame::GetIndexOf(nsIBox* aBox, PRInt32* aIndex)
02757 {
02758     nsIBox* child = mFrames.FirstChild();
02759     PRInt32 count = 0;
02760     while (child) 
02761     {       
02762       if (aBox == child) {
02763           *aIndex = count;
02764           return NS_OK;
02765       }
02766 
02767       child->GetNextBox(&child);
02768       count++;
02769     }
02770 
02771     *aIndex = -1;
02772 
02773     return NS_OK;
02774 }
02775 
02776 PRBool
02777 nsBoxFrame::GetWasCollapsed(nsBoxLayoutState& aState)
02778 {
02779   return nsBox::GetWasCollapsed(aState);
02780 }
02781 
02782 void
02783 nsBoxFrame::SetWasCollapsed(nsBoxLayoutState& aState, PRBool aWas)
02784 {
02785   nsBox::SetWasCollapsed(aState, aWas);
02786 }