From 82b44e2844c301facb3b351de4591a39f196e0f3 Mon Sep 17 00:00:00 2001 From: "evaughan%netscape.com" Date: Fri, 31 Mar 2000 07:02:06 +0000 Subject: [PATCH] box skinnablility changes. -r Hyatt git-svn-id: svn://10.0.0.236/trunk@64707 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/shared/public/nsXULAtomList.h | 8 + .../editor/ui/dialogs/skin/EditorDialog.css | 1 + mozilla/layout/base/nsCSSFrameConstructor.cpp | 175 +- mozilla/layout/base/nsCSSFrameConstructor.h | 2 + mozilla/layout/base/nsIPresShell.h | 5 + mozilla/layout/base/nsPresShell.cpp | 227 +- mozilla/layout/base/public/nsIPresShell.h | 5 + mozilla/layout/generic/nsGfxScrollFrame.cpp | 1739 ++----- mozilla/layout/generic/nsGfxScrollFrame.h | 40 +- .../layout/html/base/src/nsGfxScrollFrame.cpp | 1739 ++----- .../layout/html/base/src/nsGfxScrollFrame.h | 40 +- mozilla/layout/html/base/src/nsPresShell.cpp | 227 +- .../html/base/src/nsScrollPortFrame.cpp | 560 +-- .../layout/html/base/src/nsScrollPortFrame.h | 42 +- .../html/style/src/nsCSSFrameConstructor.cpp | 175 +- .../html/style/src/nsCSSFrameConstructor.h | 2 + mozilla/layout/macbuild/layout.mcp | Bin 137961 -> 140889 bytes mozilla/layout/xul/base/src/Makefile.in | 17 +- mozilla/layout/xul/base/src/makefile.win | 70 +- mozilla/layout/xul/base/src/nsBox.cpp | 1025 ++++ mozilla/layout/xul/base/src/nsBox.h | 120 + mozilla/layout/xul/base/src/nsBoxFrame.cpp | 4315 ++++------------- mozilla/layout/xul/base/src/nsBoxFrame.h | 110 +- .../layout/xul/base/src/nsBoxLayoutState.cpp | 381 ++ .../layout/xul/base/src/nsBoxLayoutState.h | 87 + .../xul/base/src/nsBoxToBlockAdaptor.cpp | 806 +++ .../layout/xul/base/src/nsBoxToBlockAdaptor.h | 89 + ...ULButtonFrame.cpp => nsButtonBoxFrame.cpp} | 14 +- ...{nsXULButtonFrame.h => nsButtonBoxFrame.h} | 14 +- ...LCheckboxFrame.cpp => nsCheckBoxFrame.cpp} | 24 +- ...nsXULCheckboxFrame.h => nsCheckBoxFrame.h} | 21 +- .../xul/base/src/nsColorPickerFrame.cpp | 59 +- .../layout/xul/base/src/nsColorPickerFrame.h | 13 +- .../layout/xul/base/src/nsContainerBox.cpp | 536 ++ mozilla/layout/xul/base/src/nsContainerBox.h | 77 + mozilla/layout/xul/base/src/nsDeckFrame.cpp | 123 +- mozilla/layout/xul/base/src/nsDeckFrame.h | 16 +- .../layout/xul/base/src/nsFrameNavigator.cpp | 50 +- .../layout/xul/base/src/nsFrameNavigator.h | 11 +- mozilla/layout/xul/base/src/nsGrippyFrame.cpp | 4 +- mozilla/layout/xul/base/src/nsGrippyFrame.h | 2 +- .../layout/xul/base/src/nsGroupBoxFrame.cpp | 35 +- mozilla/layout/xul/base/src/nsIBox.h | 90 +- .../layout/xul/base/src/nsImageBoxFrame.cpp | 447 ++ mozilla/layout/xul/base/src/nsImageBoxFrame.h | 102 + .../layout/xul/base/src/nsLeafBoxFrame.cpp | 246 + .../{nsXULLeafFrame.h => nsLeafBoxFrame.h} | 43 +- mozilla/layout/xul/base/src/nsMenuFrame.cpp | 164 +- mozilla/layout/xul/base/src/nsMenuFrame.h | 27 +- .../layout/xul/base/src/nsMenuPopupFrame.cpp | 2 +- .../layout/xul/base/src/nsMenuPopupFrame.h | 5 +- .../layout/xul/base/src/nsPopupSetFrame.cpp | 59 +- mozilla/layout/xul/base/src/nsPopupSetFrame.h | 10 +- .../layout/xul/base/src/nsRepeatService.cpp | 2 +- .../layout/xul/base/src/nsRootBoxFrame.cpp | 261 + .../xul/base/src/nsScrollbarButtonFrame.cpp | 10 +- .../xul/base/src/nsScrollbarButtonFrame.h | 4 +- mozilla/layout/xul/base/src/nsSliderFrame.cpp | 419 +- mozilla/layout/xul/base/src/nsSliderFrame.h | 53 +- .../layout/xul/base/src/nsSplitterFrame.cpp | 318 +- mozilla/layout/xul/base/src/nsSplitterFrame.h | 7 +- mozilla/layout/xul/base/src/nsSpringFrame.cpp | 26 +- mozilla/layout/xul/base/src/nsSpringFrame.h | 13 +- .../layout/xul/base/src/nsSprocketLayout.cpp | 1368 ++++++ .../layout/xul/base/src/nsSprocketLayout.h | 175 + mozilla/layout/xul/base/src/nsStackFrame.cpp | 110 +- mozilla/layout/xul/base/src/nsStackFrame.h | 41 +- mozilla/layout/xul/base/src/nsStackLayout.cpp | 266 + mozilla/layout/xul/base/src/nsStackLayout.h | 53 + mozilla/layout/xul/base/src/nsTabFrame.cpp | 2 +- mozilla/layout/xul/base/src/nsTabFrame.h | 4 +- ...{nsXULTextFrame.cpp => nsTextBoxFrame.cpp} | 141 +- .../{nsXULTextFrame.h => nsTextBoxFrame.h} | 39 +- .../layout/xul/base/src/nsTitledBoxFrame.cpp | 35 +- .../xul/base/src/nsTitledButtonFrame.cpp | 190 +- .../layout/xul/base/src/nsTitledButtonFrame.h | 30 +- .../layout/xul/base/src/nsToolbarFrame.cpp | 33 - mozilla/layout/xul/base/src/nsToolbarFrame.h | 7 - .../layout/xul/base/src/nsToolboxFrame.cpp | 129 +- mozilla/layout/xul/base/src/nsToolboxFrame.h | 29 +- .../layout/xul/base/src/nsXULLeafFrame.cpp | 211 - .../layout/xul/content/src/nsXULAtomList.h | 8 + .../resources/content/profileSelection.xul | 6 +- mozilla/profile/resources/skin/profile.css | 4 +- .../sidebar/resources/sidebarOverlay.css | 7 +- mozilla/xpfe/global/resources/skin/global.css | 157 +- mozilla/xpfe/global/resources/skin/xul.css | 2 - .../global/resources/skin/xulBindings.xml | 4 +- 88 files changed, 10466 insertions(+), 7899 deletions(-) create mode 100644 mozilla/layout/xul/base/src/nsBox.cpp create mode 100644 mozilla/layout/xul/base/src/nsBox.h create mode 100644 mozilla/layout/xul/base/src/nsBoxLayoutState.cpp create mode 100644 mozilla/layout/xul/base/src/nsBoxLayoutState.h create mode 100644 mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.cpp create mode 100644 mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.h rename mozilla/layout/xul/base/src/{nsXULButtonFrame.cpp => nsButtonBoxFrame.cpp} (87%) rename mozilla/layout/xul/base/src/{nsXULButtonFrame.h => nsButtonBoxFrame.h} (84%) rename mozilla/layout/xul/base/src/{nsXULCheckboxFrame.cpp => nsCheckBoxFrame.cpp} (77%) rename mozilla/layout/xul/base/src/{nsXULCheckboxFrame.h => nsCheckBoxFrame.h} (68%) create mode 100644 mozilla/layout/xul/base/src/nsContainerBox.cpp create mode 100644 mozilla/layout/xul/base/src/nsContainerBox.h create mode 100644 mozilla/layout/xul/base/src/nsImageBoxFrame.cpp create mode 100644 mozilla/layout/xul/base/src/nsImageBoxFrame.h create mode 100644 mozilla/layout/xul/base/src/nsLeafBoxFrame.cpp rename mozilla/layout/xul/base/src/{nsXULLeafFrame.h => nsLeafBoxFrame.h} (63%) create mode 100644 mozilla/layout/xul/base/src/nsRootBoxFrame.cpp create mode 100644 mozilla/layout/xul/base/src/nsSprocketLayout.cpp create mode 100644 mozilla/layout/xul/base/src/nsSprocketLayout.h create mode 100644 mozilla/layout/xul/base/src/nsStackLayout.cpp create mode 100644 mozilla/layout/xul/base/src/nsStackLayout.h rename mozilla/layout/xul/base/src/{nsXULTextFrame.cpp => nsTextBoxFrame.cpp} (84%) rename mozilla/layout/xul/base/src/{nsXULTextFrame.h => nsTextBoxFrame.h} (79%) delete mode 100644 mozilla/layout/xul/base/src/nsXULLeafFrame.cpp diff --git a/mozilla/content/shared/public/nsXULAtomList.h b/mozilla/content/shared/public/nsXULAtomList.h index cdd0b327209..528b4893b0c 100644 --- a/mozilla/content/shared/public/nsXULAtomList.h +++ b/mozilla/content/shared/public/nsXULAtomList.h @@ -97,6 +97,7 @@ XUL_ATOM(crop, "crop") XUL_ATOM(mode, "mode") XUL_ATOM(box, "box") +XUL_ATOM(mousethrough, "mousethrough") XUL_ATOM(flex, "flex") XUL_ATOM(spring, "spring") XUL_ATOM(orient, "orient") @@ -130,6 +131,13 @@ XUL_ATOM(resizeafter, "resizeafter") XUL_ATOM(state, "state") XUL_ATOM(debug, "debug") +// grid +XUL_ATOM(grid, "grid") +XUL_ATOM(rows, "rows") +XUL_ATOM(columns, "columns") +XUL_ATOM(row, "row") +XUL_ATOM(column, "column") + // toolbar & toolbar d&d atoms XUL_ATOM(ddDropLocation, "dd-droplocation") XUL_ATOM(ddDropLocationCoord, "dd-droplocationcoord") diff --git a/mozilla/editor/ui/dialogs/skin/EditorDialog.css b/mozilla/editor/ui/dialogs/skin/EditorDialog.css index de2fc81b198..87202df0494 100644 --- a/mozilla/editor/ui/dialogs/skin/EditorDialog.css +++ b/mozilla/editor/ui/dialogs/skin/EditorDialog.css @@ -206,6 +206,7 @@ menu.colorpicker { margin-bottom: 2px; } + menu.colorpicker:active { border: 1px inset #CCCCCC; } diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 68beb9b6c61..d3d07e7611f 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -120,7 +120,7 @@ #include "nsIDOMDocument.h" #include "nsDocument.h" #include "nsToolbarItemFrame.h" -#include "nsXULCheckboxFrame.h" +#include "nsCheckBoxFrame.h" #include "nsIScrollable.h" #ifdef DEBUG @@ -132,8 +132,28 @@ static PRBool gNoisyInlineConstruction = PR_FALSE; #define NEWGFX_LIST_SCROLLFRAME //------------------------------------------------------------------ +#ifdef NEWGFX_LIST_SCROLLFRAME nsresult NS_NewGfxListControlFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); +#endif + +// grid + +/* +nsresult +NS_NewGridFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); + +nsresult +NS_NewTempleFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsHorizontal); + +nsresult +NS_NewObeliskFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsHorizontal); + +// end grid +*/ + +nsresult +NS_NewRootBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); nsresult NS_NewThumbFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); @@ -142,7 +162,7 @@ nsresult NS_NewScrollPortFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); nsresult -NS_NewGfxScrollFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, nsIDocument* aDocument ); +NS_NewGfxScrollFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, nsIDocument* aDocument, PRBool aIsRoot); nsresult NS_NewTabFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); @@ -163,7 +183,10 @@ nsresult NS_NewTitledButtonFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); nsresult -NS_NewXULTextFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); +NS_NewImageBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); + +nsresult +NS_NewTextBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); nsresult NS_NewTitledBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); @@ -178,7 +201,7 @@ nsresult NS_NewBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoot); nsresult -NS_NewXULButtonFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame); +NS_NewButtonBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame); nsresult NS_NewSliderFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); @@ -2359,6 +2382,7 @@ nsCSSFrameConstructor::TableIsValidCellContent(nsIPresContext* aPresContext, #ifdef INCLUDE_XUL if ( (nsXULAtoms::button == tag.get()) || (nsXULAtoms::titledbutton == tag.get()) || + (nsXULAtoms::box == tag.get()) || (nsXULAtoms::image == tag.get()) || (nsXULAtoms::grippy == tag.get()) || (nsXULAtoms::splitter == tag.get()) || @@ -2603,6 +2627,7 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIPresShell* aPresShell, aParentFrame, nsLayoutAtoms::scrolledContentPseudo, document, + PR_FALSE, scrollFrame, newContext, newScrollFrame); @@ -2837,7 +2862,15 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, nsIAtom* rootPseudo; if (!isPaginated) { - NS_NewRootFrame(aPresShell, &rootFrame); + PRInt32 nameSpaceID; + if (NS_SUCCEEDED(aDocElement->GetNameSpaceID(nameSpaceID)) && + nameSpaceID == nsXULAtoms::nameSpaceID) + { + NS_NewRootBoxFrame(aPresShell, &rootFrame); + } else { + NS_NewRootFrame(aPresShell, &rootFrame); + } + rootPseudo = nsLayoutAtoms::canvasPseudo; mDocElementContainingBlock = rootFrame; } else { @@ -2868,6 +2901,8 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, } } + //isScrollable = PR_FALSE; + // As long as the webshell doesn't prohibit it, and the device supports // it, create a scroll frame that will act as the scolling mechanism for // the viewport. @@ -2941,6 +2976,7 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, viewportFrame, rootPseudo, document, + PR_TRUE, newFrame, rootPseudoStyle, newScrollableFrame); @@ -4656,7 +4692,7 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell, else if (aTag == nsXULAtoms::button) { processChildren = PR_TRUE; isReplaced = PR_TRUE; - rv = NS_NewXULButtonFrame(aPresShell, &newFrame); + rv = NS_NewButtonBoxFrame(aPresShell, &newFrame); const nsStyleDisplay* display = (const nsStyleDisplay*) aStyleContext->GetStyleData(eStyleStruct_Display); @@ -4679,15 +4715,18 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell, } // End of BUTTON CONSTRUCTION logic // TITLED BUTTON CONSTRUCTION - else if (aTag == nsXULAtoms::titledbutton || - aTag == nsXULAtoms::image) { + else if (aTag == nsXULAtoms::titledbutton) { processChildren = PR_TRUE; isReplaced = PR_TRUE; rv = NS_NewTitledButtonFrame(aPresShell, &newFrame); } // End of TITLED BUTTON CONSTRUCTION logic - + else if (aTag == nsXULAtoms::image) { + processChildren = PR_TRUE; + isReplaced = PR_TRUE; + rv = NS_NewImageBoxFrame(aPresShell, &newFrame); + } else if (aTag == nsXULAtoms::spring) { processChildren = PR_TRUE; isReplaced = PR_TRUE; @@ -4699,7 +4738,7 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell, else if (aTag == nsXULAtoms::text) { processChildren = PR_TRUE; isReplaced = PR_TRUE; - rv = NS_NewXULTextFrame(aPresShell, &newFrame); + rv = NS_NewTextBoxFrame(aPresShell, &newFrame); } // End of TEXT CONSTRUCTION logic @@ -4736,7 +4775,90 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell, processChildren = PR_TRUE; isReplaced = PR_TRUE; rv = NS_NewMenuPopupFrame(aPresShell, &newFrame); - } + } + + /* + + // ------- Begin Grid --------- + else if (aTag == nsXULAtoms::grid) { + processChildren = PR_TRUE; + isReplaced = PR_TRUE; + rv = NS_NewGridFrame(aPresShell, &newFrame); + + const nsStyleDisplay* display = (const nsStyleDisplay*) + aStyleContext->GetStyleData(eStyleStruct_Display); + + // Boxes can scroll. + if (IsScrollable(aPresContext, display)) { + + // set the top to be the newly created scrollframe + BuildScrollFrame(aPresShell, aPresContext, aState, aContent, aStyleContext, newFrame, aParentFrame, + topFrame, aStyleContext); + + // we have a scrollframe so the parent becomes the scroll frame. + newFrame->GetParent(&aParentFrame); + + primaryFrameSet = PR_TRUE; + + frameHasBeenInitialized = PR_TRUE; + + } + } //------- End Grid ------ + + // ------- Begin Rows/Columns --------- + else if (aTag == nsXULAtoms::rows || aTag == nsXULAtoms::columns) { + processChildren = PR_TRUE; + isReplaced = PR_TRUE; + PRBool isHorizontal = (aTag == nsXULAtoms::columns); + rv = NS_NewTempleFrame(aPresShell, &newFrame, isHorizontal); + + const nsStyleDisplay* display = (const nsStyleDisplay*) + aStyleContext->GetStyleData(eStyleStruct_Display); + + // Boxes can scroll. + if (IsScrollable(aPresContext, display)) { + + // set the top to be the newly created scrollframe + BuildScrollFrame(aPresShell, aPresContext, aState, aContent, aStyleContext, newFrame, aParentFrame, + topFrame, aStyleContext); + + // we have a scrollframe so the parent becomes the scroll frame. + newFrame->GetParent(&aParentFrame); + + primaryFrameSet = PR_TRUE; + + frameHasBeenInitialized = PR_TRUE; + + } + } //------- End Grid ------ + + // ------- Begin Row/Column --------- + else if (aTag == nsXULAtoms::row || aTag == nsXULAtoms::column) { + processChildren = PR_TRUE; + isReplaced = PR_TRUE; + PRBool isHorizontal = (aTag == nsXULAtoms::row); + rv = NS_NewObeliskFrame(aPresShell, &newFrame, isHorizontal); + + const nsStyleDisplay* display = (const nsStyleDisplay*) + aStyleContext->GetStyleData(eStyleStruct_Display); + + // Boxes can scroll. + if (IsScrollable(aPresContext, display)) { + + // set the top to be the newly created scrollframe + BuildScrollFrame(aPresShell, aPresContext, aState, aContent, aStyleContext, newFrame, aParentFrame, + topFrame, aStyleContext); + + // we have a scrollframe so the parent becomes the scroll frame. + newFrame->GetParent(&aParentFrame); + + primaryFrameSet = PR_TRUE; + + frameHasBeenInitialized = PR_TRUE; + + } + } //------- End Grid ------ +*/ else if (aTag == nsXULAtoms::title) { processChildren = PR_TRUE; isReplaced = PR_TRUE; @@ -4949,7 +5071,7 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell, aTag == nsXULAtoms::radio) { processChildren = PR_TRUE; isReplaced = PR_TRUE; - rv = NS_NewXULCheckboxFrame(aPresShell, &newFrame); + rv = NS_NewCheckBoxFrame(aPresShell, &newFrame); } // End of XULCHECKBOX CONSTRUCTION logic @@ -5123,6 +5245,7 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsIPresShell* aPresShell, nsIFrame* aParentFrame, nsIAtom* aScrolledPseudo, nsIDocument* aDocument, + PRBool aIsRoot, nsIFrame*& aNewFrame, nsCOMPtr& aScrolledChildStyle, nsIFrame*& aScrollableFrame) @@ -5140,7 +5263,7 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsIPresShell* aPresShell, if (isGfx) { BuildGfxScrollFrame(aPresShell, aPresContext, aState, aContent, aDocument, aParentFrame, - contentStyle, gfxScrollFrame, anonymousItems); + contentStyle, aIsRoot, gfxScrollFrame, anonymousItems); scrollFrame = anonymousItems.childList; parentFrame = gfxScrollFrame; @@ -5283,6 +5406,7 @@ nsCSSFrameConstructor::BuildScrollFrame (nsIPresShell* aPresShell, aParentFrame, nsLayoutAtoms::scrolledContentPseudo, document, + PR_FALSE, aNewFrame, scrolledContentStyle, scrollFrame); @@ -5317,10 +5441,11 @@ nsCSSFrameConstructor::BuildGfxScrollFrame (nsIPresShell* aPresShell, nsIDocument* aDocument, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + PRBool aIsRoot, nsIFrame*& aNewFrame, nsFrameItems& aAnonymousFrames) { - NS_NewGfxScrollFrame(aPresShell, &aNewFrame,aDocument); + NS_NewGfxScrollFrame(aPresShell, &aNewFrame, aDocument, aIsRoot); InitAndRestoreFrame(aPresContext, aState, aContent, aParentFrame, aStyleContext, nsnull, aNewFrame); @@ -7074,6 +7199,28 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, } else { // Find the frame that precedes the insertion point. nsIFrame* prevSibling = FindPreviousSibling(shell, aContainer, aIndexInContainer); + + /* + if (prevSibling) { + nsIFrame* parent; + prevSibling->GetParent(&parent); + nsIFrame* first; + parent->FirstChild(aPresContext, nsnull, &first); + PRBool found = PR_FALSE; + while(first) + { + if (first == prevSibling) { + found = PR_TRUE; + break; + } + + first->GetNextSibling(&first); + } + + NS_ASSERTION(found,"Error sibling not in parent!!!!!"); + } + */ + nsIFrame* nextSibling = nsnull; PRBool isAppend = PR_FALSE; diff --git a/mozilla/layout/base/nsCSSFrameConstructor.h b/mozilla/layout/base/nsCSSFrameConstructor.h index 8ca4f35606e..a6a35aa7b81 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.h +++ b/mozilla/layout/base/nsCSSFrameConstructor.h @@ -646,6 +646,7 @@ protected: nsIFrame* aParentFrame, nsIAtom* aScrolledPseudo, nsIDocument* aDocument, + PRBool aIsRoot, nsIFrame*& aNewFrame, nsCOMPtr& aScrolledChildStyle, nsIFrame*& aScrollableFrame); @@ -671,6 +672,7 @@ protected: nsIDocument* aDocument, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + PRBool aIsRoot, nsIFrame*& aNewFrame, nsFrameItems& aAnonymousFrames); diff --git a/mozilla/layout/base/nsIPresShell.h b/mozilla/layout/base/nsIPresShell.h index 98d864df08b..02066d7ba6f 100644 --- a/mozilla/layout/base/nsIPresShell.h +++ b/mozilla/layout/base/nsIPresShell.h @@ -109,6 +109,11 @@ public: // Methods for recycling frames. NS_IMETHOD AllocateFrame(size_t aSize, void** aResult) = 0; NS_IMETHOD FreeFrame(size_t aSize, void* aFreeChunk) = 0; + + // Dynamic stack memory allocation + NS_IMETHOD PushStackMemory() = 0; + NS_IMETHOD PopStackMemory() = 0; + NS_IMETHOD AllocateStackMemory(size_t aSize, void** aResult) = 0; NS_IMETHOD GetDocument(nsIDocument** aResult) = 0; diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 9a3d576938a..92de48d7606 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -147,7 +147,7 @@ static NS_DEFINE_CID(kCXIFConverterCID, NS_XIFFORMATCONVERTER_CID); static PRInt32 gMaxRCProcessingTime = -1; // Largest chunk size we recycle -static const size_t gMaxRecycledSize = 300; +static const size_t gMaxRecycledSize = 400; // Flag for enabling/disabling asynchronous reflow // Set via the "layout.reflow.async" pref @@ -157,6 +157,173 @@ static PRBool gDoAsyncReflow = PR_FALSE; // Set via the "layout.reflow.async.afterDocLoad" pref static PRBool gDoAsyncReflowAfterDocLoad = PR_FALSE; +#define MARK_INCREMENT 50 +#define BLOCK_INCREMENT 2048 + +/**A block of memory that the stack will + * chop up and hand out + */ +struct StackBlock { + + // a block of memory + void* mBlock; + + // another block of memory that would only be created + // if our stack overflowed. Yes we have the ability + // to grow on a stack overflow + StackBlock* mNext; + StackBlock() + { + mBlock = new char*[BLOCK_INCREMENT]; + mNext = nsnull; + } + + ~StackBlock() + { + delete[] mBlock; + } +}; + +/* we hold an array of marks. A push pushes a mark on the stack + * a pop pops it off. + */ +struct StackMark { + // the block of memory we are currently handing out chunks of + StackBlock* mBlock; + + // our current position in the memory + size_t mPos; +}; + + +/* A stack arena allows a stack based interface to a block of memory. + * It should be used when you need to allocate some temporary memory that + * you will immediately return. + */ +class StackArena { +public: + StackArena(); + ~StackArena(); + + // Memory management functions + nsresult Allocate(size_t aSize, void** aResult); + nsresult Push(); + nsresult Pop(); + +private: + // our current position in memory + size_t mPos; + + // a list of memory block. Usually there is only one + // but if we overrun our stack size we can get more memory. + StackBlock* mBlocks; + + // the current block of memory we are passing our chucks of + StackBlock* mCurBlock; + + // our stack of mark where push has been called + StackMark* mMarks; + + // the current top of the the mark list + PRUint32 mStackTop; + + // the size of the mark array + PRUint32 mMarkLength; +}; + + + +StackArena::StackArena() +{ + // allocate the marks array + mMarkLength = MARK_INCREMENT; + mMarks = new StackMark[mMarkLength]; + + // allocate our stack memory + mBlocks = new StackBlock(); + mCurBlock = mBlocks; + + mStackTop = 0; + mPos = 0; +} + +StackArena::~StackArena() +{ + // free up our data + delete[] mMarks; + while(mBlocks) + { + StackBlock* toDelete = mBlocks; + mBlocks = mBlocks->mNext; + delete toDelete; + } +} + +nsresult +StackArena::Push() +{ + // if the we overrun our mark array. Resize it. + if (mStackTop + 1 >= mMarkLength) + { + StackMark* oldMarks = mMarks; + PRUint32 oldLength = mMarkLength; + mMarkLength += MARK_INCREMENT; + void* marks = 0; + mMarks = new StackMark[mMarkLength]; + nsCRT::memcpy(mMarks, oldMarks, sizeof(StackMark)*oldLength); + + delete[] oldMarks; + } + + // set a mark at the top + mMarks[mStackTop].mBlock = mCurBlock; + mMarks[mStackTop].mPos = mPos; + + mStackTop++; + + return NS_OK; +} + +nsresult +StackArena::Allocate(size_t aSize, void** aResult) +{ + NS_ASSERTION(mStackTop > 0, "Error allocate called before push!!!"); + + // make sure we are aligned. Beard said 8 was safer then 4. + // Round size to multiple of 8 + aSize = PR_ROUNDUP(aSize, 8); + + // if the size makes the stack overflow. Grab another block for the stack + if (mPos + aSize >= BLOCK_INCREMENT) + { + NS_ASSERTION(aSize <= BLOCK_INCREMENT,"Requested memory is greater that our block size!!"); + if (mCurBlock->mNext == nsnull) + mCurBlock->mNext = new StackBlock(); + + mCurBlock = mCurBlock->mNext; + mPos = 0; + } + + // return the chunk they need. + *aResult = ((char*)mCurBlock->mBlock) + mPos; + mPos += aSize; + + return NS_OK; +} + +nsresult +StackArena::Pop() +{ + // pop off the mark + NS_ASSERTION(mStackTop > 0, "Error Pop called 1 too many times"); + mStackTop--; + mCurBlock = mMarks[mStackTop].mBlock; + mPos = mMarks[mStackTop].mPos; + + return NS_OK; +} + + // Memory is allocated 4-byte aligned. We have recyclers for chunks up to // 200 bytes class FrameArena { @@ -190,7 +357,7 @@ FrameArena::~FrameArena() { // Free the arena in the pool and finish using it PL_FinishArenaPool(&mPool); -} +} nsresult FrameArena::AllocateFrame(size_t aSize, void** aResult) @@ -309,7 +476,12 @@ public: NS_IMETHOD AllocateFrame(size_t aSize, void** aResult); NS_IMETHOD FreeFrame(size_t aSize, void* aFreeChunk); - + + // Dynamic stack memory allocation + NS_IMETHOD PushStackMemory(); + NS_IMETHOD PopStackMemory(); + NS_IMETHOD AllocateStackMemory(size_t aSize, void** aResult); + NS_IMETHOD GetDocument(nsIDocument** aResult); NS_IMETHOD GetPresContext(nsIPresContext** aResult); NS_IMETHOD GetViewManager(nsIViewManager** aResult); @@ -522,6 +694,7 @@ protected: PRBool mPendingReflowEvent; nsCOMPtr mEventQueue; FrameArena mFrameArena; + StackArena* mStackArena; PRInt32 mAccumulatedReflowTime; // Time spent in reflow command processing so far PRPackedBool mDocumentIsLoading; // A flag that is true while the document is loading. PRPackedBool mBatchReflows; // When set to true, the pres shell batches reflow commands. @@ -540,6 +713,8 @@ protected: private: + void FreeDynamicStack(); + //helper funcs for disabing autoscrolling void DisableScrolling(){mScrollingEnabled = PR_FALSE;} void EnableScrolling(){mScrollingEnabled = PR_TRUE;} @@ -650,7 +825,7 @@ NS_NewPresShell(nsIPresShell** aInstancePtrResult) (void **) aInstancePtrResult); } -PresShell::PresShell() +PresShell::PresShell():mStackArena(nsnull) { NS_INIT_REFCNT(); mIsDestroying = PR_FALSE; @@ -718,6 +893,9 @@ PresShell::QueryInterface(const nsIID& aIID, void** aInstancePtr) PresShell::~PresShell() { + // if we allocated any stack memory free it. + FreeDynamicStack(); + mRefCnt = 99;/* XXX hack! get around re-entrancy bugs */ mIsDestroying = PR_TRUE; @@ -873,6 +1051,44 @@ PresShell::Init(nsIDocument* aDocument, return NS_OK; } + // Dynamic stack memory allocation +NS_IMETHODIMP +PresShell::PushStackMemory() +{ + if (nsnull == mStackArena) + mStackArena = new StackArena(); + + return mStackArena->Push(); +} + +NS_IMETHODIMP +PresShell::PopStackMemory() +{ + if (nsnull == mStackArena) + mStackArena = new StackArena(); + + return mStackArena->Pop(); +} + +NS_IMETHODIMP +PresShell::AllocateStackMemory(size_t aSize, void** aResult) +{ + if (nsnull == mStackArena) + mStackArena = new StackArena(); + + return mStackArena->Allocate(aSize, aResult); +} + +void +PresShell::FreeDynamicStack() +{ + if (mStackArena) { + delete mStackArena; + mStackArena = nsnull; + } +} + + NS_IMETHODIMP PresShell::FreeFrame(size_t aSize, void* aPtr) { @@ -2138,6 +2354,9 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible) MOZ_TIMER_DEBUGLOG(("Stop: Reflow: PresShell::ProcessReflowCommands(), this=%p\n", this)); MOZ_TIMER_STOP(mReflowWatch); + + // if we allocated any stack memory during reflow free it. + //FreeDynamicStack(); return NS_OK; } diff --git a/mozilla/layout/base/public/nsIPresShell.h b/mozilla/layout/base/public/nsIPresShell.h index 98d864df08b..02066d7ba6f 100644 --- a/mozilla/layout/base/public/nsIPresShell.h +++ b/mozilla/layout/base/public/nsIPresShell.h @@ -109,6 +109,11 @@ public: // Methods for recycling frames. NS_IMETHOD AllocateFrame(size_t aSize, void** aResult) = 0; NS_IMETHOD FreeFrame(size_t aSize, void* aFreeChunk) = 0; + + // Dynamic stack memory allocation + NS_IMETHOD PushStackMemory() = 0; + NS_IMETHOD PopStackMemory() = 0; + NS_IMETHOD AllocateStackMemory(size_t aSize, void** aResult) = 0; NS_IMETHOD GetDocument(nsIDocument** aResult) = 0; diff --git a/mozilla/layout/generic/nsGfxScrollFrame.cpp b/mozilla/layout/generic/nsGfxScrollFrame.cpp index 5c46f9f2ce6..9fa96f11156 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.cpp +++ b/mozilla/layout/generic/nsGfxScrollFrame.cpp @@ -49,6 +49,7 @@ #include "nsIScrollPositionListener.h" //#include "nsBoxFrame.h" #include "nsIElementFactory.h" +#include "nsBoxLayoutState.h" static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID); static NS_DEFINE_IID(kScrollingViewCID, NS_SCROLLING_VIEW_CID); @@ -133,98 +134,27 @@ public: NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument) { mDocument = nsnull; return NS_OK; } - PRBool SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aSize, PRBool aReflow=PR_TRUE); - PRInt32 GetIntegerAttribute(nsIFrame* aFrame, nsIAtom* atom, PRInt32 defaultValue); + PRBool SetAttribute(nsIBox* aBox, nsIAtom* aAtom, nscoord aSize, PRBool aReflow=PR_TRUE); + PRInt32 GetIntegerAttribute(nsIBox* aFrame, nsIAtom* atom, PRInt32 defaultValue); - nsresult CalculateChildTotalSize(nsIFrame* aKidFrame, - nsHTMLReflowMetrics& aKidReflowMetrics); - - nsresult GetFrameSize( nsIFrame* aFrame, - nsSize& aSize); - - nsresult SetFrameSize( nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsSize aSize); - - nsresult CalculateScrollAreaSize(nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - const nsSize& aSbSize, - nsSize& aScrollAreaSize); - - void SetScrollbarVisibility(nsIFrame* aScrollbar, PRBool aVisible); - - - - void ReflowScrollbars( nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame*& aIncrementalChild); - - void ReflowScrollbar( nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - PRBool& aScrollBarResized, - nsIFrame* aScrollBarFrame, - nsIFrame*& aIncrementalChild); - - - nsresult ReflowFrame( nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame* aFrame, - const nsSize& aAvailable, - const nsSize& aComputed, - PRBool& aResized, - nsIFrame*& aIncrementalChild); - - void ReflowScrollArea( nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame*& aIncrementalChild); - - void LayoutChildren(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState); - - void GetScrollbarDimensions(nsIPresContext* aPresContext, - nsSize& aSbSize); + nsresult Layout(nsBoxLayoutState& aState); + nsresult LayoutBox(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect); void AddRemoveScrollbar (PRBool& aHasScrollbar, nscoord& aSize, nscoord aSbSize, PRBool aAdd); - void AddHorizontalScrollbar (const nsSize& aSbSize, nsSize& aScrollAreaSize); - void AddVerticalScrollbar (const nsSize& aSbSize, nsSize& aScrollAreaSize); - void RemoveHorizontalScrollbar(const nsSize& aSbSize, nsSize& aScrollAreaSize); - void RemoveVerticalScrollbar (const nsSize& aSbSize, nsSize& aScrollAreaSize); - - /* - PRBool IsDirty(nsIFrame* aFrame) { - nsFrameState frameState; - aFrame->GetFrameState(&frameState); - if (frameState & NS_FRAME_IS_DIRTY) - return PR_TRUE; - else - return PR_FALSE; - } - - void MarkDirty(nsIFrame* aFrame) { - nsFrameState frameState; - aFrame->GetFrameState(&frameState); - frameState |= NS_FRAME_IS_DIRTY; - aFrame->SetFrameState(frameState); - } - */ + void AddHorizontalScrollbar (const nsSize& aSbSize, nsRect& aScrollAreaSize); + void AddVerticalScrollbar (const nsSize& aSbSize, nsRect& aScrollAreaSize); + void RemoveHorizontalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize); + void RemoveVerticalScrollbar (const nsSize& aSbSize, nsRect& aScrollAreaSize); nsIScrollableView* GetScrollableView(nsIPresContext* aPresContext); - void GetScrolledContentSize(nsIPresContext* aPresContext, nsSize& aSize); + void GetScrolledContentSize(nsSize& aSize); void ScrollbarChanged(nsIPresContext* aPresContext, nscoord aX, nscoord aY); - nsresult GetContentOf(nsIFrame* aFrame, nsIContent** aContent); - nsIFrame* mHScrollbarFrame; - nsIFrame* mVScrollbarFrame; - nsIFrame* mScrollAreaFrame; + nsIBox* mHScrollbarBox; + nsIBox* mVScrollbarBox; + nsIBox* mScrollAreaBox; nscoord mOnePixel; nsCOMPtr mDocument; nsGfxScrollFrame* mOuter; @@ -241,13 +171,13 @@ public: NS_IMPL_ISUPPORTS2(nsGfxScrollFrameInner, nsIDocumentObserver, nsIScrollPositionListener) nsresult -NS_NewGfxScrollFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, nsIDocument* aDocument) +NS_NewGfxScrollFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, nsIDocument* aDocument, PRBool aIsRoot) { NS_PRECONDITION(aNewFrame, "null OUT ptr"); if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } - nsGfxScrollFrame* it = new (aPresShell) nsGfxScrollFrame(aDocument); + nsGfxScrollFrame* it = new (aPresShell) nsGfxScrollFrame(aPresShell, aDocument, aIsRoot); if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } @@ -255,7 +185,7 @@ NS_NewGfxScrollFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, nsIDocument return NS_OK; } -nsGfxScrollFrame::nsGfxScrollFrame(nsIDocument* aDocument) +nsGfxScrollFrame::nsGfxScrollFrame(nsIPresShell* aShell, nsIDocument* aDocument, PRBool aIsRoot):nsBoxFrame(aShell, aIsRoot) { mInner = new nsGfxScrollFrameInner(this); mInner->AddRef(); @@ -263,6 +193,7 @@ nsGfxScrollFrame::nsGfxScrollFrame(nsIDocument* aDocument) mPresContext = nsnull; mInner->mIsRoot = PR_FALSE; mInner->mNeverReflowed = PR_TRUE; + SetLayoutManager(nsnull); } nsGfxScrollFrame::~nsGfxScrollFrame() @@ -278,9 +209,12 @@ nsGfxScrollFrame::~nsGfxScrollFrame() NS_IMETHODIMP nsGfxScrollFrame::SetScrolledFrame(nsIPresContext* aPresContext, nsIFrame *aScrolledFrame) { - mFrames.DestroyFrame(aPresContext, mInner->mScrollAreaFrame); - mInner->mScrollAreaFrame = aScrolledFrame; - mFrames.InsertFrame(nsnull, nsnull, mInner->mScrollAreaFrame); + NS_ERROR("Not implemented!"); + /* + mFrames.DestroyFrame(aPresContext, mInner->mScrollAreaBox); + mInner->mScrollAreaBox = aScrolledFrame; + mFrames.InsertFrame(nsnull, nsnull, mInner->mScrollAreaBox); + */ return NS_OK; } @@ -291,7 +225,10 @@ nsGfxScrollFrame::SetScrolledFrame(nsIPresContext* aPresContext, nsIFrame *aScro NS_IMETHODIMP nsGfxScrollFrame::GetScrolledFrame(nsIPresContext* aPresContext, nsIFrame *&aScrolledFrame) const { - return mInner->mScrollAreaFrame->FirstChild(aPresContext, nsnull, &aScrolledFrame); + nsIBox* child = nsnull; + mInner->mScrollAreaBox->GetChildBox(&child); + child->GetFrame(&aScrolledFrame); + return NS_OK; } /** @@ -302,10 +239,10 @@ nsGfxScrollFrame::GetClipSize(nsIPresContext* aPresContext, nscoord *aWidth, nscoord *aHeight) const { - nsSize size; - mInner->mScrollAreaFrame->GetSize(size); - *aWidth = size.width; - *aHeight = size.height; + nsRect rect; + mInner->mScrollAreaBox->GetBounds(rect); + *aWidth = rect.width; + *aHeight = rect.height; return NS_OK; } @@ -358,7 +295,7 @@ NS_IMETHODIMP nsGfxScrollFrame::Destroy(nsIPresContext* aPresContext) { - return nsHTMLContainerFrame::Destroy(aPresContext); + return nsBoxFrame::Destroy(aPresContext); } NS_IMETHODIMP @@ -369,14 +306,9 @@ nsGfxScrollFrame::Init(nsIPresContext* aPresContext, nsIFrame* aPrevInFlow) { mPresContext = aPresContext; - nsresult rv = nsHTMLContainerFrame::Init(aPresContext, aContent, + nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aStyleContext, aPrevInFlow); - -// nsCOMPtr content; -// mInner->GetContentOf(this, getter_AddRefs(content)); - -// content->GetDocument(*getter_AddRefs(mInner->mDocument)); mInner->mDocument->AddObserver(mInner); return rv; } @@ -386,16 +318,16 @@ nsGfxScrollFrame::SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList) { - nsresult rv = nsHTMLContainerFrame::SetInitialChildList(aPresContext, aListName, + nsresult rv = nsBoxFrame::SetInitialChildList(aPresContext, aListName, aChildList); // get scroll area - mInner->mScrollAreaFrame = mFrames.FirstChild(); - + GetChildBox(&mInner->mScrollAreaBox); + // horizontal scrollbar - mInner->mScrollAreaFrame->GetNextSibling(&mInner->mHScrollbarFrame); + mInner->mScrollAreaBox->GetNextBox(&mInner->mHScrollbarBox); // vertical scrollbar - mInner->mHScrollbarFrame->GetNextSibling(&mInner->mVScrollbarFrame); + mInner->mHScrollbarBox->GetNextBox(&mInner->mVScrollbarBox); // listen for scroll events. mInner->GetScrollableView(aPresContext)->AddScrollPositionListener(mInner); @@ -435,278 +367,20 @@ nsGfxScrollFrame::RemoveFrame(nsIPresContext* aPresContext, } NS_IMETHODIMP -nsGfxScrollFrame::DidReflow(nsIPresContext* aPresContext, - nsDidReflowStatus aStatus) +nsGfxScrollFrame::GetPadding(nsMargin& aMargin) { - // Let the default nsFrame implementation clear the state flags - // and size and position our view - nsresult rv = nsHTMLContainerFrame::DidReflow(aPresContext, aStatus); - - return rv; + aMargin.SizeTo(0,0,0,0); + return NS_OK; } - -NS_IMETHODIMP -nsGfxScrollFrame::Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) -{ - NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS, - ("enter nsGfxScrollFrame::Reflow: maxSize=%d,%d", - aReflowState.availableWidth, - aReflowState.availableHeight)); - - // if we have any padding then ignore it. It is inherited down to our scrolled frame - if (aReflowState.mComputedPadding.left != 0 || - aReflowState.mComputedPadding.right != 0 || - aReflowState.mComputedPadding.top != 0 || - aReflowState.mComputedPadding.bottom != 0) - { - nsHTMLReflowState newState(aReflowState); - - // get the padding to remove - nscoord pwidth = (newState.mComputedPadding.left + newState.mComputedPadding.right); - nscoord pheight = (newState.mComputedPadding.top + newState.mComputedPadding.bottom); - - // adjust our computed size to add in the padding we are removing. Make sure - // the computed size doesn't go negative or anything. - if (newState.mComputedWidth != NS_INTRINSICSIZE) - newState.mComputedWidth += pwidth; - - if (newState.mComputedHeight != NS_INTRINSICSIZE) - newState.mComputedHeight += pheight; - - // fix up the borderpadding - ((nsMargin&)newState.mComputedBorderPadding) -= newState.mComputedPadding; - - // remove the padding - ((nsMargin&)newState.mComputedPadding) = nsMargin(0,0,0,0); - - // reflow us again with the correct values. - return Reflow(aPresContext, aDesiredSize, newState, aStatus); - } - - mInner->mFirstPass = PR_TRUE; - - - // Handle Incremental Reflow - nsIFrame* incrementalChild = nsnull; - - /* - if (mInner->mNeverReflowed) { - // on the initial reflow see if we are the root box. - // the root box. - mInner->mIsRoot = PR_TRUE; - mInner->mNeverReflowed = PR_FALSE; - - // see if we are the root box - nsIFrame* parent = mParent; - while (parent) { - nsIBox* ibox = nsnull; - if (NS_SUCCEEDED(parent->QueryInterface(nsIBox::GetIID(), (void**)&ibox)) && ibox) { - mInner->mIsRoot = PR_FALSE; - break; - } - - parent->GetParent(&parent); - } - } - */ - - if ( aReflowState.reason == eReflowReason_Incremental ) { - - nsIReflowCommand::ReflowType reflowType; - aReflowState.reflowCommand->GetType(reflowType); - - // See if it's targeted at us - nsIFrame* targetFrame; - aReflowState.reflowCommand->GetTarget(targetFrame); - - if (this == targetFrame) { - // if we are the target see what the type was - // and generate a normal non incremental reflow. - switch (reflowType) { - - case nsIReflowCommand::StyleChanged: - { - nsHTMLReflowState newState(aReflowState); - newState.reason = eReflowReason_StyleChange; - newState.reflowCommand = nsnull; - return Reflow(aPresContext, aDesiredSize, newState, aStatus); - } - break; - - // if its a dirty type then reflow us with a dirty reflow - case nsIReflowCommand::ReflowDirty: - { - nsHTMLReflowState newState(aReflowState); - newState.reason = eReflowReason_Dirty; - newState.reflowCommand = nsnull; - return Reflow(aPresContext, aDesiredSize, newState, aStatus); - } - break; - - default: - NS_ASSERTION(PR_FALSE, "unexpected reflow command type"); - } - } - - /* - if (mInner->mIsRoot) - nsIBox::HandleRootBoxReflow(aPresContext, this, aReflowState); - - // then get the child we need to flow incrementally - aReflowState.reflowCommand->GetNext(incrementalChild); - */ - } - - - - - // next reflow the scrollbars so we will at least know their size. If they are bigger or smaller than - // we thought we will have to reflow the scroll area as well. - mInner->ReflowScrollbars( aPresContext, - aReflowState, - aStatus, - incrementalChild); - - // then reflow the scroll area. If it gets bigger it could signal the scrollbars need - // to be reflowed. - mInner->ReflowScrollArea( aPresContext, - aDesiredSize, - aReflowState, - aStatus, - incrementalChild); - - mInner->mFirstPass = PR_FALSE; - - // reflow the scrollbars again but only the ones that need it. - mInner->ReflowScrollbars( aPresContext, - aReflowState, - aStatus, - incrementalChild); - - // layout all the children. - mInner->LayoutChildren( aPresContext, - aDesiredSize, - aReflowState); - - - /* - if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) - ((nscoord&)aReflowState.mComputedWidth) -= (padding.left + padding.right); - - if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) - ((nscoord&)aReflowState.mComputedHeight) -= (padding.top + padding.bottom); - - ((nsMargin&)aReflowState.mComputedPadding) = padding; - ((nsMargin&)aReflowState.mComputedBorderPadding) += padding; -*/ - - NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS, - ("exit nsGfxScrollFrame::Reflow: status=%d width=%d height=%d", - aStatus, aDesiredSize.width, aDesiredSize.height)); - return NS_OK; -} - - -/* -NS_IMETHODIMP -nsGfxScrollFrame::Paint(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) -{ - - if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { - // Only paint the border and background if we're visible - const nsStyleDisplay* display = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - - if (display->mVisible) { - // Paint our border only (no background) - const nsStyleSpacing* spacing = (const nsStyleSpacing*) - mStyleContext->GetStyleData(eStyleStruct_Spacing); - - nsRect rect(0, 0, mRect.width, mRect.height); - nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, - aDirtyRect, rect, *spacing, mStyleContext, 0); - - - // paint the little square between the scrollbars - nsRect vbar; - nsRect hbar; - - // get the child's rect - mVScrollbarFrame->GetRect(vbar); - mVScrollbarFrame->GetRect(hbar); - - // get the margin - const nsStyleSpacing* s; - nsresult rv = mVScrollbarFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) s); - - nsMargin margin; - if (!s->GetMargin(margin)) - margin.SizeTo(0,0,0,0); - - vbar.Inflate(margin); - - - // get the margin - rv = mHScrollbarFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) s); - - if (!s->GetMargin(margin)) - margin.SizeTo(0,0,0,0); - - hbar.Inflate(margin); - - rect.SetRect(hbar.x + hbar.width, vbar.y + vbar.height, vbar.width, hbar.height); - - nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this, - aDirtyRect, rect, *myColor, *mySpacing, 0, 0); - - } - } else { - - // Paint our children - nsresult rv = nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, - aWhichLayer); - return rv; - } -} -*/ - NS_IMETHODIMP nsGfxScrollFrame::Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { - /* - if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { - // Only paint the border and background if we're visible - const nsStyleDisplay* display = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - - if (display->mVisible) { - // Paint our border only (no background) - const nsStyleSpacing* spacing = (const nsStyleSpacing*) - mStyleContext->GetStyleData(eStyleStruct_Spacing); - - nsRect rect(0, 0, mRect.width, mRect.height); - nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, - aDirtyRect, rect, *spacing, mStyleContext, 0); - nsCSSRendering::PaintOutline(aPresContext, aRenderingContext, this, - aDirtyRect, rect, *spacing, mStyleContext, 0); - } - } - */ - // Paint our children - return nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, + return nsBoxFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); } @@ -721,7 +395,10 @@ nsGfxScrollFrame::GetContentAndOffsetsFromPoint(nsIPresContext* aCX, if (! mInner) return NS_ERROR_NULL_POINTER; - return mInner->mScrollAreaFrame->GetContentAndOffsetsFromPoint(aCX, aPoint, aNewContent, aContentOffset, aContentOffsetEnd, aBeginFrameContent); + nsIFrame* frame = nsnull; + mInner->mScrollAreaBox->GetFrame(&frame); + + return frame->GetContentAndOffsetsFromPoint(aCX, aPoint, aNewContent, aContentOffset, aContentOffsetEnd, aBeginFrameContent); } PRIntn @@ -739,6 +416,117 @@ nsGfxScrollFrame::GetFrameType(nsIAtom** aType) const return NS_OK; } + +NS_IMETHODIMP +nsGfxScrollFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) +{ + PropagateDebug(aState); + + nsIFrame* frame = nsnull; + GetFrame(&frame); + + const nsStyleDisplay* styleDisplay = nsnull; + + frame->GetStyleData(eStyleStruct_Display, + (const nsStyleStruct*&)styleDisplay); + + nsresult rv = mInner->mScrollAreaBox->GetPrefSize(aState, aSize); + nsBox::AddMargin(mInner->mScrollAreaBox, aSize); + + if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || + styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) { + nsSize vSize(0,0); + mInner->mVScrollbarBox->GetPrefSize(aState, vSize); + nsBox::AddMargin(mInner->mVScrollbarBox, vSize); + + aSize.width += vSize.width; + } + + if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || + styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL) { + nsSize hSize(0,0); + mInner->mHScrollbarBox->GetPrefSize(aState, hSize); + nsBox::AddMargin(mInner->mHScrollbarBox, hSize); + + aSize.height += hSize.height; + } + + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSPrefSize(aState, this, aSize); + + return rv; +} + +NS_IMETHODIMP +nsGfxScrollFrame::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize) +{ + PropagateDebug(aState); + + nsIFrame* frame = nsnull; + GetFrame(&frame); + + const nsStyleDisplay* styleDisplay = nsnull; + + frame->GetStyleData(eStyleStruct_Display, + (const nsStyleStruct*&)styleDisplay); + + nsresult rv = mInner->mScrollAreaBox->GetMinSize(aState, aSize); + + if (mInner->mHasVerticalScrollbar || + styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || + styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) { + nsSize vSize(0,0); + mInner->mVScrollbarBox->GetMinSize(aState, vSize); + AddMargin(mInner->mVScrollbarBox, vSize); + aSize.width += vSize.width; + if (aSize.height < vSize.height) + aSize.height = vSize.height; + } + + if (mInner->mHasHorizontalScrollbar || + styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || + styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL) { + nsSize hSize(0,0); + mInner->mHScrollbarBox->GetMinSize(aState, hSize); + AddMargin(mInner->mHScrollbarBox, hSize); + aSize.height += hSize.height; + if (aSize.width < hSize.width) + aSize.width = hSize.width; + } + + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSMinSize(aState, this, aSize); + return rv; +} + +NS_IMETHODIMP +nsGfxScrollFrame::GetMaxSize(nsBoxLayoutState& aState, nsSize& aSize) +{ + PropagateDebug(aState); + + aSize.width = NS_INTRINSICSIZE; + aSize.height = NS_INTRINSICSIZE; + + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSMaxSize(aState, this, aSize); + return NS_OK; +} + +NS_IMETHODIMP_(nsrefcnt) +nsGfxScrollFrame::AddRef(void) +{ + return NS_OK; +} + +NS_IMETHODIMP_(nsrefcnt) +nsGfxScrollFrame::Release(void) +{ + return NS_OK; +} + #ifdef NS_DEBUG NS_IMETHODIMP nsGfxScrollFrame::GetFrameName(nsString& aResult) const @@ -747,36 +535,21 @@ nsGfxScrollFrame::GetFrameName(nsString& aResult) const } #endif -NS_IMETHODIMP -nsGfxScrollFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr) -{ - if (NULL == aInstancePtr) { - return NS_ERROR_NULL_POINTER; - } - - *aInstancePtr = NULL; - - if (aIID.Equals(kIAnonymousContentCreatorIID)) { - *aInstancePtr = (void*)(nsIAnonymousContentCreator*) this; - return NS_OK; - } else if (aIID.Equals(NS_GET_IID(nsIBox))) { - *aInstancePtr = (void*)(nsIBox*) this; - return NS_OK; - } else if (aIID.Equals(kIScrollableFrameIID)) { - *aInstancePtr = (void*)(nsIScrollableFrame*) this; - return NS_OK; - } +NS_INTERFACE_MAP_BEGIN(nsGfxScrollFrame) + NS_INTERFACE_MAP_ENTRY(nsIAnonymousContentCreator) +#ifdef NS_DEBUG + NS_INTERFACE_MAP_ENTRY(nsIFrameDebug) +#endif + NS_INTERFACE_MAP_ENTRY(nsIScrollableFrame) +NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame) - return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr); -} - //-------------------- Inner ---------------------- -nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsGfxScrollFrame* aOuter):mHScrollbarFrame(nsnull), - mVScrollbarFrame(nsnull), - mScrollAreaFrame(nsnull), +nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsGfxScrollFrame* aOuter):mHScrollbarBox(nsnull), + mVScrollbarBox(nsnull), + mScrollAreaBox(nsnull), mOnePixel(20), mHasVerticalScrollbar(PR_FALSE), mHasHorizontalScrollbar(PR_FALSE) @@ -803,8 +576,8 @@ nsGfxScrollFrameInner::ScrollPositionWillChange(nsIScrollableView* aScrollable, NS_IMETHODIMP nsGfxScrollFrameInner::ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY) { - SetAttribute(mVScrollbarFrame, nsXULAtoms::curpos, aY); - SetAttribute(mHScrollbarFrame, nsXULAtoms::curpos, aX); + SetAttribute(mVScrollbarBox, nsXULAtoms::curpos, aY); + SetAttribute(mHScrollbarBox, nsXULAtoms::curpos, aX); return NS_OK; } @@ -815,13 +588,19 @@ nsGfxScrollFrameInner::AttributeChanged(nsIDocument *aDocument, nsIAtom* aAttribute, PRInt32 aHint) { - if (mHScrollbarFrame && mVScrollbarFrame) + if (mHScrollbarBox && mVScrollbarBox) { + nsIFrame* hframe = nsnull; + mHScrollbarBox->GetFrame(&hframe); + + nsIFrame* vframe = nsnull; + mVScrollbarBox->GetFrame(&vframe); + nsCOMPtr vcontent; nsCOMPtr hcontent; - mHScrollbarFrame->GetContent(getter_AddRefs(hcontent)); - mVScrollbarFrame->GetContent(getter_AddRefs(vcontent)); + hframe->GetContent(getter_AddRefs(hcontent)); + vframe->GetContent(getter_AddRefs(vcontent)); if (hcontent.get() == aContent || vcontent.get() == aContent) { @@ -858,292 +637,29 @@ nsGfxScrollFrameInner::GetScrollableView(nsIPresContext* aPresContext) { nsIScrollableView* scrollingView; nsIView* view; - mScrollAreaFrame->GetView(aPresContext, &view); + nsIFrame* frame = nsnull; + mScrollAreaBox->GetFrame(&frame); + frame->GetView(aPresContext, &view); nsresult result = view->QueryInterface(kScrollViewIID, (void**)&scrollingView); NS_ASSERTION(NS_SUCCEEDED(result), "assertion gfx scrollframe does not contain a scrollframe"); return scrollingView; } void -nsGfxScrollFrameInner::GetScrolledContentSize(nsIPresContext* aPresContext, nsSize& aSize) +nsGfxScrollFrameInner::GetScrolledContentSize(nsSize& aSize) { // get the ara frame is the scrollarea - nsIFrame* child = nsnull; - mScrollAreaFrame->FirstChild(aPresContext, nsnull, &child); + nsIBox* child = nsnull; + mScrollAreaBox->GetChildBox(&child); nsRect rect(0,0,0,0); - child->GetRect(rect); + child->GetBounds(rect); + aSize.width = rect.width; aSize.height = rect.height; -} - - -nsresult -nsGfxScrollFrameInner::SetFrameSize(nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsSize aSize) - -{ - // get the margin - const nsStyleSpacing* spacing; - nsresult rv = aFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get spacing"); - if (NS_FAILED(rv)) - return rv; - - nsMargin margin; - if (!spacing->GetMargin(margin)) - margin.SizeTo(0,0,0,0); - - // add in the margin - aSize.width -= margin.left + margin.right; - aSize.height -= margin.top + margin.bottom; - - aFrame->SizeTo(aPresContext, aSize.width, aSize.height); - - return NS_OK; -} - - -nsresult -nsGfxScrollFrameInner::GetFrameSize( nsIFrame* aFrame, - nsSize& aSize) - -{ - // get the child's rect - aFrame->GetSize(aSize); - - // get the margin - const nsStyleSpacing* spacing; - nsresult rv = aFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get spacing"); - if (NS_FAILED(rv)) - return rv; - - nsMargin margin; - if (!spacing->GetMargin(margin)) - margin.SizeTo(0,0,0,0); - - // add in the margin - aSize.width += margin.left + margin.right; - aSize.height += margin.top + margin.bottom; - - return NS_OK; -} - - -// Returns the width of the vertical scrollbar and the height of -// the horizontal scrollbar in twips -void -nsGfxScrollFrameInner::GetScrollbarDimensions(nsIPresContext* aPresContext, - nsSize& aSbSize) -{ - - // if we are using - nsRect rect(0,0,0,0); - mHScrollbarFrame->GetRect(rect); - aSbSize.height = rect.height; - - rect.SetRect(0,0,0,0); - mVScrollbarFrame->GetRect(rect); - aSbSize.width = rect.width; - return; -} - - -// Calculates the size of the scroll area. This is the area inside of the -// border edge and inside of any vertical and horizontal scrollbar -// Also returns whether space was reserved for the vertical scrollbar. -nsresult -nsGfxScrollFrameInner::CalculateScrollAreaSize(nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - const nsSize& aSbSize, - nsSize& aScrollAreaSize) -{ - aScrollAreaSize.width = aReflowState.mComputedWidth; - aScrollAreaSize.height = aReflowState.mComputedHeight; - - if (aScrollAreaSize.width != NS_INTRINSICSIZE) { - aScrollAreaSize.width -= aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; - if (aScrollAreaSize.width < 0) - aScrollAreaSize.width = 0; - } - - if (aScrollAreaSize.height != NS_INTRINSICSIZE) { - aScrollAreaSize.height -= aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; - if (aScrollAreaSize.height < 0) - aScrollAreaSize.height = 0; - - } - - // get the current state - PRBool vert = mHasVerticalScrollbar; - PRBool horiz = mHasHorizontalScrollbar; - - // reset everyting - mHasVerticalScrollbar = PR_FALSE; - mHasHorizontalScrollbar = PR_FALSE; - - if (aReflowState.mStyleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL) - { - vert = PR_TRUE; - horiz = PR_TRUE; - } - else if (aReflowState.mStyleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_NONE) - { - vert = PR_FALSE; - horiz = PR_FALSE; - } - else if (aReflowState.mStyleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) - { - vert = PR_TRUE; - horiz = PR_FALSE; - } - else if (aReflowState.mStyleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL) - { - vert = PR_FALSE; - horiz = PR_TRUE; - } - - // add in the scrollbars. - if (horiz) - AddHorizontalScrollbar(aSbSize, aScrollAreaSize); - - if (vert) - AddVerticalScrollbar(aSbSize, aScrollAreaSize); - - - - return NS_OK; -} - -// Calculate the total amount of space needed for the child frame, -// including its child frames that stick outside its bounds and any -// absolutely positioned child frames. -// Updates the width/height members of the reflow metrics -nsresult -nsGfxScrollFrameInner::CalculateChildTotalSize(nsIFrame* aKidFrame, - nsHTMLReflowMetrics& aKidReflowMetrics) -{ - // If the frame has child frames that stick outside its bounds, then take - // them into account, too - nsFrameState kidState; - aKidFrame->GetFrameState(&kidState); - if (NS_FRAME_OUTSIDE_CHILDREN & kidState) { - aKidReflowMetrics.width = aKidReflowMetrics.mOverflowArea.width; - aKidReflowMetrics.height = aKidReflowMetrics.mOverflowArea.height; - } - - return NS_OK; -} - -void -nsGfxScrollFrameInner::SetScrollbarVisibility(nsIFrame* aScrollbar, PRBool aVisible) -{ - nsAutoString oldStyle = ""; - nsCOMPtr child; - aScrollbar->GetContent(getter_AddRefs(child)); - child->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, oldStyle); - - nsAutoString newStyle; - if (aVisible) - newStyle = ""; - else - newStyle = "hidden"; - - if (oldStyle != newStyle) - child->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, newStyle, PR_TRUE); -} - - -/** - * Reflows the visible scrollbars to fit in our content area. If the scrollbars change size - * Signal that the content area needs to be reflowed to accomidate the new size. This can - * happend if a css rule like :hover causes the scrollbar to get bigger. - */ -void -nsGfxScrollFrameInner::ReflowScrollbars( nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame*& aIncrementalChild) -{ - // if we have gfx scrollbars reflow them. If they changed size then signal that - // we need to reflow the content area. This could happen if there is a style rule set - // up on them that changed there size. Like an image on the thumb gets big. - - PRBool resized = PR_TRUE; - if (mHasHorizontalScrollbar || aReflowState.reason == eReflowReason_Initial) { - ReflowScrollbar(aPresContext, - aReflowState, - aStatus, - resized, - mHScrollbarFrame, - aIncrementalChild); - } - - if (mHasVerticalScrollbar || aReflowState.reason == eReflowReason_Initial) { - ReflowScrollbar(aPresContext, - aReflowState, - aStatus, - resized, - mVScrollbarFrame, - aIncrementalChild); - } - - SetScrollbarVisibility(mHScrollbarFrame, mHasHorizontalScrollbar); - SetScrollbarVisibility(mVScrollbarFrame, mHasVerticalScrollbar); -} - -void -nsGfxScrollFrameInner::ReflowScrollbar( nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - PRBool& aScrollbarResized, - nsIFrame* aScrollbarFrame, - nsIFrame*& aIncrementalChild) -{ - nsSize scrollArea; - GetFrameSize(mScrollAreaFrame, scrollArea); - - // add the padding to it. - scrollArea.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; - scrollArea.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; - - // is it the horizontal scrollbar? - if (aScrollbarFrame == mHScrollbarFrame) { - - // get the width to layout in - nscoord width = scrollArea.width; - - nsHTMLReflowMetrics desiredSize(nsnull); - - // reflow the frame - ReflowFrame(aPresContext, desiredSize, aReflowState, aStatus, mHScrollbarFrame, - nsSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE), - nsSize(width, NS_INTRINSICSIZE), - aScrollbarResized, - aIncrementalChild); - - } else if (aScrollbarFrame == mVScrollbarFrame) { - // is it the vertical scrollbar? - - // get the height to layout in - nscoord height = scrollArea.height; - - nsHTMLReflowMetrics desiredSize(nsnull); - - // reflow the frame - ReflowFrame(aPresContext, desiredSize, aReflowState, aStatus, mVScrollbarFrame, - nsSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE), - nsSize(NS_INTRINSICSIZE, height), - aScrollbarResized, - aIncrementalChild); - - } + nsBox::AddMargin(child, aSize); + nsBox::AddBorderAndPadding(mScrollAreaBox, aSize); + nsBox::AddInset(mScrollAreaBox, aSize); } void @@ -1169,525 +685,275 @@ nsGfxScrollFrameInner::AddRemoveScrollbar(PRBool& aHasScrollbar, nscoord& aSize, } void -nsGfxScrollFrameInner::AddHorizontalScrollbar(const nsSize& aSbSize, nsSize& aScrollAreaSize) +nsGfxScrollFrameInner::AddHorizontalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize) { AddRemoveScrollbar(mHasHorizontalScrollbar, aScrollAreaSize.height, aSbSize.height, PR_TRUE); } void -nsGfxScrollFrameInner::AddVerticalScrollbar(const nsSize& aSbSize, nsSize& aScrollAreaSize) +nsGfxScrollFrameInner::AddVerticalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize) { AddRemoveScrollbar(mHasVerticalScrollbar, aScrollAreaSize.width, aSbSize.width, PR_TRUE); } void -nsGfxScrollFrameInner::RemoveHorizontalScrollbar(const nsSize& aSbSize, nsSize& aScrollAreaSize) +nsGfxScrollFrameInner::RemoveHorizontalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize) { AddRemoveScrollbar(mHasHorizontalScrollbar, aScrollAreaSize.height, aSbSize.height, PR_FALSE); } void -nsGfxScrollFrameInner::RemoveVerticalScrollbar(const nsSize& aSbSize, nsSize& aScrollAreaSize) +nsGfxScrollFrameInner::RemoveVerticalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize) { AddRemoveScrollbar(mHasVerticalScrollbar, aScrollAreaSize.width, aSbSize.width, PR_FALSE); } -/** - * Give a computed and available sizes flows the child at that size. - * This is special because it takes into account margin and borderpadding. - * It also tells us if the child changed size or not. - * And finally it will handle the incremental reflow for us. If it reflowed the - * incrementalChild it will set it to nsnull - */ + nsresult -nsGfxScrollFrameInner::ReflowFrame( nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame* aFrame, - const nsSize& aAvailable, - const nsSize& aComputed, - PRBool& aResized, - nsIFrame*& aIncrementalChild) +nsGfxScrollFrameInner::LayoutBox(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect) { - PRBool needsReflow = PR_FALSE; - nsReflowReason reason = aReflowState.reason; - - nsFrameState childState; - aFrame->GetFrameState(&childState); - - if (childState & NS_FRAME_FIRST_REFLOW) { - if (reason != eReflowReason_Initial) - { - // if incremental then make sure we send a initial reflow first. - if (reason == eReflowReason_Incremental) { - nsHTMLReflowState state(aReflowState); - state.reason = eReflowReason_Initial; - state.reflowCommand = nsnull; - ReflowFrame( aPresContext, aDesiredSize, state, aStatus, aFrame, aAvailable, aComputed, aResized, aIncrementalChild); - } else { - // convert to initial if not incremental. - reason = eReflowReason_Initial; - } - - } - } else if (reason == eReflowReason_Initial) { - reason = eReflowReason_Resize; - } - - - switch(reason) - { - case eReflowReason_Incremental: { - // if incremental see if the next child in the chain is the child. If so then - // we will just let it go down. If not then convert it to a dirty. It will get picked - // up later. - nsIFrame* incrementalChild = nsnull; - aReflowState.reflowCommand->GetNext(incrementalChild, PR_FALSE); - if (incrementalChild == aFrame) { - needsReflow = PR_TRUE; - aReflowState.reflowCommand->GetNext(incrementalChild); - } else { - nsHTMLReflowState state(aReflowState); - state.reason = eReflowReason_Dirty; - return ReflowFrame( aPresContext, aDesiredSize, state, aStatus, aFrame, aAvailable, aComputed, aResized, aIncrementalChild); - } - - /* - if (aIncrementalChild == aFrame) { - needsReflow = PR_TRUE; - aIncrementalChild = nsnull; - } else { - reason = eReflowReason_Resize; - needsReflow = PR_FALSE; - } - */ - } break; - - // if its dirty then see if the child we want to reflow is dirty. If it is then - // mark it as needing to be reflowed. - case eReflowReason_Dirty: { - - // so look at the next child. If it is use convert back to incremental. - if (aReflowState.reflowCommand) { - nsIFrame* incrementalChild = nsnull; - aReflowState.reflowCommand->GetNext(incrementalChild, PR_FALSE); - if (incrementalChild == aFrame) { - nsHTMLReflowState state(aReflowState); - state.reason = eReflowReason_Incremental; - return ReflowFrame( aPresContext, aDesiredSize, state, aStatus, aFrame, aAvailable, aComputed, aResized, aIncrementalChild); - } - } - - // get the frame state to see if it needs reflow - needsReflow = (childState & NS_FRAME_IS_DIRTY) || (childState & NS_FRAME_HAS_DIRTY_CHILDREN); - - } break; - - // if the a resize reflow then it doesn't need to be reflowed. Only if the size is different - // from the new size would we actually do a reflow - case eReflowReason_Resize: - needsReflow = PR_FALSE; - break; - - case eReflowReason_Initial: - needsReflow = PR_TRUE; - break; - - - - default: - needsReflow = PR_TRUE; - - } - - nsSize currentSize; - GetFrameSize(aFrame, currentSize); - - // if we do not need reflow then - // see if the size it what we already want. If it is then we are done. - if (!needsReflow) { - // get the current size - - // if the size is not changing and the frame is not dirty then there - // is nothing to do. - if (currentSize.width == aComputed.width && currentSize.height == aComputed.height) { - aDesiredSize.width = currentSize.width; - aDesiredSize.height = currentSize.height; - return NS_OK; - } - } - - aDesiredSize.width = 0; - aDesiredSize.height = 0; - - nsHTMLReflowState childReflowState(aPresContext, aReflowState, - aFrame, aAvailable); - - childReflowState.reason = reason; - childReflowState.mComputedWidth = aComputed.width; - childReflowState.mComputedHeight = aComputed.height; - - // subtract out the childs margin and border if computed - const nsStyleSpacing* spacing; - nsresult rv = aFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get spacing"); - if (NS_FAILED(rv)) - return rv; - - // get the margin - nsMargin margin(0,0,0,0); - spacing->GetMargin(margin); - - // subtract out the border and padding - if (childReflowState.mComputedWidth != NS_INTRINSICSIZE) { - childReflowState.mComputedWidth -= childReflowState.mComputedBorderPadding.left + childReflowState.mComputedBorderPadding.right; - childReflowState.mComputedWidth -= margin.left + margin.right; - if (childReflowState.mComputedWidth < 0) - childReflowState.mComputedWidth = 0; - } - - if (childReflowState.mComputedHeight != NS_INTRINSICSIZE) { - childReflowState.mComputedHeight -= childReflowState.mComputedBorderPadding.top + childReflowState.mComputedBorderPadding.bottom; - childReflowState.mComputedWidth -= margin.top + margin.bottom; - if (childReflowState.mComputedHeight < 0) - childReflowState.mComputedHeight = 0; - } - - mOuter->ReflowChild(aFrame, aPresContext, aDesiredSize, childReflowState, - 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); - NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); - - NS_ASSERTION(aDesiredSize.width >= 0 && aDesiredSize.height >= 0,"Error child's size is less than 0!"); - - // if the frame size change then mark the flag - if (currentSize.width != aDesiredSize.width || currentSize.height != aDesiredSize.height) { - aFrame->SizeTo(aPresContext, aDesiredSize.width, aDesiredSize.height); - aResized = PR_TRUE; - } - aFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); - - // add the margin back in - aDesiredSize.width += margin.left + margin.right; - aDesiredSize.height += margin.top + margin.bottom; - - return NS_OK; + return mOuter->LayoutChildAt(aState, aBox, aRect); } + +NS_IMETHODIMP +nsGfxScrollFrame::Layout(nsBoxLayoutState& aState) +{ + PropagateDebug(aState); + nsresult rv = mInner->Layout(aState); + nsBox::Layout(aState); + return rv; +} + /** * Reflow the scroll area if it needs it and return its size. Also determine if the reflow will * cause any of the scrollbars to need to be reflowed. */ -void -nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame*& aIncrementalChild) +nsresult +nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) { - nsSize scrollAreaSize; + nsIFrame* frame = nsnull; + mOuter->GetFrame(&frame); - // get the current scrollarea size - nsSize oldScrollAreaSize; + const nsStyleDisplay* styleDisplay = nsnull; - GetFrameSize(mScrollAreaFrame, oldScrollAreaSize); + frame->GetStyleData(eStyleStruct_Display, + (const nsStyleStruct*&)styleDisplay); - /* - // add our padding - oldScrollAreaSize.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; - oldScrollAreaSize.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; - */ + + // get the content rect + nsRect clientRect(0,0,0,0); + mOuter->GetClientRect(clientRect); - // get the width of the vertical scrollbar and the height of the horizontal scrollbar - nsSize sbSize; - GetScrollbarDimensions(aPresContext, sbSize); + // get the preferred size of the scrollbars + nsSize hSize(0,0); + nsSize vSize(0,0); + mHScrollbarBox->GetPrefSize(aState, hSize); + mVScrollbarBox->GetPrefSize(aState, vSize); + nsSize hMinSize(0,0); + nsSize vMinSize(0,0); + mHScrollbarBox->GetMinSize(aState, hMinSize); + mVScrollbarBox->GetMinSize(aState, vMinSize); - // Compute the scroll area size (area inside of the border edge and inside - // of any vertical and horizontal scrollbars) - nsHTMLReflowMetrics scrollAreaDesiredSize(aDesiredSize.maxElementSize); + nsBox::AddMargin(mHScrollbarBox, hSize); + nsBox::AddMargin(mVScrollbarBox, vSize); + nsBox::AddMargin(mHScrollbarBox, hMinSize); + nsBox::AddMargin(mVScrollbarBox, vMinSize); - CalculateScrollAreaSize(aPresContext, aReflowState, sbSize, - scrollAreaSize); + // the scroll area size starts off as big as our content area + nsRect scrollAreaRect(clientRect); - // if the frame is not changing size and its not dirty then do nothing - //if (oldScrollAreaSize == scrollAreaSize && !IsDirty(mScrollAreaFrame)) - // return; + nsSize sbSize(vSize.width, hSize.height); - // -------- flow the scroll area ----------- - nsSize scrollAreaReflowSize(scrollAreaSize.width, scrollAreaSize.height); + // Look at our style do we always have vertical or horizontal scrollbars? + if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL) + mHasHorizontalScrollbar = PR_TRUE; + if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) + mHasVerticalScrollbar = PR_TRUE; - PRBool resized = PR_FALSE; - ReflowFrame(aPresContext, scrollAreaDesiredSize, aReflowState, aStatus, mScrollAreaFrame, - scrollAreaReflowSize, - scrollAreaReflowSize, - resized, - aIncrementalChild); - - // ------- set up max size ------- - if (nsnull != aDesiredSize.maxElementSize) { - *aDesiredSize.maxElementSize = *scrollAreaDesiredSize.maxElementSize; - mMaxElementSize = *aDesiredSize.maxElementSize; + // see if we currenly have a vertical or horizotal scrollbar and subtract them + // from the scroll area size. + if (mHasHorizontalScrollbar) { + if (scrollAreaRect.height - sbSize.height < 0) + { + mHasHorizontalScrollbar = PR_FALSE; + mHScrollbarBox->Collapse(aState); + } else { + scrollAreaRect.height -= sbSize.height; } + } - // make sure we take into account any children outside our bounds - CalculateChildTotalSize(mScrollAreaFrame, scrollAreaDesiredSize); + if (mHasVerticalScrollbar) { + if (scrollAreaRect.width - sbSize.width < 0) + { + mHasVerticalScrollbar = PR_FALSE; + mVScrollbarBox->Collapse(aState); + } else { + scrollAreaRect.width -= sbSize.width; + } + } + // layout our the scroll area + LayoutBox(aState, mScrollAreaBox, scrollAreaRect); + + // now look at the content area and see if we need scrollbars or not + PRBool needsLayout = PR_FALSE; + nsSize scrolledContentSize(0,0); - // its possible that we will have to do this twice. Its a special case - // when a the scrollarea is exactly the same height as its content but - // the contents width is greater. We will need a horizontal scrollbar - // but the size of the scrollbar will cause the scrollarea to be shorter - // than the content. So we will need a vertical scrollbar. But that could - // require us to squeeze the content. So we would have to reflow. Basically - // we have to start over. Thats why this loop is here. - for (int i=0; i < 1; i++) { + // if we have 'auto' scrollbars look at the vertical case + if (styleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLL + && styleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) { + // get the area frame is the scrollarea + GetScrolledContentSize(scrolledContentSize); - // if we are shrink wrapping the height. - if (NS_INTRINSICSIZE == scrollAreaSize.height) { - // the view port become the size that child requested. - scrollAreaSize.height = scrollAreaDesiredSize.height; - - // if we were auto and have a vertical scrollbar remove it because we - // can have whatever size we wanted. - if (aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLL - && aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) { - RemoveVerticalScrollbar(sbSize, scrollAreaSize); - } - } else { - // if we are not shrink wrapping - PRBool mustReflow = PR_FALSE; - - // if we have 'auto' scrollbars - if (aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLL - && aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) { - // get the ara frame is the scrollarea - nsSize size; - GetScrolledContentSize(aPresContext, size); - - // There are two cases to consider - if (size.height <= scrollAreaSize.height - || aReflowState.mStyleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL - || aReflowState.mStyleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_NONE) { - if (mHasVerticalScrollbar) { - // We left room for the vertical scrollbar, but it's not needed; - // remove it. - RemoveVerticalScrollbar(sbSize, scrollAreaSize); - mustReflow = PR_TRUE; - } - } else { - if (!mHasVerticalScrollbar) { - // We didn't leave room for the vertical scrollbar, but it turns - // out we needed it - AddVerticalScrollbar(sbSize, scrollAreaSize); - mustReflow = PR_TRUE; - } - } - - // Go ahead and reflow the child a second time if we added or removed the scrollbar - if (mustReflow) { - - // make sure we mark it as dirty so it will reflow again. - nsFrameState childState; - mScrollAreaFrame->GetFrameState(&childState); - childState |= NS_FRAME_IS_DIRTY; - mScrollAreaFrame->SetFrameState(childState); - - scrollAreaReflowSize.SizeTo(scrollAreaSize.width, scrollAreaSize.height); - - resized = PR_FALSE; - - ReflowFrame(aPresContext, scrollAreaDesiredSize, aReflowState, aStatus, mScrollAreaFrame, - scrollAreaReflowSize, - scrollAreaReflowSize, - resized, - aIncrementalChild); - - CalculateChildTotalSize(mScrollAreaFrame, scrollAreaDesiredSize); - - } + // There are two cases to consider + if (scrolledContentSize.height <= scrollAreaRect.height + || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL + || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_NONE) { + if (mHasVerticalScrollbar) { + // We left room for the vertical scrollbar, but it's not needed; + // remove it. + RemoveVerticalScrollbar(sbSize, scrollAreaRect); + needsLayout = PR_TRUE; + mVScrollbarBox->Collapse(aState); + } + } else { + if (!mHasVerticalScrollbar) { + // We didn't leave room for the vertical scrollbar, but it turns + // out we needed it + if (scrollAreaRect.width - sbSize.width >= 0) { + AddVerticalScrollbar(sbSize, scrollAreaRect); + mVScrollbarBox->UnCollapse(aState); + needsLayout = PR_TRUE; } } - + } - // if we are shrink wrapping the scroll area height becomes whatever the child wanted - if (NS_INTRINSICSIZE == scrollAreaSize.width) { - scrollAreaSize.width = scrollAreaDesiredSize.width; + // ok layout at the right size + if (needsLayout) { + nsBoxLayoutState resizeState(aState); + resizeState.SetLayoutReason(nsBoxLayoutState::Resize); + LayoutBox(resizeState, mScrollAreaBox, scrollAreaRect); + } + } - // if we have auto scrollbars the remove the horizontal scrollbar - if (aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLL - && aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL) { - RemoveHorizontalScrollbar(sbSize, scrollAreaSize); - } - } else { - // if scrollbars are auto - if ((NS_STYLE_OVERFLOW_SCROLL != aReflowState.mStyleDisplay->mOverflow) - && (NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL != aReflowState.mStyleDisplay->mOverflow)) - { - // get the ara frame is the scrollarea - nsSize size; - GetScrolledContentSize(aPresContext, size); + needsLayout = PR_FALSE; - // if the child is wider that the scroll area - // and we don't have a scrollbar add one. - if (size.width > scrollAreaSize.width - && aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL - && aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_NONE) { + // if scrollbars are auto look at the horizontal case + if ((NS_STYLE_OVERFLOW_SCROLL != styleDisplay->mOverflow) + && (NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL != styleDisplay->mOverflow)) + { + // get the area frame is the scrollarea + GetScrolledContentSize(scrolledContentSize); - if (!mHasHorizontalScrollbar) { - AddHorizontalScrollbar(sbSize, scrollAreaSize); + // if the child is wider that the scroll area + // and we don't have a scrollbar add one. + if (scrolledContentSize.width > scrollAreaRect.width + && styleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL + && styleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_NONE) { - // if we added a horizonal scrollbar and we did not have a vertical - // there is a chance that by adding the horizonal scrollbar we will - // suddenly need a vertical scrollbar. Is a special case but its - // important. - if (!mHasVerticalScrollbar && size.height > scrollAreaSize.height - sbSize.height) - continue; - } - } else { - // if the area is smaller or equal to and we have a scrollbar then - // remove it. - RemoveHorizontalScrollbar(sbSize, scrollAreaSize); - } - } - } - - // always break out of the loop. Only continue if another scrollbar was added. - break; + if (!mHasHorizontalScrollbar) { + if (scrollAreaRect.height - sbSize.height >= 0) { + AddHorizontalScrollbar(sbSize, scrollAreaRect); + mHScrollbarBox->UnCollapse(aState); + needsLayout = PR_TRUE; + } + // if we added a horizonal scrollbar and we did not have a vertical + // there is a chance that by adding the horizonal scrollbar we will + // suddenly need a vertical scrollbar. Is a special case but its + // important. + // if (!mHasVerticalScrollbar && scrolledContentSize.height > scrollAreaRect.height - sbSize.height) + // continue; } - - /* - // the old scroll area includes our margin. If our margin changed it will cause the - // scrollbars to be recalculated as well. - nsSize marginedScrollAreaSize = scrollAreaSize; - marginedScrollAreaSize.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; - marginedScrollAreaSize.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; - */ - - nsSize size; - GetScrolledContentSize(aPresContext, size); - - float p2t; - aPresContext->GetScaledPixelsToTwips(&p2t); - mOnePixel = NSIntPixelsToTwips(1, p2t); - const nsStyleFont* font; - mOuter->GetStyleData(eStyleStruct_Font, (const nsStyleStruct*&) font); - const nsFont& f = font->mFont; - nsCOMPtr fm; - aPresContext->GetMetricsFor(f, getter_AddRefs(fm)); - nscoord fontHeight = 1; - fm->GetHeight(fontHeight); - - nscoord maxX = size.width - scrollAreaSize.width; - nscoord maxY = size.height - scrollAreaSize.height; - - nsIScrollableView* scrollable = GetScrollableView(aPresContext); - scrollable->SetLineHeight(fontHeight); - - // set the scrollbars properties. Mark the scrollbars for reflow if there values change. - if (mHasVerticalScrollbar) { - SetAttribute(mVScrollbarFrame, nsXULAtoms::maxpos, maxY); - SetAttribute(mVScrollbarFrame, nsXULAtoms::pageincrement, nscoord(scrollAreaSize.height - fontHeight)); - SetAttribute(mVScrollbarFrame, nsXULAtoms::increment, fontHeight, PR_FALSE); - } - + } else { + // if the area is smaller or equal to and we have a scrollbar then + // remove it. if (mHasHorizontalScrollbar) { - SetAttribute(mHScrollbarFrame, nsXULAtoms::maxpos, maxX); - SetAttribute(mHScrollbarFrame, nsXULAtoms::pageincrement, nscoord(float(scrollAreaSize.width)*0.8)); - SetAttribute(mHScrollbarFrame, nsXULAtoms::increment, 10*mOnePixel, PR_FALSE); - } - // size the scroll area - // even if it is different from the old size. This is because ReflowFrame set the child's - // frame so we have to make sure our final size is scrollAreaSize + RemoveHorizontalScrollbar(sbSize, scrollAreaRect); + mHScrollbarBox->Collapse(aState); + needsLayout = PR_TRUE; + } + } + } - SetFrameSize(aPresContext, mScrollAreaFrame, scrollAreaSize); + // we only need to set the rect. The inner child stays the same size. + if (needsLayout) { + nsBoxLayoutState resizeState(aState); + resizeState.SetLayoutReason(nsBoxLayoutState::Resize); + LayoutBox(resizeState, mScrollAreaBox, scrollAreaRect); + + // mScrollAreaBox->SetBounds(aState, scrollAreaRect); + + } + + GetScrolledContentSize(scrolledContentSize); + + nsIPresContext* presContext = aState.GetPresContext(); + float p2t; + presContext->GetScaledPixelsToTwips(&p2t); + mOnePixel = NSIntPixelsToTwips(1, p2t); + const nsStyleFont* font; + mOuter->GetStyleData(eStyleStruct_Font, (const nsStyleStruct*&) font); + const nsFont& f = font->mFont; + nsCOMPtr fm; + presContext->GetMetricsFor(f, getter_AddRefs(fm)); + nscoord fontHeight = 1; + fm->GetHeight(fontHeight); + + nscoord maxX = scrolledContentSize.width - scrollAreaRect.width; + nscoord maxY = scrolledContentSize.height - scrollAreaRect.height; + + nsIScrollableView* scrollable = GetScrollableView(presContext); + scrollable->SetLineHeight(fontHeight); + + + // layout the vertical and horizontal scrollbars + + + // set the scrollbars properties. Mark the scrollbars for reflow if there values change. + if (mHasVerticalScrollbar) { + nsRect vRect(clientRect); + vRect.width = vSize.width; + if (mHasHorizontalScrollbar) + vRect.height -= hSize.height; + vRect.x = clientRect.x + clientRect.width - vSize.width; + vRect.y = clientRect.y; + + if (vMinSize.width > vRect.width || vMinSize.height > vRect.height) { + mVScrollbarBox->Collapse(aState); + } else { + SetAttribute(mVScrollbarBox, nsXULAtoms::maxpos, maxY); + SetAttribute(mVScrollbarBox, nsXULAtoms::pageincrement, nscoord(scrollAreaRect.height - fontHeight)); + SetAttribute(mVScrollbarBox, nsXULAtoms::increment, fontHeight, PR_FALSE); + + LayoutBox(aState, mVScrollbarBox, vRect); + } + } + + if (mHasHorizontalScrollbar) { + + nsRect hRect(clientRect); + hRect.height = hSize.height; + + if (mHasVerticalScrollbar) + hRect.width -= vSize.width; + + hRect.y = clientRect.y + clientRect.height - hSize.height; + hRect.x = clientRect.x; + + if (hMinSize.width > hRect.width || hMinSize.height > hRect.height) { + mHScrollbarBox->Collapse(aState); + } else { + SetAttribute(mHScrollbarBox, nsXULAtoms::maxpos, maxX); + SetAttribute(mHScrollbarBox, nsXULAtoms::pageincrement, nscoord(float(scrollAreaRect.width)*0.8)); + SetAttribute(mHScrollbarBox, nsXULAtoms::increment, 10*mOnePixel, PR_FALSE); + + LayoutBox(aState, mHScrollbarBox, hRect); + } + } + + return NS_OK; } - - -/** - * Places the scrollbars and scrollarea and returns the overall size - */ -void -nsGfxScrollFrameInner::LayoutChildren(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState) -{ - nsSize scrollAreaSize; - GetFrameSize(mScrollAreaFrame, scrollAreaSize); - - // add the padding to it. - scrollAreaSize.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; - scrollAreaSize.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; - - nsSize sbSize; - GetScrollbarDimensions(aPresContext, sbSize); - - const nsMargin& borderPadding = aReflowState.mComputedBorderPadding; - nsMargin border = borderPadding - aReflowState.mComputedPadding; - - // Place scroll area - nsIView* view; - mScrollAreaFrame->MoveTo(aPresContext, borderPadding.left, borderPadding.top); - mScrollAreaFrame->GetView(aPresContext, &view); - if (view) { - nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, mScrollAreaFrame, - view, nsnull); - } - - // place vertical scrollbar move by the border because the scrollbars are outside our padding - mVScrollbarFrame->MoveTo(aPresContext, border.left + scrollAreaSize.width, border.top); - mVScrollbarFrame->GetView(aPresContext, &view); - if (view) { - nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, mVScrollbarFrame, - view, nsnull); - } - - // place horizontal scrollbar - mHScrollbarFrame->MoveTo(aPresContext, border.left, border.top + scrollAreaSize.height); - mHScrollbarFrame->GetView(aPresContext, &view); - if (view) { - nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, mHScrollbarFrame, - view, nsnull); - } - - // Compute our desired size - // ---------- compute width ----------- - aDesiredSize.width = scrollAreaSize.width; - - // add border - aDesiredSize.width += border.left + border.right; - - // add scrollbar - if (mHasVerticalScrollbar) - aDesiredSize.width += sbSize.width; - - // ---------- compute height ----------- - - /* - // For the height if we're shrink wrapping then use whatever is smaller between - // the available height and the child's desired size; otherwise, use the scroll - // area size - if (NS_AUTOHEIGHT == aReflowState.mComputedHeight) { - aDesiredSize.height = PR_MIN(aReflowState.availableHeight, scrollAreaSize.height); - } else { - */ - - aDesiredSize.height = scrollAreaSize.height; - //} - - // add the scrollbar in - if (mHasHorizontalScrollbar) - aDesiredSize.height += sbSize.height; - - // add in our border - aDesiredSize.height += border.top + border.bottom; - - - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; -} - void nsGfxScrollFrameInner::ScrollbarChanged(nsIPresContext* aPresContext, nscoord aX, nscoord aY) { @@ -1708,18 +974,20 @@ nsGfxScrollFrameInner::~nsGfxScrollFrameInner() * Returns whether it actually needed to change the attribute */ PRBool -nsGfxScrollFrameInner::SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aSize, PRBool aReflow) +nsGfxScrollFrameInner::SetAttribute(nsIBox* aBox, nsIAtom* aAtom, nscoord aSize, PRBool aReflow) { // convert to pixels aSize /= mOnePixel; // only set the attribute if it changed. - PRInt32 current = GetIntegerAttribute(aFrame, aAtom, -1); + PRInt32 current = GetIntegerAttribute(aBox, aAtom, -1); if (current != aSize) { + nsIFrame* frame = nsnull; + aBox->GetFrame(&frame); nsCOMPtr content; - aFrame->GetContent(getter_AddRefs(content)); + frame->GetContent(getter_AddRefs(content)); char ch[100]; sprintf(ch,"%d", aSize); nsAutoString newValue(ch); @@ -1731,10 +999,13 @@ nsGfxScrollFrameInner::SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aS } PRInt32 -nsGfxScrollFrameInner::GetIntegerAttribute(nsIFrame* aFrame, nsIAtom* atom, PRInt32 defaultValue) +nsGfxScrollFrameInner::GetIntegerAttribute(nsIBox* aBox, nsIAtom* atom, PRInt32 defaultValue) { + nsIFrame* frame = nsnull; + aBox->GetFrame(&frame); + nsCOMPtr content; - aFrame->GetContent(getter_AddRefs(content)); + frame->GetContent(getter_AddRefs(content)); nsAutoString value; if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, atom, value)) @@ -1748,185 +1019,9 @@ nsGfxScrollFrameInner::GetIntegerAttribute(nsIFrame* aFrame, nsIAtom* atom, PRIn return defaultValue; } -NS_IMETHODIMP -nsGfxScrollFrame::InvalidateCache(nsIFrame* aChild) -{ - // we don't cache any layout information. So do nothing. - return NS_OK; -} - -NS_IMETHODIMP -nsGfxScrollFrame::SetDebug(nsIPresContext* aPresContext, PRBool aDebug) -{ - nsIFrame* kid = mFrames.FirstChild(); - while (nsnull != kid) { - nsIBox* ibox = nsnull; - if (NS_SUCCEEDED(kid->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) { - ibox->SetDebug(aPresContext, aDebug); - } - - kid->GetNextSibling(&kid); - } - - return NS_OK; -} - - -NS_IMETHODIMP -nsGfxScrollFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize) -{ - - nsIFrame* incrementalChild = nsnull; - - // if incremental pop off the child if it is ours and mark it dirty. - if (aReflowState.reason == eReflowReason_Incremental) { - aReflowState.reflowCommand->GetNext(incrementalChild, PR_FALSE); - if (incrementalChild == mInner->mScrollAreaFrame || - incrementalChild == mInner->mVScrollbarFrame || - incrementalChild == mInner->mHScrollbarFrame) { - aReflowState.reflowCommand->GetNext(incrementalChild); - // mark it dirty - nsFrameState childState; - incrementalChild->GetFrameState(&childState); - childState |= NS_FRAME_IS_DIRTY; - incrementalChild->SetFrameState(childState); - } - } - - aSize.Clear(); - - nsBoxInfo scrollAreaInfo, vboxInfo, hboxInfo; - nsCOMPtr ibox ( do_QueryInterface(mInner->mScrollAreaFrame) ); - if (ibox) ibox->GetBoxInfo(aPresContext, aReflowState, scrollAreaInfo); - - if (mInner->mHasVerticalScrollbar) { - nsCOMPtr vScrollbarBox ( do_QueryInterface(mInner->mVScrollbarFrame) ); - if (vScrollbarBox) vScrollbarBox->GetBoxInfo(aPresContext, aReflowState, vboxInfo); - } - - if (mInner->mHasHorizontalScrollbar) { - nsCOMPtr hScrollbarBox ( do_QueryInterface(mInner->mHScrollbarFrame) ); - if (hScrollbarBox) hScrollbarBox->GetBoxInfo(aPresContext, aReflowState, hboxInfo); - } - - aSize.prefSize.width += scrollAreaInfo.prefSize.width + vboxInfo.prefSize.width; - aSize.prefSize.height += scrollAreaInfo.prefSize.height + hboxInfo.prefSize.height; - - aSize.minSize.width += vboxInfo.minSize.width; - aSize.minSize.height += hboxInfo.minSize.height; - - if (scrollAreaInfo.maxSize.width != NS_INTRINSICSIZE && - vboxInfo.maxSize.width != NS_INTRINSICSIZE && - hboxInfo.maxSize.width != NS_INTRINSICSIZE) - { - aSize.maxSize.width += scrollAreaInfo.maxSize.width + vboxInfo.maxSize.width + hboxInfo.maxSize.width; - } - - if (scrollAreaInfo.maxSize.height != NS_INTRINSICSIZE && - vboxInfo.maxSize.height != NS_INTRINSICSIZE && - hboxInfo.maxSize.height != NS_INTRINSICSIZE) - { - aSize.maxSize.height += scrollAreaInfo.maxSize.height + vboxInfo.maxSize.height + hboxInfo.maxSize.height; - } - - return NS_OK; -} - -/* -void -nsBoxFrame::GetRedefinedMinPrefMax(nsIFrame* aFrame, nsBoxInfo& aSize) -{ - // add in the css min, max, pref - const nsStylePosition* position; - nsresult rv = aFrame->GetStyleData(eStyleStruct_Position, - (const nsStyleStruct*&) position); - - // see if the width or height was specifically set - if (position->mWidth.GetUnit() == eStyleUnit_Coord) { - aSize.prefSize.width = position->mWidth.GetCoordValue(); - } - - if (position->mHeight.GetUnit() == eStyleUnit_Coord) { - aSize.prefSize.height = position->mHeight.GetCoordValue(); - } - - // same for min size. Unfortunately min size is always set to 0. So for now - // we will assume 0 means not set. - if (position->mMinWidth.GetUnit() == eStyleUnit_Coord) { - nscoord min = position->mMinWidth.GetCoordValue(); - if (min != 0) - aSize.minSize.width = min; - } - - if (position->mMinHeight.GetUnit() == eStyleUnit_Coord) { - nscoord min = position->mMinHeight.GetCoordValue(); - if (min != 0) - aSize.minSize.height = min; - } - - // and max - if (position->mMaxWidth.GetUnit() == eStyleUnit_Coord) { - nscoord max = position->mMaxWidth.GetCoordValue(); - aSize.maxSize.width = max; - } - - if (position->mMaxHeight.GetUnit() == eStyleUnit_Coord) { - nscoord max = position->mMaxHeight.GetCoordValue(); - aSize.maxSize.height = max; - } - - // get the flexibility - nsCOMPtr content; - aFrame->GetContent(getter_AddRefs(content)); - - PRInt32 error; - nsAutoString value; - - if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::flex, value)) - { - value.Trim("%"); - // convert to a percent. - aSize.flex = value.ToFloat(&error)/float(100.0); - } -} -*/ - - -NS_IMETHODIMP -nsGfxScrollFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild) -{ - // if the frame is a vertical or horizontal scrollbar and we are about - // to reflow the scrollbars then don't propagate up - if (aChild == mInner->mHScrollbarFrame || aChild == mInner->mVScrollbarFrame) { - - // First pass means we will be checking to see if children should be reflowed - // if (mInner->mFirstPass) - // return NS_OK; - } - - // if we aren't dirty dirty us - if (!(mState & NS_FRAME_IS_DIRTY)) { - mState |= NS_FRAME_IS_DIRTY; - // if out parent is a box ask it to post a reflow for us and mark us as dirty - return mParent->ReflowDirtyChild(aPresShell,this); - } - - return NS_OK; -} - nsresult -nsGfxScrollFrameInner::GetContentOf(nsIFrame* aFrame, nsIContent** aContent) +nsGfxScrollFrame::GetContentOf(nsIContent** aContent) { - // If we don't have a content node find a parent that does. - while(aFrame != nsnull) { - aFrame->GetContent(aContent); - if (*aContent != nsnull) - return NS_OK; - - aFrame->GetParent(&aFrame); - } - - NS_ERROR("Can't find a parent with a content node"); + GetContent(aContent); return NS_OK; } - diff --git a/mozilla/layout/generic/nsGfxScrollFrame.h b/mozilla/layout/generic/nsGfxScrollFrame.h index 4e89b87eba8..c625d0aa3ed 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.h +++ b/mozilla/layout/generic/nsGfxScrollFrame.h @@ -19,12 +19,12 @@ * * Contributor(s): */ -#ifndef nsScrollFrame_h___ -#define nsScrollFrame_h___ +#ifndef nsGfxScrollFrame_h___ +#define nsGfxScrollFrame_h___ #include "nsHTMLContainerFrame.h" #include "nsIAnonymousContentCreator.h" -#include "nsIBox.h" +#include "nsBoxFrame.h" #include "nsIScrollableFrame.h" class nsISupportsArray; @@ -39,13 +39,12 @@ class nsGfxScrollFrameInner; * Scroll frames don't support incremental changes, i.e. you can't replace * or remove the scrolled frame */ -class nsGfxScrollFrame : public nsHTMLContainerFrame, - public nsIAnonymousContentCreator, - public nsIBox, +class nsGfxScrollFrame : public nsIAnonymousContentCreator, + public nsBoxFrame, public nsIScrollableFrame { public: friend nsresult NS_NewGfxScrollFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, - nsIDocument* aDocument); + nsIDocument* aDocument, PRBool aIsRoot); NS_IMETHOD Init(nsIPresContext* aPresContext, nsIContent* aContent, @@ -53,8 +52,6 @@ public: nsIStyleContext* aContext, nsIFrame* aPrevInFlow); - NS_IMETHOD SetDebug(nsIPresContext* aPresContext, PRBool aDebug); - virtual ~nsGfxScrollFrame(); @@ -85,13 +82,6 @@ public: nsIAtom* aListName, nsIFrame* aOldFrame); - NS_IMETHOD DidReflow(nsIPresContext* aPresContext, - nsDidReflowStatus aStatus); - - NS_IMETHOD Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); NS_IMETHOD Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -105,18 +95,18 @@ public: PRInt32& aContentOffsetEnd, PRBool& aBeginFrameContent); - NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild); - // nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aAnonymousItems); // nsIBox methods - NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); - NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); - NS_IMETHOD_(nsrefcnt) AddRef(void) { return NS_OK; } - NS_IMETHOD_(nsrefcnt) Release(void) { return NS_OK; } - NS_IMETHOD InvalidateCache(nsIFrame* aChild); + NS_DECL_ISUPPORTS + + NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); + NS_IMETHOD GetPadding(nsMargin& aPadding); // nsIScrollableFrame NS_IMETHOD SetScrolledFrame(nsIPresContext* aPresContext, nsIFrame *aScrolledFrame); @@ -138,8 +128,10 @@ public: NS_IMETHOD GetFrameName(nsString& aResult) const; #endif + virtual nsresult GetContentOf(nsIContent** aContent); + protected: - nsGfxScrollFrame(nsIDocument* aDocument); + nsGfxScrollFrame(nsIPresShell* aShell, nsIDocument* aDocument, PRBool aIsRoot); virtual PRIntn GetSkipSides() const; private: diff --git a/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp b/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp index 5c46f9f2ce6..9fa96f11156 100644 --- a/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp +++ b/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp @@ -49,6 +49,7 @@ #include "nsIScrollPositionListener.h" //#include "nsBoxFrame.h" #include "nsIElementFactory.h" +#include "nsBoxLayoutState.h" static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID); static NS_DEFINE_IID(kScrollingViewCID, NS_SCROLLING_VIEW_CID); @@ -133,98 +134,27 @@ public: NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument) { mDocument = nsnull; return NS_OK; } - PRBool SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aSize, PRBool aReflow=PR_TRUE); - PRInt32 GetIntegerAttribute(nsIFrame* aFrame, nsIAtom* atom, PRInt32 defaultValue); + PRBool SetAttribute(nsIBox* aBox, nsIAtom* aAtom, nscoord aSize, PRBool aReflow=PR_TRUE); + PRInt32 GetIntegerAttribute(nsIBox* aFrame, nsIAtom* atom, PRInt32 defaultValue); - nsresult CalculateChildTotalSize(nsIFrame* aKidFrame, - nsHTMLReflowMetrics& aKidReflowMetrics); - - nsresult GetFrameSize( nsIFrame* aFrame, - nsSize& aSize); - - nsresult SetFrameSize( nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsSize aSize); - - nsresult CalculateScrollAreaSize(nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - const nsSize& aSbSize, - nsSize& aScrollAreaSize); - - void SetScrollbarVisibility(nsIFrame* aScrollbar, PRBool aVisible); - - - - void ReflowScrollbars( nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame*& aIncrementalChild); - - void ReflowScrollbar( nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - PRBool& aScrollBarResized, - nsIFrame* aScrollBarFrame, - nsIFrame*& aIncrementalChild); - - - nsresult ReflowFrame( nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame* aFrame, - const nsSize& aAvailable, - const nsSize& aComputed, - PRBool& aResized, - nsIFrame*& aIncrementalChild); - - void ReflowScrollArea( nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame*& aIncrementalChild); - - void LayoutChildren(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState); - - void GetScrollbarDimensions(nsIPresContext* aPresContext, - nsSize& aSbSize); + nsresult Layout(nsBoxLayoutState& aState); + nsresult LayoutBox(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect); void AddRemoveScrollbar (PRBool& aHasScrollbar, nscoord& aSize, nscoord aSbSize, PRBool aAdd); - void AddHorizontalScrollbar (const nsSize& aSbSize, nsSize& aScrollAreaSize); - void AddVerticalScrollbar (const nsSize& aSbSize, nsSize& aScrollAreaSize); - void RemoveHorizontalScrollbar(const nsSize& aSbSize, nsSize& aScrollAreaSize); - void RemoveVerticalScrollbar (const nsSize& aSbSize, nsSize& aScrollAreaSize); - - /* - PRBool IsDirty(nsIFrame* aFrame) { - nsFrameState frameState; - aFrame->GetFrameState(&frameState); - if (frameState & NS_FRAME_IS_DIRTY) - return PR_TRUE; - else - return PR_FALSE; - } - - void MarkDirty(nsIFrame* aFrame) { - nsFrameState frameState; - aFrame->GetFrameState(&frameState); - frameState |= NS_FRAME_IS_DIRTY; - aFrame->SetFrameState(frameState); - } - */ + void AddHorizontalScrollbar (const nsSize& aSbSize, nsRect& aScrollAreaSize); + void AddVerticalScrollbar (const nsSize& aSbSize, nsRect& aScrollAreaSize); + void RemoveHorizontalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize); + void RemoveVerticalScrollbar (const nsSize& aSbSize, nsRect& aScrollAreaSize); nsIScrollableView* GetScrollableView(nsIPresContext* aPresContext); - void GetScrolledContentSize(nsIPresContext* aPresContext, nsSize& aSize); + void GetScrolledContentSize(nsSize& aSize); void ScrollbarChanged(nsIPresContext* aPresContext, nscoord aX, nscoord aY); - nsresult GetContentOf(nsIFrame* aFrame, nsIContent** aContent); - nsIFrame* mHScrollbarFrame; - nsIFrame* mVScrollbarFrame; - nsIFrame* mScrollAreaFrame; + nsIBox* mHScrollbarBox; + nsIBox* mVScrollbarBox; + nsIBox* mScrollAreaBox; nscoord mOnePixel; nsCOMPtr mDocument; nsGfxScrollFrame* mOuter; @@ -241,13 +171,13 @@ public: NS_IMPL_ISUPPORTS2(nsGfxScrollFrameInner, nsIDocumentObserver, nsIScrollPositionListener) nsresult -NS_NewGfxScrollFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, nsIDocument* aDocument) +NS_NewGfxScrollFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, nsIDocument* aDocument, PRBool aIsRoot) { NS_PRECONDITION(aNewFrame, "null OUT ptr"); if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } - nsGfxScrollFrame* it = new (aPresShell) nsGfxScrollFrame(aDocument); + nsGfxScrollFrame* it = new (aPresShell) nsGfxScrollFrame(aPresShell, aDocument, aIsRoot); if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } @@ -255,7 +185,7 @@ NS_NewGfxScrollFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, nsIDocument return NS_OK; } -nsGfxScrollFrame::nsGfxScrollFrame(nsIDocument* aDocument) +nsGfxScrollFrame::nsGfxScrollFrame(nsIPresShell* aShell, nsIDocument* aDocument, PRBool aIsRoot):nsBoxFrame(aShell, aIsRoot) { mInner = new nsGfxScrollFrameInner(this); mInner->AddRef(); @@ -263,6 +193,7 @@ nsGfxScrollFrame::nsGfxScrollFrame(nsIDocument* aDocument) mPresContext = nsnull; mInner->mIsRoot = PR_FALSE; mInner->mNeverReflowed = PR_TRUE; + SetLayoutManager(nsnull); } nsGfxScrollFrame::~nsGfxScrollFrame() @@ -278,9 +209,12 @@ nsGfxScrollFrame::~nsGfxScrollFrame() NS_IMETHODIMP nsGfxScrollFrame::SetScrolledFrame(nsIPresContext* aPresContext, nsIFrame *aScrolledFrame) { - mFrames.DestroyFrame(aPresContext, mInner->mScrollAreaFrame); - mInner->mScrollAreaFrame = aScrolledFrame; - mFrames.InsertFrame(nsnull, nsnull, mInner->mScrollAreaFrame); + NS_ERROR("Not implemented!"); + /* + mFrames.DestroyFrame(aPresContext, mInner->mScrollAreaBox); + mInner->mScrollAreaBox = aScrolledFrame; + mFrames.InsertFrame(nsnull, nsnull, mInner->mScrollAreaBox); + */ return NS_OK; } @@ -291,7 +225,10 @@ nsGfxScrollFrame::SetScrolledFrame(nsIPresContext* aPresContext, nsIFrame *aScro NS_IMETHODIMP nsGfxScrollFrame::GetScrolledFrame(nsIPresContext* aPresContext, nsIFrame *&aScrolledFrame) const { - return mInner->mScrollAreaFrame->FirstChild(aPresContext, nsnull, &aScrolledFrame); + nsIBox* child = nsnull; + mInner->mScrollAreaBox->GetChildBox(&child); + child->GetFrame(&aScrolledFrame); + return NS_OK; } /** @@ -302,10 +239,10 @@ nsGfxScrollFrame::GetClipSize(nsIPresContext* aPresContext, nscoord *aWidth, nscoord *aHeight) const { - nsSize size; - mInner->mScrollAreaFrame->GetSize(size); - *aWidth = size.width; - *aHeight = size.height; + nsRect rect; + mInner->mScrollAreaBox->GetBounds(rect); + *aWidth = rect.width; + *aHeight = rect.height; return NS_OK; } @@ -358,7 +295,7 @@ NS_IMETHODIMP nsGfxScrollFrame::Destroy(nsIPresContext* aPresContext) { - return nsHTMLContainerFrame::Destroy(aPresContext); + return nsBoxFrame::Destroy(aPresContext); } NS_IMETHODIMP @@ -369,14 +306,9 @@ nsGfxScrollFrame::Init(nsIPresContext* aPresContext, nsIFrame* aPrevInFlow) { mPresContext = aPresContext; - nsresult rv = nsHTMLContainerFrame::Init(aPresContext, aContent, + nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aStyleContext, aPrevInFlow); - -// nsCOMPtr content; -// mInner->GetContentOf(this, getter_AddRefs(content)); - -// content->GetDocument(*getter_AddRefs(mInner->mDocument)); mInner->mDocument->AddObserver(mInner); return rv; } @@ -386,16 +318,16 @@ nsGfxScrollFrame::SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList) { - nsresult rv = nsHTMLContainerFrame::SetInitialChildList(aPresContext, aListName, + nsresult rv = nsBoxFrame::SetInitialChildList(aPresContext, aListName, aChildList); // get scroll area - mInner->mScrollAreaFrame = mFrames.FirstChild(); - + GetChildBox(&mInner->mScrollAreaBox); + // horizontal scrollbar - mInner->mScrollAreaFrame->GetNextSibling(&mInner->mHScrollbarFrame); + mInner->mScrollAreaBox->GetNextBox(&mInner->mHScrollbarBox); // vertical scrollbar - mInner->mHScrollbarFrame->GetNextSibling(&mInner->mVScrollbarFrame); + mInner->mHScrollbarBox->GetNextBox(&mInner->mVScrollbarBox); // listen for scroll events. mInner->GetScrollableView(aPresContext)->AddScrollPositionListener(mInner); @@ -435,278 +367,20 @@ nsGfxScrollFrame::RemoveFrame(nsIPresContext* aPresContext, } NS_IMETHODIMP -nsGfxScrollFrame::DidReflow(nsIPresContext* aPresContext, - nsDidReflowStatus aStatus) +nsGfxScrollFrame::GetPadding(nsMargin& aMargin) { - // Let the default nsFrame implementation clear the state flags - // and size and position our view - nsresult rv = nsHTMLContainerFrame::DidReflow(aPresContext, aStatus); - - return rv; + aMargin.SizeTo(0,0,0,0); + return NS_OK; } - -NS_IMETHODIMP -nsGfxScrollFrame::Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) -{ - NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS, - ("enter nsGfxScrollFrame::Reflow: maxSize=%d,%d", - aReflowState.availableWidth, - aReflowState.availableHeight)); - - // if we have any padding then ignore it. It is inherited down to our scrolled frame - if (aReflowState.mComputedPadding.left != 0 || - aReflowState.mComputedPadding.right != 0 || - aReflowState.mComputedPadding.top != 0 || - aReflowState.mComputedPadding.bottom != 0) - { - nsHTMLReflowState newState(aReflowState); - - // get the padding to remove - nscoord pwidth = (newState.mComputedPadding.left + newState.mComputedPadding.right); - nscoord pheight = (newState.mComputedPadding.top + newState.mComputedPadding.bottom); - - // adjust our computed size to add in the padding we are removing. Make sure - // the computed size doesn't go negative or anything. - if (newState.mComputedWidth != NS_INTRINSICSIZE) - newState.mComputedWidth += pwidth; - - if (newState.mComputedHeight != NS_INTRINSICSIZE) - newState.mComputedHeight += pheight; - - // fix up the borderpadding - ((nsMargin&)newState.mComputedBorderPadding) -= newState.mComputedPadding; - - // remove the padding - ((nsMargin&)newState.mComputedPadding) = nsMargin(0,0,0,0); - - // reflow us again with the correct values. - return Reflow(aPresContext, aDesiredSize, newState, aStatus); - } - - mInner->mFirstPass = PR_TRUE; - - - // Handle Incremental Reflow - nsIFrame* incrementalChild = nsnull; - - /* - if (mInner->mNeverReflowed) { - // on the initial reflow see if we are the root box. - // the root box. - mInner->mIsRoot = PR_TRUE; - mInner->mNeverReflowed = PR_FALSE; - - // see if we are the root box - nsIFrame* parent = mParent; - while (parent) { - nsIBox* ibox = nsnull; - if (NS_SUCCEEDED(parent->QueryInterface(nsIBox::GetIID(), (void**)&ibox)) && ibox) { - mInner->mIsRoot = PR_FALSE; - break; - } - - parent->GetParent(&parent); - } - } - */ - - if ( aReflowState.reason == eReflowReason_Incremental ) { - - nsIReflowCommand::ReflowType reflowType; - aReflowState.reflowCommand->GetType(reflowType); - - // See if it's targeted at us - nsIFrame* targetFrame; - aReflowState.reflowCommand->GetTarget(targetFrame); - - if (this == targetFrame) { - // if we are the target see what the type was - // and generate a normal non incremental reflow. - switch (reflowType) { - - case nsIReflowCommand::StyleChanged: - { - nsHTMLReflowState newState(aReflowState); - newState.reason = eReflowReason_StyleChange; - newState.reflowCommand = nsnull; - return Reflow(aPresContext, aDesiredSize, newState, aStatus); - } - break; - - // if its a dirty type then reflow us with a dirty reflow - case nsIReflowCommand::ReflowDirty: - { - nsHTMLReflowState newState(aReflowState); - newState.reason = eReflowReason_Dirty; - newState.reflowCommand = nsnull; - return Reflow(aPresContext, aDesiredSize, newState, aStatus); - } - break; - - default: - NS_ASSERTION(PR_FALSE, "unexpected reflow command type"); - } - } - - /* - if (mInner->mIsRoot) - nsIBox::HandleRootBoxReflow(aPresContext, this, aReflowState); - - // then get the child we need to flow incrementally - aReflowState.reflowCommand->GetNext(incrementalChild); - */ - } - - - - - // next reflow the scrollbars so we will at least know their size. If they are bigger or smaller than - // we thought we will have to reflow the scroll area as well. - mInner->ReflowScrollbars( aPresContext, - aReflowState, - aStatus, - incrementalChild); - - // then reflow the scroll area. If it gets bigger it could signal the scrollbars need - // to be reflowed. - mInner->ReflowScrollArea( aPresContext, - aDesiredSize, - aReflowState, - aStatus, - incrementalChild); - - mInner->mFirstPass = PR_FALSE; - - // reflow the scrollbars again but only the ones that need it. - mInner->ReflowScrollbars( aPresContext, - aReflowState, - aStatus, - incrementalChild); - - // layout all the children. - mInner->LayoutChildren( aPresContext, - aDesiredSize, - aReflowState); - - - /* - if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) - ((nscoord&)aReflowState.mComputedWidth) -= (padding.left + padding.right); - - if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) - ((nscoord&)aReflowState.mComputedHeight) -= (padding.top + padding.bottom); - - ((nsMargin&)aReflowState.mComputedPadding) = padding; - ((nsMargin&)aReflowState.mComputedBorderPadding) += padding; -*/ - - NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS, - ("exit nsGfxScrollFrame::Reflow: status=%d width=%d height=%d", - aStatus, aDesiredSize.width, aDesiredSize.height)); - return NS_OK; -} - - -/* -NS_IMETHODIMP -nsGfxScrollFrame::Paint(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) -{ - - if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { - // Only paint the border and background if we're visible - const nsStyleDisplay* display = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - - if (display->mVisible) { - // Paint our border only (no background) - const nsStyleSpacing* spacing = (const nsStyleSpacing*) - mStyleContext->GetStyleData(eStyleStruct_Spacing); - - nsRect rect(0, 0, mRect.width, mRect.height); - nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, - aDirtyRect, rect, *spacing, mStyleContext, 0); - - - // paint the little square between the scrollbars - nsRect vbar; - nsRect hbar; - - // get the child's rect - mVScrollbarFrame->GetRect(vbar); - mVScrollbarFrame->GetRect(hbar); - - // get the margin - const nsStyleSpacing* s; - nsresult rv = mVScrollbarFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) s); - - nsMargin margin; - if (!s->GetMargin(margin)) - margin.SizeTo(0,0,0,0); - - vbar.Inflate(margin); - - - // get the margin - rv = mHScrollbarFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) s); - - if (!s->GetMargin(margin)) - margin.SizeTo(0,0,0,0); - - hbar.Inflate(margin); - - rect.SetRect(hbar.x + hbar.width, vbar.y + vbar.height, vbar.width, hbar.height); - - nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this, - aDirtyRect, rect, *myColor, *mySpacing, 0, 0); - - } - } else { - - // Paint our children - nsresult rv = nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, - aWhichLayer); - return rv; - } -} -*/ - NS_IMETHODIMP nsGfxScrollFrame::Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { - /* - if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { - // Only paint the border and background if we're visible - const nsStyleDisplay* display = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - - if (display->mVisible) { - // Paint our border only (no background) - const nsStyleSpacing* spacing = (const nsStyleSpacing*) - mStyleContext->GetStyleData(eStyleStruct_Spacing); - - nsRect rect(0, 0, mRect.width, mRect.height); - nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, - aDirtyRect, rect, *spacing, mStyleContext, 0); - nsCSSRendering::PaintOutline(aPresContext, aRenderingContext, this, - aDirtyRect, rect, *spacing, mStyleContext, 0); - } - } - */ - // Paint our children - return nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, + return nsBoxFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); } @@ -721,7 +395,10 @@ nsGfxScrollFrame::GetContentAndOffsetsFromPoint(nsIPresContext* aCX, if (! mInner) return NS_ERROR_NULL_POINTER; - return mInner->mScrollAreaFrame->GetContentAndOffsetsFromPoint(aCX, aPoint, aNewContent, aContentOffset, aContentOffsetEnd, aBeginFrameContent); + nsIFrame* frame = nsnull; + mInner->mScrollAreaBox->GetFrame(&frame); + + return frame->GetContentAndOffsetsFromPoint(aCX, aPoint, aNewContent, aContentOffset, aContentOffsetEnd, aBeginFrameContent); } PRIntn @@ -739,6 +416,117 @@ nsGfxScrollFrame::GetFrameType(nsIAtom** aType) const return NS_OK; } + +NS_IMETHODIMP +nsGfxScrollFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) +{ + PropagateDebug(aState); + + nsIFrame* frame = nsnull; + GetFrame(&frame); + + const nsStyleDisplay* styleDisplay = nsnull; + + frame->GetStyleData(eStyleStruct_Display, + (const nsStyleStruct*&)styleDisplay); + + nsresult rv = mInner->mScrollAreaBox->GetPrefSize(aState, aSize); + nsBox::AddMargin(mInner->mScrollAreaBox, aSize); + + if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || + styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) { + nsSize vSize(0,0); + mInner->mVScrollbarBox->GetPrefSize(aState, vSize); + nsBox::AddMargin(mInner->mVScrollbarBox, vSize); + + aSize.width += vSize.width; + } + + if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || + styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL) { + nsSize hSize(0,0); + mInner->mHScrollbarBox->GetPrefSize(aState, hSize); + nsBox::AddMargin(mInner->mHScrollbarBox, hSize); + + aSize.height += hSize.height; + } + + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSPrefSize(aState, this, aSize); + + return rv; +} + +NS_IMETHODIMP +nsGfxScrollFrame::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize) +{ + PropagateDebug(aState); + + nsIFrame* frame = nsnull; + GetFrame(&frame); + + const nsStyleDisplay* styleDisplay = nsnull; + + frame->GetStyleData(eStyleStruct_Display, + (const nsStyleStruct*&)styleDisplay); + + nsresult rv = mInner->mScrollAreaBox->GetMinSize(aState, aSize); + + if (mInner->mHasVerticalScrollbar || + styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || + styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) { + nsSize vSize(0,0); + mInner->mVScrollbarBox->GetMinSize(aState, vSize); + AddMargin(mInner->mVScrollbarBox, vSize); + aSize.width += vSize.width; + if (aSize.height < vSize.height) + aSize.height = vSize.height; + } + + if (mInner->mHasHorizontalScrollbar || + styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || + styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL) { + nsSize hSize(0,0); + mInner->mHScrollbarBox->GetMinSize(aState, hSize); + AddMargin(mInner->mHScrollbarBox, hSize); + aSize.height += hSize.height; + if (aSize.width < hSize.width) + aSize.width = hSize.width; + } + + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSMinSize(aState, this, aSize); + return rv; +} + +NS_IMETHODIMP +nsGfxScrollFrame::GetMaxSize(nsBoxLayoutState& aState, nsSize& aSize) +{ + PropagateDebug(aState); + + aSize.width = NS_INTRINSICSIZE; + aSize.height = NS_INTRINSICSIZE; + + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSMaxSize(aState, this, aSize); + return NS_OK; +} + +NS_IMETHODIMP_(nsrefcnt) +nsGfxScrollFrame::AddRef(void) +{ + return NS_OK; +} + +NS_IMETHODIMP_(nsrefcnt) +nsGfxScrollFrame::Release(void) +{ + return NS_OK; +} + #ifdef NS_DEBUG NS_IMETHODIMP nsGfxScrollFrame::GetFrameName(nsString& aResult) const @@ -747,36 +535,21 @@ nsGfxScrollFrame::GetFrameName(nsString& aResult) const } #endif -NS_IMETHODIMP -nsGfxScrollFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr) -{ - if (NULL == aInstancePtr) { - return NS_ERROR_NULL_POINTER; - } - - *aInstancePtr = NULL; - - if (aIID.Equals(kIAnonymousContentCreatorIID)) { - *aInstancePtr = (void*)(nsIAnonymousContentCreator*) this; - return NS_OK; - } else if (aIID.Equals(NS_GET_IID(nsIBox))) { - *aInstancePtr = (void*)(nsIBox*) this; - return NS_OK; - } else if (aIID.Equals(kIScrollableFrameIID)) { - *aInstancePtr = (void*)(nsIScrollableFrame*) this; - return NS_OK; - } +NS_INTERFACE_MAP_BEGIN(nsGfxScrollFrame) + NS_INTERFACE_MAP_ENTRY(nsIAnonymousContentCreator) +#ifdef NS_DEBUG + NS_INTERFACE_MAP_ENTRY(nsIFrameDebug) +#endif + NS_INTERFACE_MAP_ENTRY(nsIScrollableFrame) +NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame) - return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr); -} - //-------------------- Inner ---------------------- -nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsGfxScrollFrame* aOuter):mHScrollbarFrame(nsnull), - mVScrollbarFrame(nsnull), - mScrollAreaFrame(nsnull), +nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsGfxScrollFrame* aOuter):mHScrollbarBox(nsnull), + mVScrollbarBox(nsnull), + mScrollAreaBox(nsnull), mOnePixel(20), mHasVerticalScrollbar(PR_FALSE), mHasHorizontalScrollbar(PR_FALSE) @@ -803,8 +576,8 @@ nsGfxScrollFrameInner::ScrollPositionWillChange(nsIScrollableView* aScrollable, NS_IMETHODIMP nsGfxScrollFrameInner::ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY) { - SetAttribute(mVScrollbarFrame, nsXULAtoms::curpos, aY); - SetAttribute(mHScrollbarFrame, nsXULAtoms::curpos, aX); + SetAttribute(mVScrollbarBox, nsXULAtoms::curpos, aY); + SetAttribute(mHScrollbarBox, nsXULAtoms::curpos, aX); return NS_OK; } @@ -815,13 +588,19 @@ nsGfxScrollFrameInner::AttributeChanged(nsIDocument *aDocument, nsIAtom* aAttribute, PRInt32 aHint) { - if (mHScrollbarFrame && mVScrollbarFrame) + if (mHScrollbarBox && mVScrollbarBox) { + nsIFrame* hframe = nsnull; + mHScrollbarBox->GetFrame(&hframe); + + nsIFrame* vframe = nsnull; + mVScrollbarBox->GetFrame(&vframe); + nsCOMPtr vcontent; nsCOMPtr hcontent; - mHScrollbarFrame->GetContent(getter_AddRefs(hcontent)); - mVScrollbarFrame->GetContent(getter_AddRefs(vcontent)); + hframe->GetContent(getter_AddRefs(hcontent)); + vframe->GetContent(getter_AddRefs(vcontent)); if (hcontent.get() == aContent || vcontent.get() == aContent) { @@ -858,292 +637,29 @@ nsGfxScrollFrameInner::GetScrollableView(nsIPresContext* aPresContext) { nsIScrollableView* scrollingView; nsIView* view; - mScrollAreaFrame->GetView(aPresContext, &view); + nsIFrame* frame = nsnull; + mScrollAreaBox->GetFrame(&frame); + frame->GetView(aPresContext, &view); nsresult result = view->QueryInterface(kScrollViewIID, (void**)&scrollingView); NS_ASSERTION(NS_SUCCEEDED(result), "assertion gfx scrollframe does not contain a scrollframe"); return scrollingView; } void -nsGfxScrollFrameInner::GetScrolledContentSize(nsIPresContext* aPresContext, nsSize& aSize) +nsGfxScrollFrameInner::GetScrolledContentSize(nsSize& aSize) { // get the ara frame is the scrollarea - nsIFrame* child = nsnull; - mScrollAreaFrame->FirstChild(aPresContext, nsnull, &child); + nsIBox* child = nsnull; + mScrollAreaBox->GetChildBox(&child); nsRect rect(0,0,0,0); - child->GetRect(rect); + child->GetBounds(rect); + aSize.width = rect.width; aSize.height = rect.height; -} - - -nsresult -nsGfxScrollFrameInner::SetFrameSize(nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsSize aSize) - -{ - // get the margin - const nsStyleSpacing* spacing; - nsresult rv = aFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get spacing"); - if (NS_FAILED(rv)) - return rv; - - nsMargin margin; - if (!spacing->GetMargin(margin)) - margin.SizeTo(0,0,0,0); - - // add in the margin - aSize.width -= margin.left + margin.right; - aSize.height -= margin.top + margin.bottom; - - aFrame->SizeTo(aPresContext, aSize.width, aSize.height); - - return NS_OK; -} - - -nsresult -nsGfxScrollFrameInner::GetFrameSize( nsIFrame* aFrame, - nsSize& aSize) - -{ - // get the child's rect - aFrame->GetSize(aSize); - - // get the margin - const nsStyleSpacing* spacing; - nsresult rv = aFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get spacing"); - if (NS_FAILED(rv)) - return rv; - - nsMargin margin; - if (!spacing->GetMargin(margin)) - margin.SizeTo(0,0,0,0); - - // add in the margin - aSize.width += margin.left + margin.right; - aSize.height += margin.top + margin.bottom; - - return NS_OK; -} - - -// Returns the width of the vertical scrollbar and the height of -// the horizontal scrollbar in twips -void -nsGfxScrollFrameInner::GetScrollbarDimensions(nsIPresContext* aPresContext, - nsSize& aSbSize) -{ - - // if we are using - nsRect rect(0,0,0,0); - mHScrollbarFrame->GetRect(rect); - aSbSize.height = rect.height; - - rect.SetRect(0,0,0,0); - mVScrollbarFrame->GetRect(rect); - aSbSize.width = rect.width; - return; -} - - -// Calculates the size of the scroll area. This is the area inside of the -// border edge and inside of any vertical and horizontal scrollbar -// Also returns whether space was reserved for the vertical scrollbar. -nsresult -nsGfxScrollFrameInner::CalculateScrollAreaSize(nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - const nsSize& aSbSize, - nsSize& aScrollAreaSize) -{ - aScrollAreaSize.width = aReflowState.mComputedWidth; - aScrollAreaSize.height = aReflowState.mComputedHeight; - - if (aScrollAreaSize.width != NS_INTRINSICSIZE) { - aScrollAreaSize.width -= aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; - if (aScrollAreaSize.width < 0) - aScrollAreaSize.width = 0; - } - - if (aScrollAreaSize.height != NS_INTRINSICSIZE) { - aScrollAreaSize.height -= aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; - if (aScrollAreaSize.height < 0) - aScrollAreaSize.height = 0; - - } - - // get the current state - PRBool vert = mHasVerticalScrollbar; - PRBool horiz = mHasHorizontalScrollbar; - - // reset everyting - mHasVerticalScrollbar = PR_FALSE; - mHasHorizontalScrollbar = PR_FALSE; - - if (aReflowState.mStyleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL) - { - vert = PR_TRUE; - horiz = PR_TRUE; - } - else if (aReflowState.mStyleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_NONE) - { - vert = PR_FALSE; - horiz = PR_FALSE; - } - else if (aReflowState.mStyleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) - { - vert = PR_TRUE; - horiz = PR_FALSE; - } - else if (aReflowState.mStyleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL) - { - vert = PR_FALSE; - horiz = PR_TRUE; - } - - // add in the scrollbars. - if (horiz) - AddHorizontalScrollbar(aSbSize, aScrollAreaSize); - - if (vert) - AddVerticalScrollbar(aSbSize, aScrollAreaSize); - - - - return NS_OK; -} - -// Calculate the total amount of space needed for the child frame, -// including its child frames that stick outside its bounds and any -// absolutely positioned child frames. -// Updates the width/height members of the reflow metrics -nsresult -nsGfxScrollFrameInner::CalculateChildTotalSize(nsIFrame* aKidFrame, - nsHTMLReflowMetrics& aKidReflowMetrics) -{ - // If the frame has child frames that stick outside its bounds, then take - // them into account, too - nsFrameState kidState; - aKidFrame->GetFrameState(&kidState); - if (NS_FRAME_OUTSIDE_CHILDREN & kidState) { - aKidReflowMetrics.width = aKidReflowMetrics.mOverflowArea.width; - aKidReflowMetrics.height = aKidReflowMetrics.mOverflowArea.height; - } - - return NS_OK; -} - -void -nsGfxScrollFrameInner::SetScrollbarVisibility(nsIFrame* aScrollbar, PRBool aVisible) -{ - nsAutoString oldStyle = ""; - nsCOMPtr child; - aScrollbar->GetContent(getter_AddRefs(child)); - child->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, oldStyle); - - nsAutoString newStyle; - if (aVisible) - newStyle = ""; - else - newStyle = "hidden"; - - if (oldStyle != newStyle) - child->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, newStyle, PR_TRUE); -} - - -/** - * Reflows the visible scrollbars to fit in our content area. If the scrollbars change size - * Signal that the content area needs to be reflowed to accomidate the new size. This can - * happend if a css rule like :hover causes the scrollbar to get bigger. - */ -void -nsGfxScrollFrameInner::ReflowScrollbars( nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame*& aIncrementalChild) -{ - // if we have gfx scrollbars reflow them. If they changed size then signal that - // we need to reflow the content area. This could happen if there is a style rule set - // up on them that changed there size. Like an image on the thumb gets big. - - PRBool resized = PR_TRUE; - if (mHasHorizontalScrollbar || aReflowState.reason == eReflowReason_Initial) { - ReflowScrollbar(aPresContext, - aReflowState, - aStatus, - resized, - mHScrollbarFrame, - aIncrementalChild); - } - - if (mHasVerticalScrollbar || aReflowState.reason == eReflowReason_Initial) { - ReflowScrollbar(aPresContext, - aReflowState, - aStatus, - resized, - mVScrollbarFrame, - aIncrementalChild); - } - - SetScrollbarVisibility(mHScrollbarFrame, mHasHorizontalScrollbar); - SetScrollbarVisibility(mVScrollbarFrame, mHasVerticalScrollbar); -} - -void -nsGfxScrollFrameInner::ReflowScrollbar( nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - PRBool& aScrollbarResized, - nsIFrame* aScrollbarFrame, - nsIFrame*& aIncrementalChild) -{ - nsSize scrollArea; - GetFrameSize(mScrollAreaFrame, scrollArea); - - // add the padding to it. - scrollArea.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; - scrollArea.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; - - // is it the horizontal scrollbar? - if (aScrollbarFrame == mHScrollbarFrame) { - - // get the width to layout in - nscoord width = scrollArea.width; - - nsHTMLReflowMetrics desiredSize(nsnull); - - // reflow the frame - ReflowFrame(aPresContext, desiredSize, aReflowState, aStatus, mHScrollbarFrame, - nsSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE), - nsSize(width, NS_INTRINSICSIZE), - aScrollbarResized, - aIncrementalChild); - - } else if (aScrollbarFrame == mVScrollbarFrame) { - // is it the vertical scrollbar? - - // get the height to layout in - nscoord height = scrollArea.height; - - nsHTMLReflowMetrics desiredSize(nsnull); - - // reflow the frame - ReflowFrame(aPresContext, desiredSize, aReflowState, aStatus, mVScrollbarFrame, - nsSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE), - nsSize(NS_INTRINSICSIZE, height), - aScrollbarResized, - aIncrementalChild); - - } + nsBox::AddMargin(child, aSize); + nsBox::AddBorderAndPadding(mScrollAreaBox, aSize); + nsBox::AddInset(mScrollAreaBox, aSize); } void @@ -1169,525 +685,275 @@ nsGfxScrollFrameInner::AddRemoveScrollbar(PRBool& aHasScrollbar, nscoord& aSize, } void -nsGfxScrollFrameInner::AddHorizontalScrollbar(const nsSize& aSbSize, nsSize& aScrollAreaSize) +nsGfxScrollFrameInner::AddHorizontalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize) { AddRemoveScrollbar(mHasHorizontalScrollbar, aScrollAreaSize.height, aSbSize.height, PR_TRUE); } void -nsGfxScrollFrameInner::AddVerticalScrollbar(const nsSize& aSbSize, nsSize& aScrollAreaSize) +nsGfxScrollFrameInner::AddVerticalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize) { AddRemoveScrollbar(mHasVerticalScrollbar, aScrollAreaSize.width, aSbSize.width, PR_TRUE); } void -nsGfxScrollFrameInner::RemoveHorizontalScrollbar(const nsSize& aSbSize, nsSize& aScrollAreaSize) +nsGfxScrollFrameInner::RemoveHorizontalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize) { AddRemoveScrollbar(mHasHorizontalScrollbar, aScrollAreaSize.height, aSbSize.height, PR_FALSE); } void -nsGfxScrollFrameInner::RemoveVerticalScrollbar(const nsSize& aSbSize, nsSize& aScrollAreaSize) +nsGfxScrollFrameInner::RemoveVerticalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize) { AddRemoveScrollbar(mHasVerticalScrollbar, aScrollAreaSize.width, aSbSize.width, PR_FALSE); } -/** - * Give a computed and available sizes flows the child at that size. - * This is special because it takes into account margin and borderpadding. - * It also tells us if the child changed size or not. - * And finally it will handle the incremental reflow for us. If it reflowed the - * incrementalChild it will set it to nsnull - */ + nsresult -nsGfxScrollFrameInner::ReflowFrame( nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame* aFrame, - const nsSize& aAvailable, - const nsSize& aComputed, - PRBool& aResized, - nsIFrame*& aIncrementalChild) +nsGfxScrollFrameInner::LayoutBox(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect) { - PRBool needsReflow = PR_FALSE; - nsReflowReason reason = aReflowState.reason; - - nsFrameState childState; - aFrame->GetFrameState(&childState); - - if (childState & NS_FRAME_FIRST_REFLOW) { - if (reason != eReflowReason_Initial) - { - // if incremental then make sure we send a initial reflow first. - if (reason == eReflowReason_Incremental) { - nsHTMLReflowState state(aReflowState); - state.reason = eReflowReason_Initial; - state.reflowCommand = nsnull; - ReflowFrame( aPresContext, aDesiredSize, state, aStatus, aFrame, aAvailable, aComputed, aResized, aIncrementalChild); - } else { - // convert to initial if not incremental. - reason = eReflowReason_Initial; - } - - } - } else if (reason == eReflowReason_Initial) { - reason = eReflowReason_Resize; - } - - - switch(reason) - { - case eReflowReason_Incremental: { - // if incremental see if the next child in the chain is the child. If so then - // we will just let it go down. If not then convert it to a dirty. It will get picked - // up later. - nsIFrame* incrementalChild = nsnull; - aReflowState.reflowCommand->GetNext(incrementalChild, PR_FALSE); - if (incrementalChild == aFrame) { - needsReflow = PR_TRUE; - aReflowState.reflowCommand->GetNext(incrementalChild); - } else { - nsHTMLReflowState state(aReflowState); - state.reason = eReflowReason_Dirty; - return ReflowFrame( aPresContext, aDesiredSize, state, aStatus, aFrame, aAvailable, aComputed, aResized, aIncrementalChild); - } - - /* - if (aIncrementalChild == aFrame) { - needsReflow = PR_TRUE; - aIncrementalChild = nsnull; - } else { - reason = eReflowReason_Resize; - needsReflow = PR_FALSE; - } - */ - } break; - - // if its dirty then see if the child we want to reflow is dirty. If it is then - // mark it as needing to be reflowed. - case eReflowReason_Dirty: { - - // so look at the next child. If it is use convert back to incremental. - if (aReflowState.reflowCommand) { - nsIFrame* incrementalChild = nsnull; - aReflowState.reflowCommand->GetNext(incrementalChild, PR_FALSE); - if (incrementalChild == aFrame) { - nsHTMLReflowState state(aReflowState); - state.reason = eReflowReason_Incremental; - return ReflowFrame( aPresContext, aDesiredSize, state, aStatus, aFrame, aAvailable, aComputed, aResized, aIncrementalChild); - } - } - - // get the frame state to see if it needs reflow - needsReflow = (childState & NS_FRAME_IS_DIRTY) || (childState & NS_FRAME_HAS_DIRTY_CHILDREN); - - } break; - - // if the a resize reflow then it doesn't need to be reflowed. Only if the size is different - // from the new size would we actually do a reflow - case eReflowReason_Resize: - needsReflow = PR_FALSE; - break; - - case eReflowReason_Initial: - needsReflow = PR_TRUE; - break; - - - - default: - needsReflow = PR_TRUE; - - } - - nsSize currentSize; - GetFrameSize(aFrame, currentSize); - - // if we do not need reflow then - // see if the size it what we already want. If it is then we are done. - if (!needsReflow) { - // get the current size - - // if the size is not changing and the frame is not dirty then there - // is nothing to do. - if (currentSize.width == aComputed.width && currentSize.height == aComputed.height) { - aDesiredSize.width = currentSize.width; - aDesiredSize.height = currentSize.height; - return NS_OK; - } - } - - aDesiredSize.width = 0; - aDesiredSize.height = 0; - - nsHTMLReflowState childReflowState(aPresContext, aReflowState, - aFrame, aAvailable); - - childReflowState.reason = reason; - childReflowState.mComputedWidth = aComputed.width; - childReflowState.mComputedHeight = aComputed.height; - - // subtract out the childs margin and border if computed - const nsStyleSpacing* spacing; - nsresult rv = aFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get spacing"); - if (NS_FAILED(rv)) - return rv; - - // get the margin - nsMargin margin(0,0,0,0); - spacing->GetMargin(margin); - - // subtract out the border and padding - if (childReflowState.mComputedWidth != NS_INTRINSICSIZE) { - childReflowState.mComputedWidth -= childReflowState.mComputedBorderPadding.left + childReflowState.mComputedBorderPadding.right; - childReflowState.mComputedWidth -= margin.left + margin.right; - if (childReflowState.mComputedWidth < 0) - childReflowState.mComputedWidth = 0; - } - - if (childReflowState.mComputedHeight != NS_INTRINSICSIZE) { - childReflowState.mComputedHeight -= childReflowState.mComputedBorderPadding.top + childReflowState.mComputedBorderPadding.bottom; - childReflowState.mComputedWidth -= margin.top + margin.bottom; - if (childReflowState.mComputedHeight < 0) - childReflowState.mComputedHeight = 0; - } - - mOuter->ReflowChild(aFrame, aPresContext, aDesiredSize, childReflowState, - 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); - NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); - - NS_ASSERTION(aDesiredSize.width >= 0 && aDesiredSize.height >= 0,"Error child's size is less than 0!"); - - // if the frame size change then mark the flag - if (currentSize.width != aDesiredSize.width || currentSize.height != aDesiredSize.height) { - aFrame->SizeTo(aPresContext, aDesiredSize.width, aDesiredSize.height); - aResized = PR_TRUE; - } - aFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); - - // add the margin back in - aDesiredSize.width += margin.left + margin.right; - aDesiredSize.height += margin.top + margin.bottom; - - return NS_OK; + return mOuter->LayoutChildAt(aState, aBox, aRect); } + +NS_IMETHODIMP +nsGfxScrollFrame::Layout(nsBoxLayoutState& aState) +{ + PropagateDebug(aState); + nsresult rv = mInner->Layout(aState); + nsBox::Layout(aState); + return rv; +} + /** * Reflow the scroll area if it needs it and return its size. Also determine if the reflow will * cause any of the scrollbars to need to be reflowed. */ -void -nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame*& aIncrementalChild) +nsresult +nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) { - nsSize scrollAreaSize; + nsIFrame* frame = nsnull; + mOuter->GetFrame(&frame); - // get the current scrollarea size - nsSize oldScrollAreaSize; + const nsStyleDisplay* styleDisplay = nsnull; - GetFrameSize(mScrollAreaFrame, oldScrollAreaSize); + frame->GetStyleData(eStyleStruct_Display, + (const nsStyleStruct*&)styleDisplay); - /* - // add our padding - oldScrollAreaSize.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; - oldScrollAreaSize.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; - */ + + // get the content rect + nsRect clientRect(0,0,0,0); + mOuter->GetClientRect(clientRect); - // get the width of the vertical scrollbar and the height of the horizontal scrollbar - nsSize sbSize; - GetScrollbarDimensions(aPresContext, sbSize); + // get the preferred size of the scrollbars + nsSize hSize(0,0); + nsSize vSize(0,0); + mHScrollbarBox->GetPrefSize(aState, hSize); + mVScrollbarBox->GetPrefSize(aState, vSize); + nsSize hMinSize(0,0); + nsSize vMinSize(0,0); + mHScrollbarBox->GetMinSize(aState, hMinSize); + mVScrollbarBox->GetMinSize(aState, vMinSize); - // Compute the scroll area size (area inside of the border edge and inside - // of any vertical and horizontal scrollbars) - nsHTMLReflowMetrics scrollAreaDesiredSize(aDesiredSize.maxElementSize); + nsBox::AddMargin(mHScrollbarBox, hSize); + nsBox::AddMargin(mVScrollbarBox, vSize); + nsBox::AddMargin(mHScrollbarBox, hMinSize); + nsBox::AddMargin(mVScrollbarBox, vMinSize); - CalculateScrollAreaSize(aPresContext, aReflowState, sbSize, - scrollAreaSize); + // the scroll area size starts off as big as our content area + nsRect scrollAreaRect(clientRect); - // if the frame is not changing size and its not dirty then do nothing - //if (oldScrollAreaSize == scrollAreaSize && !IsDirty(mScrollAreaFrame)) - // return; + nsSize sbSize(vSize.width, hSize.height); - // -------- flow the scroll area ----------- - nsSize scrollAreaReflowSize(scrollAreaSize.width, scrollAreaSize.height); + // Look at our style do we always have vertical or horizontal scrollbars? + if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL) + mHasHorizontalScrollbar = PR_TRUE; + if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) + mHasVerticalScrollbar = PR_TRUE; - PRBool resized = PR_FALSE; - ReflowFrame(aPresContext, scrollAreaDesiredSize, aReflowState, aStatus, mScrollAreaFrame, - scrollAreaReflowSize, - scrollAreaReflowSize, - resized, - aIncrementalChild); - - // ------- set up max size ------- - if (nsnull != aDesiredSize.maxElementSize) { - *aDesiredSize.maxElementSize = *scrollAreaDesiredSize.maxElementSize; - mMaxElementSize = *aDesiredSize.maxElementSize; + // see if we currenly have a vertical or horizotal scrollbar and subtract them + // from the scroll area size. + if (mHasHorizontalScrollbar) { + if (scrollAreaRect.height - sbSize.height < 0) + { + mHasHorizontalScrollbar = PR_FALSE; + mHScrollbarBox->Collapse(aState); + } else { + scrollAreaRect.height -= sbSize.height; } + } - // make sure we take into account any children outside our bounds - CalculateChildTotalSize(mScrollAreaFrame, scrollAreaDesiredSize); + if (mHasVerticalScrollbar) { + if (scrollAreaRect.width - sbSize.width < 0) + { + mHasVerticalScrollbar = PR_FALSE; + mVScrollbarBox->Collapse(aState); + } else { + scrollAreaRect.width -= sbSize.width; + } + } + // layout our the scroll area + LayoutBox(aState, mScrollAreaBox, scrollAreaRect); + + // now look at the content area and see if we need scrollbars or not + PRBool needsLayout = PR_FALSE; + nsSize scrolledContentSize(0,0); - // its possible that we will have to do this twice. Its a special case - // when a the scrollarea is exactly the same height as its content but - // the contents width is greater. We will need a horizontal scrollbar - // but the size of the scrollbar will cause the scrollarea to be shorter - // than the content. So we will need a vertical scrollbar. But that could - // require us to squeeze the content. So we would have to reflow. Basically - // we have to start over. Thats why this loop is here. - for (int i=0; i < 1; i++) { + // if we have 'auto' scrollbars look at the vertical case + if (styleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLL + && styleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) { + // get the area frame is the scrollarea + GetScrolledContentSize(scrolledContentSize); - // if we are shrink wrapping the height. - if (NS_INTRINSICSIZE == scrollAreaSize.height) { - // the view port become the size that child requested. - scrollAreaSize.height = scrollAreaDesiredSize.height; - - // if we were auto and have a vertical scrollbar remove it because we - // can have whatever size we wanted. - if (aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLL - && aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) { - RemoveVerticalScrollbar(sbSize, scrollAreaSize); - } - } else { - // if we are not shrink wrapping - PRBool mustReflow = PR_FALSE; - - // if we have 'auto' scrollbars - if (aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLL - && aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) { - // get the ara frame is the scrollarea - nsSize size; - GetScrolledContentSize(aPresContext, size); - - // There are two cases to consider - if (size.height <= scrollAreaSize.height - || aReflowState.mStyleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL - || aReflowState.mStyleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_NONE) { - if (mHasVerticalScrollbar) { - // We left room for the vertical scrollbar, but it's not needed; - // remove it. - RemoveVerticalScrollbar(sbSize, scrollAreaSize); - mustReflow = PR_TRUE; - } - } else { - if (!mHasVerticalScrollbar) { - // We didn't leave room for the vertical scrollbar, but it turns - // out we needed it - AddVerticalScrollbar(sbSize, scrollAreaSize); - mustReflow = PR_TRUE; - } - } - - // Go ahead and reflow the child a second time if we added or removed the scrollbar - if (mustReflow) { - - // make sure we mark it as dirty so it will reflow again. - nsFrameState childState; - mScrollAreaFrame->GetFrameState(&childState); - childState |= NS_FRAME_IS_DIRTY; - mScrollAreaFrame->SetFrameState(childState); - - scrollAreaReflowSize.SizeTo(scrollAreaSize.width, scrollAreaSize.height); - - resized = PR_FALSE; - - ReflowFrame(aPresContext, scrollAreaDesiredSize, aReflowState, aStatus, mScrollAreaFrame, - scrollAreaReflowSize, - scrollAreaReflowSize, - resized, - aIncrementalChild); - - CalculateChildTotalSize(mScrollAreaFrame, scrollAreaDesiredSize); - - } + // There are two cases to consider + if (scrolledContentSize.height <= scrollAreaRect.height + || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL + || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_NONE) { + if (mHasVerticalScrollbar) { + // We left room for the vertical scrollbar, but it's not needed; + // remove it. + RemoveVerticalScrollbar(sbSize, scrollAreaRect); + needsLayout = PR_TRUE; + mVScrollbarBox->Collapse(aState); + } + } else { + if (!mHasVerticalScrollbar) { + // We didn't leave room for the vertical scrollbar, but it turns + // out we needed it + if (scrollAreaRect.width - sbSize.width >= 0) { + AddVerticalScrollbar(sbSize, scrollAreaRect); + mVScrollbarBox->UnCollapse(aState); + needsLayout = PR_TRUE; } } - + } - // if we are shrink wrapping the scroll area height becomes whatever the child wanted - if (NS_INTRINSICSIZE == scrollAreaSize.width) { - scrollAreaSize.width = scrollAreaDesiredSize.width; + // ok layout at the right size + if (needsLayout) { + nsBoxLayoutState resizeState(aState); + resizeState.SetLayoutReason(nsBoxLayoutState::Resize); + LayoutBox(resizeState, mScrollAreaBox, scrollAreaRect); + } + } - // if we have auto scrollbars the remove the horizontal scrollbar - if (aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLL - && aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL) { - RemoveHorizontalScrollbar(sbSize, scrollAreaSize); - } - } else { - // if scrollbars are auto - if ((NS_STYLE_OVERFLOW_SCROLL != aReflowState.mStyleDisplay->mOverflow) - && (NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL != aReflowState.mStyleDisplay->mOverflow)) - { - // get the ara frame is the scrollarea - nsSize size; - GetScrolledContentSize(aPresContext, size); + needsLayout = PR_FALSE; - // if the child is wider that the scroll area - // and we don't have a scrollbar add one. - if (size.width > scrollAreaSize.width - && aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL - && aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_NONE) { + // if scrollbars are auto look at the horizontal case + if ((NS_STYLE_OVERFLOW_SCROLL != styleDisplay->mOverflow) + && (NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL != styleDisplay->mOverflow)) + { + // get the area frame is the scrollarea + GetScrolledContentSize(scrolledContentSize); - if (!mHasHorizontalScrollbar) { - AddHorizontalScrollbar(sbSize, scrollAreaSize); + // if the child is wider that the scroll area + // and we don't have a scrollbar add one. + if (scrolledContentSize.width > scrollAreaRect.width + && styleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL + && styleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_NONE) { - // if we added a horizonal scrollbar and we did not have a vertical - // there is a chance that by adding the horizonal scrollbar we will - // suddenly need a vertical scrollbar. Is a special case but its - // important. - if (!mHasVerticalScrollbar && size.height > scrollAreaSize.height - sbSize.height) - continue; - } - } else { - // if the area is smaller or equal to and we have a scrollbar then - // remove it. - RemoveHorizontalScrollbar(sbSize, scrollAreaSize); - } - } - } - - // always break out of the loop. Only continue if another scrollbar was added. - break; + if (!mHasHorizontalScrollbar) { + if (scrollAreaRect.height - sbSize.height >= 0) { + AddHorizontalScrollbar(sbSize, scrollAreaRect); + mHScrollbarBox->UnCollapse(aState); + needsLayout = PR_TRUE; + } + // if we added a horizonal scrollbar and we did not have a vertical + // there is a chance that by adding the horizonal scrollbar we will + // suddenly need a vertical scrollbar. Is a special case but its + // important. + // if (!mHasVerticalScrollbar && scrolledContentSize.height > scrollAreaRect.height - sbSize.height) + // continue; } - - /* - // the old scroll area includes our margin. If our margin changed it will cause the - // scrollbars to be recalculated as well. - nsSize marginedScrollAreaSize = scrollAreaSize; - marginedScrollAreaSize.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; - marginedScrollAreaSize.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; - */ - - nsSize size; - GetScrolledContentSize(aPresContext, size); - - float p2t; - aPresContext->GetScaledPixelsToTwips(&p2t); - mOnePixel = NSIntPixelsToTwips(1, p2t); - const nsStyleFont* font; - mOuter->GetStyleData(eStyleStruct_Font, (const nsStyleStruct*&) font); - const nsFont& f = font->mFont; - nsCOMPtr fm; - aPresContext->GetMetricsFor(f, getter_AddRefs(fm)); - nscoord fontHeight = 1; - fm->GetHeight(fontHeight); - - nscoord maxX = size.width - scrollAreaSize.width; - nscoord maxY = size.height - scrollAreaSize.height; - - nsIScrollableView* scrollable = GetScrollableView(aPresContext); - scrollable->SetLineHeight(fontHeight); - - // set the scrollbars properties. Mark the scrollbars for reflow if there values change. - if (mHasVerticalScrollbar) { - SetAttribute(mVScrollbarFrame, nsXULAtoms::maxpos, maxY); - SetAttribute(mVScrollbarFrame, nsXULAtoms::pageincrement, nscoord(scrollAreaSize.height - fontHeight)); - SetAttribute(mVScrollbarFrame, nsXULAtoms::increment, fontHeight, PR_FALSE); - } - + } else { + // if the area is smaller or equal to and we have a scrollbar then + // remove it. if (mHasHorizontalScrollbar) { - SetAttribute(mHScrollbarFrame, nsXULAtoms::maxpos, maxX); - SetAttribute(mHScrollbarFrame, nsXULAtoms::pageincrement, nscoord(float(scrollAreaSize.width)*0.8)); - SetAttribute(mHScrollbarFrame, nsXULAtoms::increment, 10*mOnePixel, PR_FALSE); - } - // size the scroll area - // even if it is different from the old size. This is because ReflowFrame set the child's - // frame so we have to make sure our final size is scrollAreaSize + RemoveHorizontalScrollbar(sbSize, scrollAreaRect); + mHScrollbarBox->Collapse(aState); + needsLayout = PR_TRUE; + } + } + } - SetFrameSize(aPresContext, mScrollAreaFrame, scrollAreaSize); + // we only need to set the rect. The inner child stays the same size. + if (needsLayout) { + nsBoxLayoutState resizeState(aState); + resizeState.SetLayoutReason(nsBoxLayoutState::Resize); + LayoutBox(resizeState, mScrollAreaBox, scrollAreaRect); + + // mScrollAreaBox->SetBounds(aState, scrollAreaRect); + + } + + GetScrolledContentSize(scrolledContentSize); + + nsIPresContext* presContext = aState.GetPresContext(); + float p2t; + presContext->GetScaledPixelsToTwips(&p2t); + mOnePixel = NSIntPixelsToTwips(1, p2t); + const nsStyleFont* font; + mOuter->GetStyleData(eStyleStruct_Font, (const nsStyleStruct*&) font); + const nsFont& f = font->mFont; + nsCOMPtr fm; + presContext->GetMetricsFor(f, getter_AddRefs(fm)); + nscoord fontHeight = 1; + fm->GetHeight(fontHeight); + + nscoord maxX = scrolledContentSize.width - scrollAreaRect.width; + nscoord maxY = scrolledContentSize.height - scrollAreaRect.height; + + nsIScrollableView* scrollable = GetScrollableView(presContext); + scrollable->SetLineHeight(fontHeight); + + + // layout the vertical and horizontal scrollbars + + + // set the scrollbars properties. Mark the scrollbars for reflow if there values change. + if (mHasVerticalScrollbar) { + nsRect vRect(clientRect); + vRect.width = vSize.width; + if (mHasHorizontalScrollbar) + vRect.height -= hSize.height; + vRect.x = clientRect.x + clientRect.width - vSize.width; + vRect.y = clientRect.y; + + if (vMinSize.width > vRect.width || vMinSize.height > vRect.height) { + mVScrollbarBox->Collapse(aState); + } else { + SetAttribute(mVScrollbarBox, nsXULAtoms::maxpos, maxY); + SetAttribute(mVScrollbarBox, nsXULAtoms::pageincrement, nscoord(scrollAreaRect.height - fontHeight)); + SetAttribute(mVScrollbarBox, nsXULAtoms::increment, fontHeight, PR_FALSE); + + LayoutBox(aState, mVScrollbarBox, vRect); + } + } + + if (mHasHorizontalScrollbar) { + + nsRect hRect(clientRect); + hRect.height = hSize.height; + + if (mHasVerticalScrollbar) + hRect.width -= vSize.width; + + hRect.y = clientRect.y + clientRect.height - hSize.height; + hRect.x = clientRect.x; + + if (hMinSize.width > hRect.width || hMinSize.height > hRect.height) { + mHScrollbarBox->Collapse(aState); + } else { + SetAttribute(mHScrollbarBox, nsXULAtoms::maxpos, maxX); + SetAttribute(mHScrollbarBox, nsXULAtoms::pageincrement, nscoord(float(scrollAreaRect.width)*0.8)); + SetAttribute(mHScrollbarBox, nsXULAtoms::increment, 10*mOnePixel, PR_FALSE); + + LayoutBox(aState, mHScrollbarBox, hRect); + } + } + + return NS_OK; } - - -/** - * Places the scrollbars and scrollarea and returns the overall size - */ -void -nsGfxScrollFrameInner::LayoutChildren(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState) -{ - nsSize scrollAreaSize; - GetFrameSize(mScrollAreaFrame, scrollAreaSize); - - // add the padding to it. - scrollAreaSize.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; - scrollAreaSize.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; - - nsSize sbSize; - GetScrollbarDimensions(aPresContext, sbSize); - - const nsMargin& borderPadding = aReflowState.mComputedBorderPadding; - nsMargin border = borderPadding - aReflowState.mComputedPadding; - - // Place scroll area - nsIView* view; - mScrollAreaFrame->MoveTo(aPresContext, borderPadding.left, borderPadding.top); - mScrollAreaFrame->GetView(aPresContext, &view); - if (view) { - nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, mScrollAreaFrame, - view, nsnull); - } - - // place vertical scrollbar move by the border because the scrollbars are outside our padding - mVScrollbarFrame->MoveTo(aPresContext, border.left + scrollAreaSize.width, border.top); - mVScrollbarFrame->GetView(aPresContext, &view); - if (view) { - nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, mVScrollbarFrame, - view, nsnull); - } - - // place horizontal scrollbar - mHScrollbarFrame->MoveTo(aPresContext, border.left, border.top + scrollAreaSize.height); - mHScrollbarFrame->GetView(aPresContext, &view); - if (view) { - nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, mHScrollbarFrame, - view, nsnull); - } - - // Compute our desired size - // ---------- compute width ----------- - aDesiredSize.width = scrollAreaSize.width; - - // add border - aDesiredSize.width += border.left + border.right; - - // add scrollbar - if (mHasVerticalScrollbar) - aDesiredSize.width += sbSize.width; - - // ---------- compute height ----------- - - /* - // For the height if we're shrink wrapping then use whatever is smaller between - // the available height and the child's desired size; otherwise, use the scroll - // area size - if (NS_AUTOHEIGHT == aReflowState.mComputedHeight) { - aDesiredSize.height = PR_MIN(aReflowState.availableHeight, scrollAreaSize.height); - } else { - */ - - aDesiredSize.height = scrollAreaSize.height; - //} - - // add the scrollbar in - if (mHasHorizontalScrollbar) - aDesiredSize.height += sbSize.height; - - // add in our border - aDesiredSize.height += border.top + border.bottom; - - - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; -} - void nsGfxScrollFrameInner::ScrollbarChanged(nsIPresContext* aPresContext, nscoord aX, nscoord aY) { @@ -1708,18 +974,20 @@ nsGfxScrollFrameInner::~nsGfxScrollFrameInner() * Returns whether it actually needed to change the attribute */ PRBool -nsGfxScrollFrameInner::SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aSize, PRBool aReflow) +nsGfxScrollFrameInner::SetAttribute(nsIBox* aBox, nsIAtom* aAtom, nscoord aSize, PRBool aReflow) { // convert to pixels aSize /= mOnePixel; // only set the attribute if it changed. - PRInt32 current = GetIntegerAttribute(aFrame, aAtom, -1); + PRInt32 current = GetIntegerAttribute(aBox, aAtom, -1); if (current != aSize) { + nsIFrame* frame = nsnull; + aBox->GetFrame(&frame); nsCOMPtr content; - aFrame->GetContent(getter_AddRefs(content)); + frame->GetContent(getter_AddRefs(content)); char ch[100]; sprintf(ch,"%d", aSize); nsAutoString newValue(ch); @@ -1731,10 +999,13 @@ nsGfxScrollFrameInner::SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aS } PRInt32 -nsGfxScrollFrameInner::GetIntegerAttribute(nsIFrame* aFrame, nsIAtom* atom, PRInt32 defaultValue) +nsGfxScrollFrameInner::GetIntegerAttribute(nsIBox* aBox, nsIAtom* atom, PRInt32 defaultValue) { + nsIFrame* frame = nsnull; + aBox->GetFrame(&frame); + nsCOMPtr content; - aFrame->GetContent(getter_AddRefs(content)); + frame->GetContent(getter_AddRefs(content)); nsAutoString value; if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, atom, value)) @@ -1748,185 +1019,9 @@ nsGfxScrollFrameInner::GetIntegerAttribute(nsIFrame* aFrame, nsIAtom* atom, PRIn return defaultValue; } -NS_IMETHODIMP -nsGfxScrollFrame::InvalidateCache(nsIFrame* aChild) -{ - // we don't cache any layout information. So do nothing. - return NS_OK; -} - -NS_IMETHODIMP -nsGfxScrollFrame::SetDebug(nsIPresContext* aPresContext, PRBool aDebug) -{ - nsIFrame* kid = mFrames.FirstChild(); - while (nsnull != kid) { - nsIBox* ibox = nsnull; - if (NS_SUCCEEDED(kid->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) { - ibox->SetDebug(aPresContext, aDebug); - } - - kid->GetNextSibling(&kid); - } - - return NS_OK; -} - - -NS_IMETHODIMP -nsGfxScrollFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize) -{ - - nsIFrame* incrementalChild = nsnull; - - // if incremental pop off the child if it is ours and mark it dirty. - if (aReflowState.reason == eReflowReason_Incremental) { - aReflowState.reflowCommand->GetNext(incrementalChild, PR_FALSE); - if (incrementalChild == mInner->mScrollAreaFrame || - incrementalChild == mInner->mVScrollbarFrame || - incrementalChild == mInner->mHScrollbarFrame) { - aReflowState.reflowCommand->GetNext(incrementalChild); - // mark it dirty - nsFrameState childState; - incrementalChild->GetFrameState(&childState); - childState |= NS_FRAME_IS_DIRTY; - incrementalChild->SetFrameState(childState); - } - } - - aSize.Clear(); - - nsBoxInfo scrollAreaInfo, vboxInfo, hboxInfo; - nsCOMPtr ibox ( do_QueryInterface(mInner->mScrollAreaFrame) ); - if (ibox) ibox->GetBoxInfo(aPresContext, aReflowState, scrollAreaInfo); - - if (mInner->mHasVerticalScrollbar) { - nsCOMPtr vScrollbarBox ( do_QueryInterface(mInner->mVScrollbarFrame) ); - if (vScrollbarBox) vScrollbarBox->GetBoxInfo(aPresContext, aReflowState, vboxInfo); - } - - if (mInner->mHasHorizontalScrollbar) { - nsCOMPtr hScrollbarBox ( do_QueryInterface(mInner->mHScrollbarFrame) ); - if (hScrollbarBox) hScrollbarBox->GetBoxInfo(aPresContext, aReflowState, hboxInfo); - } - - aSize.prefSize.width += scrollAreaInfo.prefSize.width + vboxInfo.prefSize.width; - aSize.prefSize.height += scrollAreaInfo.prefSize.height + hboxInfo.prefSize.height; - - aSize.minSize.width += vboxInfo.minSize.width; - aSize.minSize.height += hboxInfo.minSize.height; - - if (scrollAreaInfo.maxSize.width != NS_INTRINSICSIZE && - vboxInfo.maxSize.width != NS_INTRINSICSIZE && - hboxInfo.maxSize.width != NS_INTRINSICSIZE) - { - aSize.maxSize.width += scrollAreaInfo.maxSize.width + vboxInfo.maxSize.width + hboxInfo.maxSize.width; - } - - if (scrollAreaInfo.maxSize.height != NS_INTRINSICSIZE && - vboxInfo.maxSize.height != NS_INTRINSICSIZE && - hboxInfo.maxSize.height != NS_INTRINSICSIZE) - { - aSize.maxSize.height += scrollAreaInfo.maxSize.height + vboxInfo.maxSize.height + hboxInfo.maxSize.height; - } - - return NS_OK; -} - -/* -void -nsBoxFrame::GetRedefinedMinPrefMax(nsIFrame* aFrame, nsBoxInfo& aSize) -{ - // add in the css min, max, pref - const nsStylePosition* position; - nsresult rv = aFrame->GetStyleData(eStyleStruct_Position, - (const nsStyleStruct*&) position); - - // see if the width or height was specifically set - if (position->mWidth.GetUnit() == eStyleUnit_Coord) { - aSize.prefSize.width = position->mWidth.GetCoordValue(); - } - - if (position->mHeight.GetUnit() == eStyleUnit_Coord) { - aSize.prefSize.height = position->mHeight.GetCoordValue(); - } - - // same for min size. Unfortunately min size is always set to 0. So for now - // we will assume 0 means not set. - if (position->mMinWidth.GetUnit() == eStyleUnit_Coord) { - nscoord min = position->mMinWidth.GetCoordValue(); - if (min != 0) - aSize.minSize.width = min; - } - - if (position->mMinHeight.GetUnit() == eStyleUnit_Coord) { - nscoord min = position->mMinHeight.GetCoordValue(); - if (min != 0) - aSize.minSize.height = min; - } - - // and max - if (position->mMaxWidth.GetUnit() == eStyleUnit_Coord) { - nscoord max = position->mMaxWidth.GetCoordValue(); - aSize.maxSize.width = max; - } - - if (position->mMaxHeight.GetUnit() == eStyleUnit_Coord) { - nscoord max = position->mMaxHeight.GetCoordValue(); - aSize.maxSize.height = max; - } - - // get the flexibility - nsCOMPtr content; - aFrame->GetContent(getter_AddRefs(content)); - - PRInt32 error; - nsAutoString value; - - if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::flex, value)) - { - value.Trim("%"); - // convert to a percent. - aSize.flex = value.ToFloat(&error)/float(100.0); - } -} -*/ - - -NS_IMETHODIMP -nsGfxScrollFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild) -{ - // if the frame is a vertical or horizontal scrollbar and we are about - // to reflow the scrollbars then don't propagate up - if (aChild == mInner->mHScrollbarFrame || aChild == mInner->mVScrollbarFrame) { - - // First pass means we will be checking to see if children should be reflowed - // if (mInner->mFirstPass) - // return NS_OK; - } - - // if we aren't dirty dirty us - if (!(mState & NS_FRAME_IS_DIRTY)) { - mState |= NS_FRAME_IS_DIRTY; - // if out parent is a box ask it to post a reflow for us and mark us as dirty - return mParent->ReflowDirtyChild(aPresShell,this); - } - - return NS_OK; -} - nsresult -nsGfxScrollFrameInner::GetContentOf(nsIFrame* aFrame, nsIContent** aContent) +nsGfxScrollFrame::GetContentOf(nsIContent** aContent) { - // If we don't have a content node find a parent that does. - while(aFrame != nsnull) { - aFrame->GetContent(aContent); - if (*aContent != nsnull) - return NS_OK; - - aFrame->GetParent(&aFrame); - } - - NS_ERROR("Can't find a parent with a content node"); + GetContent(aContent); return NS_OK; } - diff --git a/mozilla/layout/html/base/src/nsGfxScrollFrame.h b/mozilla/layout/html/base/src/nsGfxScrollFrame.h index 4e89b87eba8..c625d0aa3ed 100644 --- a/mozilla/layout/html/base/src/nsGfxScrollFrame.h +++ b/mozilla/layout/html/base/src/nsGfxScrollFrame.h @@ -19,12 +19,12 @@ * * Contributor(s): */ -#ifndef nsScrollFrame_h___ -#define nsScrollFrame_h___ +#ifndef nsGfxScrollFrame_h___ +#define nsGfxScrollFrame_h___ #include "nsHTMLContainerFrame.h" #include "nsIAnonymousContentCreator.h" -#include "nsIBox.h" +#include "nsBoxFrame.h" #include "nsIScrollableFrame.h" class nsISupportsArray; @@ -39,13 +39,12 @@ class nsGfxScrollFrameInner; * Scroll frames don't support incremental changes, i.e. you can't replace * or remove the scrolled frame */ -class nsGfxScrollFrame : public nsHTMLContainerFrame, - public nsIAnonymousContentCreator, - public nsIBox, +class nsGfxScrollFrame : public nsIAnonymousContentCreator, + public nsBoxFrame, public nsIScrollableFrame { public: friend nsresult NS_NewGfxScrollFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, - nsIDocument* aDocument); + nsIDocument* aDocument, PRBool aIsRoot); NS_IMETHOD Init(nsIPresContext* aPresContext, nsIContent* aContent, @@ -53,8 +52,6 @@ public: nsIStyleContext* aContext, nsIFrame* aPrevInFlow); - NS_IMETHOD SetDebug(nsIPresContext* aPresContext, PRBool aDebug); - virtual ~nsGfxScrollFrame(); @@ -85,13 +82,6 @@ public: nsIAtom* aListName, nsIFrame* aOldFrame); - NS_IMETHOD DidReflow(nsIPresContext* aPresContext, - nsDidReflowStatus aStatus); - - NS_IMETHOD Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); NS_IMETHOD Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -105,18 +95,18 @@ public: PRInt32& aContentOffsetEnd, PRBool& aBeginFrameContent); - NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild); - // nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aAnonymousItems); // nsIBox methods - NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); - NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); - NS_IMETHOD_(nsrefcnt) AddRef(void) { return NS_OK; } - NS_IMETHOD_(nsrefcnt) Release(void) { return NS_OK; } - NS_IMETHOD InvalidateCache(nsIFrame* aChild); + NS_DECL_ISUPPORTS + + NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); + NS_IMETHOD GetPadding(nsMargin& aPadding); // nsIScrollableFrame NS_IMETHOD SetScrolledFrame(nsIPresContext* aPresContext, nsIFrame *aScrolledFrame); @@ -138,8 +128,10 @@ public: NS_IMETHOD GetFrameName(nsString& aResult) const; #endif + virtual nsresult GetContentOf(nsIContent** aContent); + protected: - nsGfxScrollFrame(nsIDocument* aDocument); + nsGfxScrollFrame(nsIPresShell* aShell, nsIDocument* aDocument, PRBool aIsRoot); virtual PRIntn GetSkipSides() const; private: diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp index 9a3d576938a..92de48d7606 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -147,7 +147,7 @@ static NS_DEFINE_CID(kCXIFConverterCID, NS_XIFFORMATCONVERTER_CID); static PRInt32 gMaxRCProcessingTime = -1; // Largest chunk size we recycle -static const size_t gMaxRecycledSize = 300; +static const size_t gMaxRecycledSize = 400; // Flag for enabling/disabling asynchronous reflow // Set via the "layout.reflow.async" pref @@ -157,6 +157,173 @@ static PRBool gDoAsyncReflow = PR_FALSE; // Set via the "layout.reflow.async.afterDocLoad" pref static PRBool gDoAsyncReflowAfterDocLoad = PR_FALSE; +#define MARK_INCREMENT 50 +#define BLOCK_INCREMENT 2048 + +/**A block of memory that the stack will + * chop up and hand out + */ +struct StackBlock { + + // a block of memory + void* mBlock; + + // another block of memory that would only be created + // if our stack overflowed. Yes we have the ability + // to grow on a stack overflow + StackBlock* mNext; + StackBlock() + { + mBlock = new char*[BLOCK_INCREMENT]; + mNext = nsnull; + } + + ~StackBlock() + { + delete[] mBlock; + } +}; + +/* we hold an array of marks. A push pushes a mark on the stack + * a pop pops it off. + */ +struct StackMark { + // the block of memory we are currently handing out chunks of + StackBlock* mBlock; + + // our current position in the memory + size_t mPos; +}; + + +/* A stack arena allows a stack based interface to a block of memory. + * It should be used when you need to allocate some temporary memory that + * you will immediately return. + */ +class StackArena { +public: + StackArena(); + ~StackArena(); + + // Memory management functions + nsresult Allocate(size_t aSize, void** aResult); + nsresult Push(); + nsresult Pop(); + +private: + // our current position in memory + size_t mPos; + + // a list of memory block. Usually there is only one + // but if we overrun our stack size we can get more memory. + StackBlock* mBlocks; + + // the current block of memory we are passing our chucks of + StackBlock* mCurBlock; + + // our stack of mark where push has been called + StackMark* mMarks; + + // the current top of the the mark list + PRUint32 mStackTop; + + // the size of the mark array + PRUint32 mMarkLength; +}; + + + +StackArena::StackArena() +{ + // allocate the marks array + mMarkLength = MARK_INCREMENT; + mMarks = new StackMark[mMarkLength]; + + // allocate our stack memory + mBlocks = new StackBlock(); + mCurBlock = mBlocks; + + mStackTop = 0; + mPos = 0; +} + +StackArena::~StackArena() +{ + // free up our data + delete[] mMarks; + while(mBlocks) + { + StackBlock* toDelete = mBlocks; + mBlocks = mBlocks->mNext; + delete toDelete; + } +} + +nsresult +StackArena::Push() +{ + // if the we overrun our mark array. Resize it. + if (mStackTop + 1 >= mMarkLength) + { + StackMark* oldMarks = mMarks; + PRUint32 oldLength = mMarkLength; + mMarkLength += MARK_INCREMENT; + void* marks = 0; + mMarks = new StackMark[mMarkLength]; + nsCRT::memcpy(mMarks, oldMarks, sizeof(StackMark)*oldLength); + + delete[] oldMarks; + } + + // set a mark at the top + mMarks[mStackTop].mBlock = mCurBlock; + mMarks[mStackTop].mPos = mPos; + + mStackTop++; + + return NS_OK; +} + +nsresult +StackArena::Allocate(size_t aSize, void** aResult) +{ + NS_ASSERTION(mStackTop > 0, "Error allocate called before push!!!"); + + // make sure we are aligned. Beard said 8 was safer then 4. + // Round size to multiple of 8 + aSize = PR_ROUNDUP(aSize, 8); + + // if the size makes the stack overflow. Grab another block for the stack + if (mPos + aSize >= BLOCK_INCREMENT) + { + NS_ASSERTION(aSize <= BLOCK_INCREMENT,"Requested memory is greater that our block size!!"); + if (mCurBlock->mNext == nsnull) + mCurBlock->mNext = new StackBlock(); + + mCurBlock = mCurBlock->mNext; + mPos = 0; + } + + // return the chunk they need. + *aResult = ((char*)mCurBlock->mBlock) + mPos; + mPos += aSize; + + return NS_OK; +} + +nsresult +StackArena::Pop() +{ + // pop off the mark + NS_ASSERTION(mStackTop > 0, "Error Pop called 1 too many times"); + mStackTop--; + mCurBlock = mMarks[mStackTop].mBlock; + mPos = mMarks[mStackTop].mPos; + + return NS_OK; +} + + // Memory is allocated 4-byte aligned. We have recyclers for chunks up to // 200 bytes class FrameArena { @@ -190,7 +357,7 @@ FrameArena::~FrameArena() { // Free the arena in the pool and finish using it PL_FinishArenaPool(&mPool); -} +} nsresult FrameArena::AllocateFrame(size_t aSize, void** aResult) @@ -309,7 +476,12 @@ public: NS_IMETHOD AllocateFrame(size_t aSize, void** aResult); NS_IMETHOD FreeFrame(size_t aSize, void* aFreeChunk); - + + // Dynamic stack memory allocation + NS_IMETHOD PushStackMemory(); + NS_IMETHOD PopStackMemory(); + NS_IMETHOD AllocateStackMemory(size_t aSize, void** aResult); + NS_IMETHOD GetDocument(nsIDocument** aResult); NS_IMETHOD GetPresContext(nsIPresContext** aResult); NS_IMETHOD GetViewManager(nsIViewManager** aResult); @@ -522,6 +694,7 @@ protected: PRBool mPendingReflowEvent; nsCOMPtr mEventQueue; FrameArena mFrameArena; + StackArena* mStackArena; PRInt32 mAccumulatedReflowTime; // Time spent in reflow command processing so far PRPackedBool mDocumentIsLoading; // A flag that is true while the document is loading. PRPackedBool mBatchReflows; // When set to true, the pres shell batches reflow commands. @@ -540,6 +713,8 @@ protected: private: + void FreeDynamicStack(); + //helper funcs for disabing autoscrolling void DisableScrolling(){mScrollingEnabled = PR_FALSE;} void EnableScrolling(){mScrollingEnabled = PR_TRUE;} @@ -650,7 +825,7 @@ NS_NewPresShell(nsIPresShell** aInstancePtrResult) (void **) aInstancePtrResult); } -PresShell::PresShell() +PresShell::PresShell():mStackArena(nsnull) { NS_INIT_REFCNT(); mIsDestroying = PR_FALSE; @@ -718,6 +893,9 @@ PresShell::QueryInterface(const nsIID& aIID, void** aInstancePtr) PresShell::~PresShell() { + // if we allocated any stack memory free it. + FreeDynamicStack(); + mRefCnt = 99;/* XXX hack! get around re-entrancy bugs */ mIsDestroying = PR_TRUE; @@ -873,6 +1051,44 @@ PresShell::Init(nsIDocument* aDocument, return NS_OK; } + // Dynamic stack memory allocation +NS_IMETHODIMP +PresShell::PushStackMemory() +{ + if (nsnull == mStackArena) + mStackArena = new StackArena(); + + return mStackArena->Push(); +} + +NS_IMETHODIMP +PresShell::PopStackMemory() +{ + if (nsnull == mStackArena) + mStackArena = new StackArena(); + + return mStackArena->Pop(); +} + +NS_IMETHODIMP +PresShell::AllocateStackMemory(size_t aSize, void** aResult) +{ + if (nsnull == mStackArena) + mStackArena = new StackArena(); + + return mStackArena->Allocate(aSize, aResult); +} + +void +PresShell::FreeDynamicStack() +{ + if (mStackArena) { + delete mStackArena; + mStackArena = nsnull; + } +} + + NS_IMETHODIMP PresShell::FreeFrame(size_t aSize, void* aPtr) { @@ -2138,6 +2354,9 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible) MOZ_TIMER_DEBUGLOG(("Stop: Reflow: PresShell::ProcessReflowCommands(), this=%p\n", this)); MOZ_TIMER_STOP(mReflowWatch); + + // if we allocated any stack memory during reflow free it. + //FreeDynamicStack(); return NS_OK; } diff --git a/mozilla/layout/html/base/src/nsScrollPortFrame.cpp b/mozilla/layout/html/base/src/nsScrollPortFrame.cpp index d889af03c03..a10df708046 100644 --- a/mozilla/layout/html/base/src/nsScrollPortFrame.cpp +++ b/mozilla/layout/html/base/src/nsScrollPortFrame.cpp @@ -38,6 +38,8 @@ #include "nsScrollPortFrame.h" #include "nsLayoutAtoms.h" #include "nsIBox.h" +#include "nsBoxLayoutState.h" +#include "nsIBoxToBlockAdaptor.h" /* @@ -68,7 +70,7 @@ NS_NewScrollPortFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } - nsScrollPortFrame* it = new (aPresShell) nsScrollPortFrame; + nsScrollPortFrame* it = new (aPresShell) nsScrollPortFrame (aPresShell); if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } @@ -76,28 +78,8 @@ NS_NewScrollPortFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) return NS_OK; } -NS_IMETHODIMP -nsScrollPortFrame::SetDebug(nsIPresContext* aPresContext, PRBool aDebug) +nsScrollPortFrame::nsScrollPortFrame(nsIPresShell* aShell):nsBoxFrame(aShell) { - nsIFrame* kid = mFrames.FirstChild(); - while (nsnull != kid) { - nsIBox* ibox = nsnull; - if (NS_SUCCEEDED(kid->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) { - ibox->SetDebug(aPresContext, aDebug); - } - - kid->GetNextSibling(&kid); - } - - mNeedsRecalc = PR_TRUE; - - return NS_OK; -} - -nsScrollPortFrame::nsScrollPortFrame() -{ - //mIncremental = PR_FALSE; - mNeedsRecalc = PR_TRUE; } NS_IMETHODIMP @@ -107,7 +89,7 @@ nsScrollPortFrame::Init(nsIPresContext* aPresContext, nsIStyleContext* aStyleContext, nsIFrame* aPrevInFlow) { - nsresult rv = nsHTMLContainerFrame::Init(aPresContext, aContent, + nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aStyleContext, aPrevInFlow); @@ -121,7 +103,7 @@ nsScrollPortFrame::SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList) { - nsresult rv = nsHTMLContainerFrame::SetInitialChildList(aPresContext, aListName, + nsresult rv = nsBoxFrame::SetInitialChildList(aPresContext, aListName, aChildList); nsIFrame* frame = mFrames.FirstChild(); @@ -180,29 +162,6 @@ nsScrollPortFrame::RemoveFrame(nsIPresContext* aPresContext, return NS_ERROR_NOT_IMPLEMENTED; } -NS_IMETHODIMP -nsScrollPortFrame::DidReflow(nsIPresContext* aPresContext, - nsDidReflowStatus aStatus) -{ - nsresult rv = NS_OK; - - if (NS_FRAME_REFLOW_FINISHED == aStatus) { - // Let the default nsFrame implementation clear the state flags - // and size and position our view - rv = nsFrame::DidReflow(aPresContext, aStatus); - - // Have the scrolling view layout - nsIScrollableView* scrollingView; - nsIView* view; - GetView(aPresContext, &view); - if (NS_SUCCEEDED(view->QueryInterface(kScrollViewIID, (void**)&scrollingView))) { - scrollingView->ComputeScrollOffsets(PR_TRUE); - } - } - - return rv; -} - nsresult nsScrollPortFrame::CreateScrollingViewWidget(nsIView* aView, const nsStylePosition* aPosition) { @@ -314,234 +273,127 @@ nsScrollPortFrame::CreateScrollingView(nsIPresContext* aPresContext) return rv; } - -// Calculate the total amount of space needed for the child frame, -// including its child frames that stick outside its bounds and any -// absolutely positioned child frames. -// Updates the width/height members of the reflow metrics -nsresult -nsScrollPortFrame::CalculateChildTotalSize(nsIFrame* aKidFrame, - nsHTMLReflowMetrics& aKidReflowMetrics) +NS_IMETHODIMP +nsScrollPortFrame::GetMargin(nsMargin& aMargin) { - // If the frame has child frames that stick outside its bounds, then take - // them into account, too - nsFrameState kidState; - aKidFrame->GetFrameState(&kidState); - if (NS_FRAME_OUTSIDE_CHILDREN & kidState) { - aKidReflowMetrics.width = aKidReflowMetrics.mOverflowArea.width; - aKidReflowMetrics.height = aKidReflowMetrics.mOverflowArea.height; + aMargin.SizeTo(0,0,0,0); + return NS_OK; +} + +NS_IMETHODIMP +nsScrollPortFrame::GetPadding(nsMargin& aMargin) +{ + aMargin.SizeTo(0,0,0,0); + return NS_OK; +} + +NS_IMETHODIMP +nsScrollPortFrame::GetBorder(nsMargin& aMargin) +{ + aMargin.SizeTo(0,0,0,0); + return NS_OK; +} + +NS_IMETHODIMP +nsScrollPortFrame::Layout(nsBoxLayoutState& aState) +{ + nsRect clientRect(0,0,0,0); + GetClientRect(clientRect); + nsIBox* kid = nsnull; + GetChildBox(&kid); + nsRect childRect(clientRect); + nsMargin margin(0,0,0,0); + kid->GetMargin(margin); + childRect.Deflate(margin); + nsSize min(0,0); + kid->GetMinSize(aState, min); + + /* + // if our child is not html then get is min size + // and make sure we don't squeeze it smaller than that. + nsIBoxToBlockAdaptor* adaptor = nsnull; + if (NS_FAILED(kid->QueryInterface(NS_GET_IID(nsIBoxToBlockAdaptor), (void**)&adaptor))) { + if (min.height > childRect.height) + childRect.height = min.height; + } + */ + + if (min.height > childRect.height) + childRect.height = min.height; + + if (min.width > childRect.width) + childRect.width = min.width; + + kid->SetBounds(aState, childRect); + kid->Layout(aState); + kid->GetBounds(childRect); + + clientRect.Inflate(margin); + + if (childRect.width < clientRect.width || childRect.height < childRect.height) + { + if (childRect.width < clientRect.width) + childRect.width = clientRect.width; + + if (childRect.height < clientRect.height) + childRect.height = clientRect.height; + + clientRect.Deflate(margin); + + kid->SetBounds(aState, childRect); + } + + SyncLayout(aState); + + nsIPresContext* presContext = aState.GetPresContext(); + nsIScrollableView* scrollingView; + nsIView* view; + GetView(presContext, &view); + if (NS_SUCCEEDED(view->QueryInterface(kScrollViewIID, (void**)&scrollingView))) { + scrollingView->ComputeScrollOffsets(PR_TRUE); } return NS_OK; } + NS_IMETHODIMP -nsScrollPortFrame::Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) +nsScrollPortFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) { - NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS, - ("enter nsScrollPortFrame::Reflow: maxSize=%d,%d", - aReflowState.availableWidth, - aReflowState.availableHeight)); + nsIBox* child = nsnull; + GetChildBox(&child); + nsresult rv = child->GetPrefSize(aBoxLayoutState, aSize); + AddMargin(child, aSize); + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSPrefSize(aBoxLayoutState, this, aSize); + return rv; +} - // if we have any padding then ignore it. It is inherited down to our scrolled frame - if (aReflowState.mComputedPadding.left != 0 || - aReflowState.mComputedPadding.right != 0 || - aReflowState.mComputedPadding.top != 0 || - aReflowState.mComputedPadding.bottom != 0) - { - nsHTMLReflowState newState(aReflowState); - - // get the padding to remove - nscoord pwidth = (newState.mComputedPadding.left + newState.mComputedPadding.right); - nscoord pheight = (newState.mComputedPadding.top + newState.mComputedPadding.bottom); - - // adjust our computed size to add in the padding we are removing. Make sure - // the computed size doesn't go negative or anything. - if (newState.mComputedWidth != NS_INTRINSICSIZE) - newState.mComputedWidth += pwidth; - - if (newState.mComputedHeight != NS_INTRINSICSIZE) - newState.mComputedHeight += pheight; - - // fix up the borderpadding - ((nsMargin&)newState.mComputedBorderPadding) -= newState.mComputedPadding; - - // remove the padding - ((nsMargin&)newState.mComputedPadding) = nsMargin(0,0,0,0); - - // reflow us again with the correct values. - return Reflow(aPresContext, aDesiredSize, newState, aStatus); - } - - // Handle Incremental Reflow - nsIFrame* incrementalChild = nsnull; - if ( aReflowState.reason == eReflowReason_Incremental ) { - nsIReflowCommand::ReflowType reflowType; - aReflowState.reflowCommand->GetType(reflowType); - - // See if it's targeted at us - nsIFrame* targetFrame; - aReflowState.reflowCommand->GetTarget(targetFrame); - - if (this == targetFrame) { - // if we are the target see what the type was - // and generate a normal non incremental reflow. - switch (reflowType) { - - case nsIReflowCommand::StyleChanged: - { - nsHTMLReflowState newState(aReflowState); - newState.reason = eReflowReason_StyleChange; - return Reflow(aPresContext, aDesiredSize, newState, aStatus); - } - break; - - // if its a dirty type then reflow us with a dirty reflow - case nsIReflowCommand::ReflowDirty: - { - nsHTMLReflowState newState(aReflowState); - newState.reason = eReflowReason_Dirty; - return Reflow(aPresContext, aDesiredSize, newState, aStatus); - } - break; - - default: - NS_ASSERTION(PR_FALSE, "unexpected reflow command type"); - } - - } - - // then get the child we need to flow incrementally - aReflowState.reflowCommand->GetNext(incrementalChild); - - } - nsIFrame* kidFrame = mFrames.FirstChild(); - // Reflow the child and get its desired size. Let it be as high as it - // wants - - const nsMargin& border = aReflowState.mComputedBorderPadding; - - /* - // we only worry about our border. Out scrolled frame worries about the padding. - // so lets remove the padding and add it to our computed size. - nsMargin padding = aReflowState.mComputedPadding; - - if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) - ((nscoord&)aReflowState.mComputedWidth) += padding.left + padding.right; - - if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) - ((nscoord&)aReflowState.mComputedHeight) += padding.top + padding.bottom; - - - ((nsMargin&)aReflowState.mComputedPadding) = nsMargin(0,0,0,0); - ((nsMargin&)aReflowState.mComputedBorderPadding) -= padding; - */ - - nscoord theHeight; - nsIBox* box; - nsReflowReason reason = aReflowState.reason; - nsresult result = kidFrame->QueryInterface(NS_GET_IID(nsIBox), (void**)&box); - if (NS_SUCCEEDED(result)) - theHeight = aReflowState.mComputedHeight; - else { - theHeight = NS_INTRINSICSIZE; - // html can't handle a reflow of dirty. Convert it to - // a resize reflow - if (reason == eReflowReason_Dirty) - reason = eReflowReason_Resize; - } - - nsSize kidReflowSize(aReflowState.availableWidth, theHeight); - nsHTMLReflowState kidReflowState(aPresContext, aReflowState, - kidFrame, kidReflowSize); - nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.maxElementSize); - - kidReflowState.mComputedWidth = aReflowState.mComputedWidth; - kidReflowState.mComputedHeight = theHeight; - kidReflowState.reason = reason; - - nscoord pwidth = (kidReflowState.mComputedBorderPadding.left + kidReflowState.mComputedBorderPadding.right); - nscoord pheight = (kidReflowState.mComputedBorderPadding.top + kidReflowState.mComputedBorderPadding.bottom); - - // child's size is our computed size minus its border and padding. - if (kidReflowState.mComputedWidth != NS_INTRINSICSIZE && kidReflowState.mComputedWidth >= pwidth) - kidReflowState.mComputedWidth -= pwidth; - - if (kidReflowState.mComputedHeight != NS_INTRINSICSIZE && kidReflowState.mComputedHeight >= pheight) - kidReflowState.mComputedHeight -= pheight; - - // reflow and place the child. - ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState, - border.left, border.top, NS_FRAME_NO_MOVE_VIEW, aStatus); - - NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); - CalculateChildTotalSize(kidFrame, kidDesiredSize); - - // Place and size the child. - nscoord x = border.left; - nscoord y = border.top; - - // Compute our desired size - if (aReflowState.mComputedWidth == NS_INTRINSICSIZE) - aDesiredSize.width = kidDesiredSize.width; - else - aDesiredSize.width = aReflowState.mComputedWidth; - - if (aDesiredSize.width > kidDesiredSize.width) - kidDesiredSize.width = aDesiredSize.width; - - aDesiredSize.width += border.left + border.right; - - // Compute our desired size - if (aReflowState.mComputedHeight == NS_INTRINSICSIZE) - aDesiredSize.height = kidDesiredSize.height; - else - aDesiredSize.height = aReflowState.mComputedHeight; - - if (aDesiredSize.height > kidDesiredSize.height) - kidDesiredSize.height = aDesiredSize.height; - - aDesiredSize.height += border.top + border.bottom; - - FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, x, y, NS_FRAME_NO_MOVE_VIEW); - //printf("width=%d, height=%d\n", kidDesiredSize.width, kidDesiredSize.height); - - - if (nsnull != aDesiredSize.maxElementSize) { - // nscoord maxWidth = aDesiredSize.maxElementSize->width; - // maxWidth += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; - // nscoord maxHeight = aDesiredSize.maxElementSize->height; - // maxHeight += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; - // aDesiredSize.maxElementSize->width = maxWidth; - // aDesiredSize.maxElementSize->height = maxHeight; - *aDesiredSize.maxElementSize = *kidDesiredSize.maxElementSize; - } - - //mIncremental = PR_FALSE; - - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; - - /* - if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) - ((nscoord&)aReflowState.mComputedWidth) -= (padding.left + padding.right); - - if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) - ((nscoord&)aReflowState.mComputedHeight) -= (padding.top + padding.bottom); - - ((nsMargin&)aReflowState.mComputedPadding) = padding; - ((nsMargin&)aReflowState.mComputedBorderPadding) += padding; - */ - - NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS, - ("exit nsScrollPortFrame::Reflow: status=%d width=%d height=%d", - aStatus, aDesiredSize.width, aDesiredSize.height)); +NS_IMETHODIMP +nsScrollPortFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + nsIBox* child = nsnull; + GetChildBox(&child); + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSMinSize(aBoxLayoutState, this, aSize); return NS_OK; } +NS_IMETHODIMP +nsScrollPortFrame::GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + nsIBox* child = nsnull; + GetChildBox(&child); + nsresult rv = child->GetMaxSize(aBoxLayoutState, aSize); + AddMargin(child, aSize); + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSMaxSize(aBoxLayoutState, this, aSize); + return rv; +} + NS_IMETHODIMP nsScrollPortFrame::Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -565,7 +417,7 @@ nsScrollPortFrame::Paint(nsIPresContext* aPresContext, } // Paint our children - nsresult rv = nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, + nsresult rv = nsBoxFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); return rv; @@ -577,6 +429,12 @@ nsScrollPortFrame::GetSkipSides() const return 0; } +nsresult +nsScrollPortFrame::GetContentOf(nsIContent** aContent) +{ + return GetContent(aContent); +} + NS_IMETHODIMP nsScrollPortFrame::GetFrameType(nsIAtom** aType) const { @@ -590,176 +448,26 @@ nsScrollPortFrame::GetFrameType(nsIAtom** aType) const NS_IMETHODIMP nsScrollPortFrame::GetFrameName(nsString& aResult) const { - return MakeFrameName("Scroll", aResult); + return MakeFrameName("ScrollPort", aResult); } #endif -NS_IMETHODIMP -nsScrollPortFrame::InvalidateCache(nsIFrame* aChild) +NS_IMETHODIMP_(nsrefcnt) +nsScrollPortFrame::AddRef(void) { - mNeedsRecalc = PR_TRUE; - return NS_OK; -} - -/** - * Goes though each child asking for its size to determine our size. Returns our box size minus our border. - * This method is defined in nsIBox interface. - */ -NS_IMETHODIMP -nsScrollPortFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize) -{ - nsresult rv; - - aSize.Clear(); - - nsIFrame* childFrame = mFrames.FirstChild(); - - // if incremental see if the next in chain is our child. Remove it if it is - // and make sure we pass it down. - if (aReflowState.reason == eReflowReason_Incremental) - { - nsIFrame* incrementalChild = nsnull; - aReflowState.reflowCommand->GetNext(incrementalChild, PR_FALSE); - if (incrementalChild == childFrame) { - aReflowState.reflowCommand->GetNext(incrementalChild); - mNeedsRecalc = PR_TRUE; - } - } - - if (mNeedsRecalc) { - // get the size of the child. This is the min, max, preferred, and spring constant - // it does not include its border. - rv = GetChildBoxInfo(aPresContext, aReflowState, childFrame, mSpring); - NS_ASSERTION(rv == NS_OK,"failed to child box info"); - if (NS_FAILED(rv)) - return rv; - - // add in the child's margin and border/padding if there is one. - const nsStyleSpacing* spacing; - rv = childFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - NS_ASSERTION(rv == NS_OK,"failed to get spacing info"); - if (NS_FAILED(rv)) - return rv; - - nsMargin margin(0,0,0,0); - spacing->GetMargin(margin); - nsSize m(margin.left+margin.right,margin.top+margin.bottom); - mSpring.minSize += m; - mSpring.prefSize += m; - if (mSpring.maxSize.width != NS_INTRINSICSIZE) - mSpring.maxSize.width += m.width; - - if (mSpring.maxSize.height != NS_INTRINSICSIZE) - mSpring.maxSize.height += m.height; - - spacing->GetBorderPadding(margin); - nsSize b(margin.left+margin.right,margin.top+margin.bottom); - mSpring.minSize += b; - mSpring.prefSize += b; - if (mSpring.maxSize.width != NS_INTRINSICSIZE) - mSpring.maxSize.width += b.width; - - if (mSpring.maxSize.height != NS_INTRINSICSIZE) - mSpring.maxSize.height += b.height; - - - // ok we don't need to calc this guy again - mNeedsRecalc = PR_FALSE; - } - - aSize = mSpring; - - return rv; -} - -nsresult -nsScrollPortFrame::GetChildBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame* aFrame, nsBoxInfo& aSize) -{ - - aSize.Clear(); - - // see if the frame has IBox interface - - // if it does ask it for its BoxSize and we are done - nsIBox* ibox; - if (NS_SUCCEEDED(aFrame->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) { - ibox->GetBoxInfo(aPresContext, aReflowState, aSize); - return NS_OK; - } - - // start the preferred size as intrinsic - aSize.prefSize.width = NS_INTRINSICSIZE; - aSize.prefSize.height = NS_INTRINSICSIZE; - - nsSize kidReflowSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE); - nsHTMLReflowState kidReflowState(aPresContext, aReflowState, - aFrame, kidReflowSize); - nsHTMLReflowMetrics kidDesiredSize(nsnull); - - kidReflowState.reason = eReflowReason_Resize; - - kidReflowState.mComputedWidth = NS_INTRINSICSIZE; - kidReflowState.mComputedHeight = NS_INTRINSICSIZE; - - nsReflowStatus status = NS_FRAME_COMPLETE; - - ReflowChild(aFrame, aPresContext, kidDesiredSize, kidReflowState, - 0, 0, NS_FRAME_NO_MOVE_FRAME, status); - aFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); - - NS_ASSERTION(NS_FRAME_IS_COMPLETE(status), "bad status"); - - const nsStyleSpacing* spacing; - nsresult rv = aFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get spacing"); - if (NS_FAILED(rv)) - return rv; - - nsMargin border(0,0,0,0);; - spacing->GetBorderPadding(border); - - - // remove border - kidDesiredSize.width -= (border.left + border.right); - kidDesiredSize.height -= (border.top + border.bottom); - - // get the size returned and the it as the preferredsize. - aSize.prefSize.width = kidDesiredSize.width; - aSize.prefSize.height = kidDesiredSize.height; - return NS_OK; } -NS_IMETHODIMP -nsScrollPortFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr) -{ - if (NULL == aInstancePtr) { - return NS_ERROR_NULL_POINTER; - } - - *aInstancePtr = NULL; - - if (aIID.Equals(NS_GET_IID(nsIBox))) { - *aInstancePtr = (void*)(nsIBox*) this; - NS_ADDREF_THIS(); - return NS_OK; - } - - return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr); -} - -NS_IMETHODIMP -nsScrollPortFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild) +NS_IMETHODIMP_(nsrefcnt) +nsScrollPortFrame::Release(void) { - if (! (mState & NS_FRAME_IS_DIRTY)) { - mState |= NS_FRAME_IS_DIRTY; - return mParent->ReflowDirtyChild(aPresShell, aChild); - } - return NS_OK; } +NS_INTERFACE_MAP_BEGIN(nsScrollPortFrame) + NS_INTERFACE_MAP_ENTRY(nsIBox) +#ifdef NS_DEBUG + NS_INTERFACE_MAP_ENTRY(nsIFrameDebug) +#endif + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBox) +NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame) diff --git a/mozilla/layout/html/base/src/nsScrollPortFrame.h b/mozilla/layout/html/base/src/nsScrollPortFrame.h index b728751b3b8..69d655335ae 100644 --- a/mozilla/layout/html/base/src/nsScrollPortFrame.h +++ b/mozilla/layout/html/base/src/nsScrollPortFrame.h @@ -22,8 +22,7 @@ #ifndef nsScrollPortFrame_h___ #define nsScrollPortFrame_h___ -#include "nsHTMLContainerFrame.h" -#include "nsIBox.h" +#include "nsBoxFrame.h" /** * The scroll frame creates and manages the scrolling view @@ -34,7 +33,7 @@ * Scroll frames don't support incremental changes, i.e. you can't replace * or remove the scrolled frame */ -class nsScrollPortFrame : public nsHTMLContainerFrame, public nsIBox { +class nsScrollPortFrame : nsBoxFrame { public: friend nsresult NS_NewScrollPortFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); @@ -44,8 +43,6 @@ public: nsIStyleContext* aContext, nsIFrame* aPrevInFlow); - NS_IMETHOD SetDebug(nsIPresContext* aPresContext, PRBool aDebug); - // Called to set the one and only child frame. Returns NS_ERROR_INVALID_ARG // if the child frame is NULL, and NS_ERROR_UNEXPECTED if the child list // contains more than one frame @@ -71,21 +68,12 @@ public: nsIAtom* aListName, nsIFrame* aOldFrame); - NS_IMETHOD DidReflow(nsIPresContext* aPresContext, - nsDidReflowStatus aStatus); - - NS_IMETHOD Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); NS_IMETHOD Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer); - NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild); - /** * Get the "type" of the frame * @@ -98,14 +86,20 @@ public: #endif // nsIBox methods - NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); - NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); - NS_IMETHOD_(nsrefcnt) AddRef(void) { return NS_OK; } - NS_IMETHOD_(nsrefcnt) Release(void) { return NS_OK; } - NS_IMETHOD InvalidateCache(nsIFrame* aChild); + NS_DECL_ISUPPORTS + + NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); + NS_IMETHOD GetPadding(nsMargin& aMargin); + NS_IMETHOD GetBorder(nsMargin& aMargin); + NS_IMETHOD GetMargin(nsMargin& aMargin); + + virtual nsresult GetContentOf(nsIContent** aContent); protected: - nsScrollPortFrame(); + nsScrollPortFrame(nsIPresShell* aShell); virtual PRIntn GetSkipSides() const; // Creation of the widget for the scrolling view is factored into a virtual method so @@ -119,14 +113,6 @@ protected: private: nsresult CreateScrollingView(nsIPresContext* aPresContext); - nsresult CalculateChildTotalSize(nsIFrame* aKidFrame, - nsHTMLReflowMetrics& aKidReflowMetrics); - - nsresult GetChildBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame* aFrame, nsBoxInfo& aSize); - - PRBool mNeedsRecalc; - nsBoxInfo mSpring; - PRBool mIncremental; }; #endif /* nsScrollPortFrame_h___ */ diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp index 68beb9b6c61..d3d07e7611f 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -120,7 +120,7 @@ #include "nsIDOMDocument.h" #include "nsDocument.h" #include "nsToolbarItemFrame.h" -#include "nsXULCheckboxFrame.h" +#include "nsCheckBoxFrame.h" #include "nsIScrollable.h" #ifdef DEBUG @@ -132,8 +132,28 @@ static PRBool gNoisyInlineConstruction = PR_FALSE; #define NEWGFX_LIST_SCROLLFRAME //------------------------------------------------------------------ +#ifdef NEWGFX_LIST_SCROLLFRAME nsresult NS_NewGfxListControlFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); +#endif + +// grid + +/* +nsresult +NS_NewGridFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); + +nsresult +NS_NewTempleFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsHorizontal); + +nsresult +NS_NewObeliskFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsHorizontal); + +// end grid +*/ + +nsresult +NS_NewRootBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); nsresult NS_NewThumbFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); @@ -142,7 +162,7 @@ nsresult NS_NewScrollPortFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); nsresult -NS_NewGfxScrollFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, nsIDocument* aDocument ); +NS_NewGfxScrollFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, nsIDocument* aDocument, PRBool aIsRoot); nsresult NS_NewTabFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); @@ -163,7 +183,10 @@ nsresult NS_NewTitledButtonFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); nsresult -NS_NewXULTextFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); +NS_NewImageBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); + +nsresult +NS_NewTextBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); nsresult NS_NewTitledBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); @@ -178,7 +201,7 @@ nsresult NS_NewBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoot); nsresult -NS_NewXULButtonFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame); +NS_NewButtonBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame); nsresult NS_NewSliderFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); @@ -2359,6 +2382,7 @@ nsCSSFrameConstructor::TableIsValidCellContent(nsIPresContext* aPresContext, #ifdef INCLUDE_XUL if ( (nsXULAtoms::button == tag.get()) || (nsXULAtoms::titledbutton == tag.get()) || + (nsXULAtoms::box == tag.get()) || (nsXULAtoms::image == tag.get()) || (nsXULAtoms::grippy == tag.get()) || (nsXULAtoms::splitter == tag.get()) || @@ -2603,6 +2627,7 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIPresShell* aPresShell, aParentFrame, nsLayoutAtoms::scrolledContentPseudo, document, + PR_FALSE, scrollFrame, newContext, newScrollFrame); @@ -2837,7 +2862,15 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, nsIAtom* rootPseudo; if (!isPaginated) { - NS_NewRootFrame(aPresShell, &rootFrame); + PRInt32 nameSpaceID; + if (NS_SUCCEEDED(aDocElement->GetNameSpaceID(nameSpaceID)) && + nameSpaceID == nsXULAtoms::nameSpaceID) + { + NS_NewRootBoxFrame(aPresShell, &rootFrame); + } else { + NS_NewRootFrame(aPresShell, &rootFrame); + } + rootPseudo = nsLayoutAtoms::canvasPseudo; mDocElementContainingBlock = rootFrame; } else { @@ -2868,6 +2901,8 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, } } + //isScrollable = PR_FALSE; + // As long as the webshell doesn't prohibit it, and the device supports // it, create a scroll frame that will act as the scolling mechanism for // the viewport. @@ -2941,6 +2976,7 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, viewportFrame, rootPseudo, document, + PR_TRUE, newFrame, rootPseudoStyle, newScrollableFrame); @@ -4656,7 +4692,7 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell, else if (aTag == nsXULAtoms::button) { processChildren = PR_TRUE; isReplaced = PR_TRUE; - rv = NS_NewXULButtonFrame(aPresShell, &newFrame); + rv = NS_NewButtonBoxFrame(aPresShell, &newFrame); const nsStyleDisplay* display = (const nsStyleDisplay*) aStyleContext->GetStyleData(eStyleStruct_Display); @@ -4679,15 +4715,18 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell, } // End of BUTTON CONSTRUCTION logic // TITLED BUTTON CONSTRUCTION - else if (aTag == nsXULAtoms::titledbutton || - aTag == nsXULAtoms::image) { + else if (aTag == nsXULAtoms::titledbutton) { processChildren = PR_TRUE; isReplaced = PR_TRUE; rv = NS_NewTitledButtonFrame(aPresShell, &newFrame); } // End of TITLED BUTTON CONSTRUCTION logic - + else if (aTag == nsXULAtoms::image) { + processChildren = PR_TRUE; + isReplaced = PR_TRUE; + rv = NS_NewImageBoxFrame(aPresShell, &newFrame); + } else if (aTag == nsXULAtoms::spring) { processChildren = PR_TRUE; isReplaced = PR_TRUE; @@ -4699,7 +4738,7 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell, else if (aTag == nsXULAtoms::text) { processChildren = PR_TRUE; isReplaced = PR_TRUE; - rv = NS_NewXULTextFrame(aPresShell, &newFrame); + rv = NS_NewTextBoxFrame(aPresShell, &newFrame); } // End of TEXT CONSTRUCTION logic @@ -4736,7 +4775,90 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell, processChildren = PR_TRUE; isReplaced = PR_TRUE; rv = NS_NewMenuPopupFrame(aPresShell, &newFrame); - } + } + + /* + + // ------- Begin Grid --------- + else if (aTag == nsXULAtoms::grid) { + processChildren = PR_TRUE; + isReplaced = PR_TRUE; + rv = NS_NewGridFrame(aPresShell, &newFrame); + + const nsStyleDisplay* display = (const nsStyleDisplay*) + aStyleContext->GetStyleData(eStyleStruct_Display); + + // Boxes can scroll. + if (IsScrollable(aPresContext, display)) { + + // set the top to be the newly created scrollframe + BuildScrollFrame(aPresShell, aPresContext, aState, aContent, aStyleContext, newFrame, aParentFrame, + topFrame, aStyleContext); + + // we have a scrollframe so the parent becomes the scroll frame. + newFrame->GetParent(&aParentFrame); + + primaryFrameSet = PR_TRUE; + + frameHasBeenInitialized = PR_TRUE; + + } + } //------- End Grid ------ + + // ------- Begin Rows/Columns --------- + else if (aTag == nsXULAtoms::rows || aTag == nsXULAtoms::columns) { + processChildren = PR_TRUE; + isReplaced = PR_TRUE; + PRBool isHorizontal = (aTag == nsXULAtoms::columns); + rv = NS_NewTempleFrame(aPresShell, &newFrame, isHorizontal); + + const nsStyleDisplay* display = (const nsStyleDisplay*) + aStyleContext->GetStyleData(eStyleStruct_Display); + + // Boxes can scroll. + if (IsScrollable(aPresContext, display)) { + + // set the top to be the newly created scrollframe + BuildScrollFrame(aPresShell, aPresContext, aState, aContent, aStyleContext, newFrame, aParentFrame, + topFrame, aStyleContext); + + // we have a scrollframe so the parent becomes the scroll frame. + newFrame->GetParent(&aParentFrame); + + primaryFrameSet = PR_TRUE; + + frameHasBeenInitialized = PR_TRUE; + + } + } //------- End Grid ------ + + // ------- Begin Row/Column --------- + else if (aTag == nsXULAtoms::row || aTag == nsXULAtoms::column) { + processChildren = PR_TRUE; + isReplaced = PR_TRUE; + PRBool isHorizontal = (aTag == nsXULAtoms::row); + rv = NS_NewObeliskFrame(aPresShell, &newFrame, isHorizontal); + + const nsStyleDisplay* display = (const nsStyleDisplay*) + aStyleContext->GetStyleData(eStyleStruct_Display); + + // Boxes can scroll. + if (IsScrollable(aPresContext, display)) { + + // set the top to be the newly created scrollframe + BuildScrollFrame(aPresShell, aPresContext, aState, aContent, aStyleContext, newFrame, aParentFrame, + topFrame, aStyleContext); + + // we have a scrollframe so the parent becomes the scroll frame. + newFrame->GetParent(&aParentFrame); + + primaryFrameSet = PR_TRUE; + + frameHasBeenInitialized = PR_TRUE; + + } + } //------- End Grid ------ +*/ else if (aTag == nsXULAtoms::title) { processChildren = PR_TRUE; isReplaced = PR_TRUE; @@ -4949,7 +5071,7 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell, aTag == nsXULAtoms::radio) { processChildren = PR_TRUE; isReplaced = PR_TRUE; - rv = NS_NewXULCheckboxFrame(aPresShell, &newFrame); + rv = NS_NewCheckBoxFrame(aPresShell, &newFrame); } // End of XULCHECKBOX CONSTRUCTION logic @@ -5123,6 +5245,7 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsIPresShell* aPresShell, nsIFrame* aParentFrame, nsIAtom* aScrolledPseudo, nsIDocument* aDocument, + PRBool aIsRoot, nsIFrame*& aNewFrame, nsCOMPtr& aScrolledChildStyle, nsIFrame*& aScrollableFrame) @@ -5140,7 +5263,7 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsIPresShell* aPresShell, if (isGfx) { BuildGfxScrollFrame(aPresShell, aPresContext, aState, aContent, aDocument, aParentFrame, - contentStyle, gfxScrollFrame, anonymousItems); + contentStyle, aIsRoot, gfxScrollFrame, anonymousItems); scrollFrame = anonymousItems.childList; parentFrame = gfxScrollFrame; @@ -5283,6 +5406,7 @@ nsCSSFrameConstructor::BuildScrollFrame (nsIPresShell* aPresShell, aParentFrame, nsLayoutAtoms::scrolledContentPseudo, document, + PR_FALSE, aNewFrame, scrolledContentStyle, scrollFrame); @@ -5317,10 +5441,11 @@ nsCSSFrameConstructor::BuildGfxScrollFrame (nsIPresShell* aPresShell, nsIDocument* aDocument, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + PRBool aIsRoot, nsIFrame*& aNewFrame, nsFrameItems& aAnonymousFrames) { - NS_NewGfxScrollFrame(aPresShell, &aNewFrame,aDocument); + NS_NewGfxScrollFrame(aPresShell, &aNewFrame, aDocument, aIsRoot); InitAndRestoreFrame(aPresContext, aState, aContent, aParentFrame, aStyleContext, nsnull, aNewFrame); @@ -7074,6 +7199,28 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, } else { // Find the frame that precedes the insertion point. nsIFrame* prevSibling = FindPreviousSibling(shell, aContainer, aIndexInContainer); + + /* + if (prevSibling) { + nsIFrame* parent; + prevSibling->GetParent(&parent); + nsIFrame* first; + parent->FirstChild(aPresContext, nsnull, &first); + PRBool found = PR_FALSE; + while(first) + { + if (first == prevSibling) { + found = PR_TRUE; + break; + } + + first->GetNextSibling(&first); + } + + NS_ASSERTION(found,"Error sibling not in parent!!!!!"); + } + */ + nsIFrame* nextSibling = nsnull; PRBool isAppend = PR_FALSE; diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.h b/mozilla/layout/html/style/src/nsCSSFrameConstructor.h index 8ca4f35606e..a6a35aa7b81 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.h +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.h @@ -646,6 +646,7 @@ protected: nsIFrame* aParentFrame, nsIAtom* aScrolledPseudo, nsIDocument* aDocument, + PRBool aIsRoot, nsIFrame*& aNewFrame, nsCOMPtr& aScrolledChildStyle, nsIFrame*& aScrollableFrame); @@ -671,6 +672,7 @@ protected: nsIDocument* aDocument, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + PRBool aIsRoot, nsIFrame*& aNewFrame, nsFrameItems& aAnonymousFrames); diff --git a/mozilla/layout/macbuild/layout.mcp b/mozilla/layout/macbuild/layout.mcp index a739f8ef8ea25f471f13cda8a5f14d796138d36a..b7d71724f70bfa2490add020fcffbb92f8429173 100644 GIT binary patch delta 5146 zcmeI03viUx702(r-)?p{2{e(#yfg$5iYZE)FbLylCnC`Z)EJ<(I0#F!d6>s8$zlT& z+@MwK*gC{3-LXow4%E>KG+ooRXcc^n8bM+oND|14WJA!lkj9V%aC`1||657Mnc5kr z9cK)4=J!A6zVCNm>_C&f^`PBZ=z941n4Vvf#HSUs7<^`_V&^Z7NGr&Hl93+1seagwz1v#sP?nFt4W^2|H^S;b}>6k{yQ zOPZUKWz~}w(A!Bs+H{=uqZ{Cn;3tqqF8cWVmn!Z-DHnMiIV`Rt4I>mchS>mutW>mfTq)=Sn$7MA>( zMaCg!m)o9p26sPi@Lh!HhDJsCi*LUE}#3e;7ZR86`sQK zoFbRk=c$gyH~M^@Dyl5E+Ep3Nytvd|SWYp?o2U9eYiOCGqB50JU3K zJ}$D-UF(}rvcTh+7|N@3mAJ=cqxBJ3l+2SG@*n=fpK+C+pUBNyw#34CFW3i$!G7>0 zH~^jkKLS4n{|5dY{0Dd%JOd7z^fUfX1cty*z+v#Lrf|X^0Y||x@SLXD1OGgD0gND> zfn3o+>u-)3kWY=wT14~kj85jez+Z#k2EU^zwt6xWiDLE2t$C-^M*Jop%RSneB5yOA2X3xV0-WneORC3rPB7yKqzE>p&)`Kh8G zA}~vnF9B}?mx9Z|Tfy7F72rxuaRvNU;P=5FfRBQ|AzEqCi4F3VvFYj?=-HLwv6=J9 z%hLJ8I&cg4BG?4}9t_Fr&L#Wj!SjM8;FI7EuoNrSOvZW{sDX&{1Lbb+zf67?*;D%e+=FS{@kRWi3bpP5PTf`1^7$wDe!6VSKw~& zci=wokKk+I`(O+Bfl2ys9rBU$84F1iBc<-5bwAChU2opmNNWb)0}lnm=LJur(gzS( z2)0K2=D*<5Pq#0LUQe>I&KbR!rZ(JI5qj)qzB(x-dW)!=WSoU;>v)ngxV-cwF+IYV z*g+R5?Lu{fOmr50@rHt=&HO5@q7@ck9ZmWyWm0j-Jw*q z_#Q%F|3&ldFbZpG)aORpBjBT;lnp~^SJ3(YtPb$)px#`JNB7JNvSlb;9iDffWFm;e zP~gxLR>W~QG8`AI8}Z+QHcjpTCxNJ!Z$myi;?szJ^}!Mln1Kwdz$u91{^0t4V?0yG zSs3}yAo~P%d>1C1Ys-vWLB z{t5guQO!O73j%)ykANS7*aW;4ejA9Zf#c5LSQNYi>DaZr3qBSL?}1O7(*J*auBq1= zj*%hs2&;z=!;kK6C;Sm`6dVK3Y5sT5HTv{(^uGG~xyHWY&$anj0A8>Jj6T=;;qL%T z!7}haJ=<_k32Z45z0a_f`~rJVU@!iUpKtVBiyp-HVMMrU{{4*WL;OMTOMTAGrM+|# z6~6|4{=4o=dDdl9a|h7OLa;Ss;$KxwUV*!+$X#7lRkGL?IkiWgk89 zE@&B6uRSgMDMOr=^y85cA83dWs&UEG&>XNS$vb z$+c8N5?ZPu8Ct3#S+rC`vTCV@6r-gYl1)oBB)gVsNDeL4kYcr@AyMbehG|IDc~jDm zsPm?zA&u|+u5XAyT!JV{omF31vk+K}TC n@j6fcXe$*MK>_@XrV0$cN0|-=2BwHBZLIE;St7+LT4MeMa@519 delta 3214 zcmZwK3s6*57zgn4o!#Y;(rAJpAZVZop`uylIMy`g0}Vw5%ghHT1}2DtLZB^L+E|WB zE8Qr~7e2ClvC85rCubZ{fp{aOA>}iz)ChTR-`(?P24~utGr#Zq&bjyOp1t?%-P$6T zyT@JJ7c5=6L9YvRH>aOL|K=ojWh<8 z^SiI$R>`f3TQ#>DZdbU~ax3OmB8!EKW%CYq>%jvCvL0W%Dp7mMi+u9dXOiVeu2E|| zOg+t>6Q)N+@Wy|@q%oCpTJMyJUAaNfYERnd`n3?l%fvx&tUj? zvtuIKh(a>_7A}WTO7S~#4>%L`8}K&j5lYHJUXA_-@DXe@BY3QoKf-t5^Kg!mb|N1P zr@*Q31iSz*by;3NQ_PC^B@6Y1M(@Y?{PKq`!(0sul9PFm0fRc%W;61vE@NGsVpql{ zrs%^>s+;z~Z1@G-u9OG59By#c40(JJ@K-$x-96zn7zuHDIbG%A8mveEA?U0mSLg1##>w}P&xY$^&iF7t$Ho2u z3aj8@cv1_sl7A$>MZ7hdt9mE~Cc+e$2Ge0C{0M%pl;^bFR_d>>{!mm#VZ?ce%ZLh* zUxb(7Wmp7@VF~;RmclYv4l7uF^{EntDu^3~YLH)nweV;73%m+(S;Uvn=N8m}4qQLfh`e)W za7W$*n_&xVRZ4uh)P{OHw4+}@f`inZW!c^|U=**zE)3rT_rg#(Oer_PryW|_o96iP zb<_vd#SmAd+^22LC$A75aS%P2M`9kiAN9{+v35P5d|u}x;!qg~eW4c&f9#MB2_K}QICQ%A?6``7W$6sCVh`tYB}A~-<1Qk znp*b)3g91qIb0nmabwF23Mw-!qeMWwWd@Wo9w?OPeavgFFehIh2ZSWho9qQ{j&NN!cBPbNWQ}7Hd zf+Y~!ku0-RxAp7J3%?K@=~~1|@^a@2b~=fjPF}VSX_vHsd(L9)%dixdLwzsPzvN0- z1#226CW@T+>mnyPlz%6MapJXp&UtO2!HM=eQ|3-d;fJI!z27>yBYWKcJ#)>sZJ9`K zd-f^ilb3NT=T@Ol#I1^3was}xdAessxbS0@$&!?6w9UFo7BXe?Fa0TPX9)$^?q8z< zGVS6*p`&2h&EZ8ysO8qtAk!YsFRQM-92TjrBE4%r=OvDOUqc<4tSi!b$e!N(gy+M} zms?+MewOv=lWB^jB>k-IRwi{DYCC$0x&@oc`QT=C-U<#|R9MMjs|u?)Y*S%1hwUn? z;jqIIYNu~fxHTeYH02MbCdymCnrv(C>8CE`G0obrb_y_+aoD0leZp21>Jzr9P@k|} zh5CdYj!@g^A)h$)KGHIL?|H#7NT3Gw#-+a^gH}eh@njhDM|WY1^vk%ue9Zy7HMI9Ww6ugS2&Ke qz28@!Bfq-4LWK6i0s3D9^`fz7cu=V}%U=dL(`=jLhz + */ + +// +// Eric Vaughan +// Netscape Communications +// +// See documentation in associated header file +// + +#include "nsBoxLayoutState.h" +#include "nsBox.h" +#include "nsBoxFrame.h" +#include "nsIStyleContext.h" +#include "nsIPresContext.h" +#include "nsCOMPtr.h" +#include "nsIContent.h" +#include "nsIViewManager.h" +#include "nsIView.h" +#include "nsIPresShell.h" +#include "nsHTMLContainerFrame.h" +#include "nsISelfScrollingFrame.h" +#include "nsINameSpaceManager.h" +#include "nsHTMLAtoms.h" +#include "nsXULAtoms.h" + +nsBox::nsBox(nsIPresShell* aShell):mParentBox(nsnull),mNextChild(nsnull),mMouseThrough(always) +{ + //mX = 0; + //mY = 0; +} + +NS_IMETHODIMP +nsBox::GetInset(nsMargin& margin) +{ + margin.SizeTo(0,0,0,0); + return NS_OK; +} + +NS_IMETHODIMP +nsBox::IsDirty(PRBool& aDirty) +{ + nsFrameState state; + nsIFrame* frame; + GetFrame(&frame); + frame->GetFrameState(&state); + aDirty = (state & NS_FRAME_IS_DIRTY); + return NS_OK; +} + +NS_IMETHODIMP +nsBox::HasDirtyChildren(PRBool& aDirty) +{ + nsFrameState state; + nsIFrame* frame; + GetFrame(&frame); + frame->GetFrameState(&state); + aDirty = (state & NS_FRAME_HAS_DIRTY_CHILDREN); + return NS_OK; +} + +NS_IMETHODIMP +nsBox::MarkDirty(nsBoxLayoutState& aState) +{ + NeedsRecalc(); + + nsFrameState state; + nsIFrame* frame; + GetFrame(&frame); + frame->GetFrameState(&state); + + // only reflow if we aren't already dirty. + if (state & NS_FRAME_IS_DIRTY) + return NS_OK; + + state |= NS_FRAME_IS_DIRTY; + frame->SetFrameState(state); + + nsIFrame* parent = nsnull; + frame->GetParent(&parent); + nsCOMPtr shell; + aState.GetPresShell(getter_AddRefs(shell)); + + return parent->ReflowDirtyChild(shell, frame); +} + +NS_IMETHODIMP +nsBox::MarkDirtyChildren(nsBoxLayoutState& aState) +{ + nsFrameState state; + nsIFrame* frame; + GetFrame(&frame); + frame->GetFrameState(&state); + + // only reflow if we aren't already dirty. + if (state & NS_FRAME_HAS_DIRTY_CHILDREN) + return NS_OK; + + state |= NS_FRAME_HAS_DIRTY_CHILDREN; + frame->SetFrameState(state); + + NeedsRecalc(); + nsIFrame* parent = nsnull; + frame->GetParent(&parent); + nsCOMPtr shell; + aState.GetPresShell(getter_AddRefs(shell)); + + return parent->ReflowDirtyChild(shell, frame); +} + +NS_IMETHODIMP +nsBox::GetVAlign(Valignment& aAlign) +{ + aAlign = vAlign_Top; + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetHAlign(Halignment& aAlign) +{ + aAlign = hAlign_Left; + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetClientRect(nsRect& aClientRect) +{ + GetContentRect(aClientRect); + + nsMargin borderPadding; + GetBorderAndPadding(borderPadding); + + aClientRect.Deflate(borderPadding); + + nsMargin insets; + GetInset(insets); + + aClientRect.Deflate(insets); + if (aClientRect.width < 0) + aClientRect.width = 0; + + if (aClientRect.height < 0) + aClientRect.height = 0; + + // NS_ASSERTION(aClientRect.width >=0 && aClientRect.height >= 0, "Content Size < 0"); + + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetContentRect(nsRect& aContentRect) +{ + GetBounds(aContentRect); + aContentRect.x = 0; + aContentRect.y = 0; + NS_ASSERTION(aContentRect.width >=0 && aContentRect.height >= 0, "Content Size < 0"); + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetBounds(nsRect& aRect) +{ + nsIFrame* frame = nsnull; + GetFrame(&frame); + + return frame->GetRect(aRect); +} + +NS_IMETHODIMP +nsBox::SetBounds(nsBoxLayoutState& aLayoutState, const nsRect& aRect) +{ + NS_ASSERTION(aRect.width >=0 && aRect.height >= 0, "SetBounds Size < 0"); + + nsRect rect(0,0,0,0); + GetBounds(rect); + + nsIFrame* frame = nsnull; + GetFrame(&frame); + + nsIPresContext* presContext = aLayoutState.GetPresContext(); + frame->SetRect(presContext, aRect); + + + // only if the origin changed + if ((rect.x != aRect.x) || (rect.y != aRect.y)) { + nsIView* view; + frame->GetView(presContext, &view); + if (view) { + nsContainerFrame::PositionFrameView(presContext, frame, view); + } else { + nsContainerFrame::PositionChildViews(presContext, frame); + } + } + + return NS_OK; +} + + +NS_IMETHODIMP +nsBox::GetBorderAndPadding(nsMargin& aBorderAndPadding) +{ + nsIFrame* frame = nsnull; + GetFrame(&frame); + + const nsStyleSpacing* spacing; + nsresult rv = frame->GetStyleData(eStyleStruct_Spacing, + (const nsStyleStruct*&) spacing); + + nsMargin border; + nsMargin padding; + GetBorder(border); + GetPadding(padding); + aBorderAndPadding.SizeTo(0,0,0,0); + aBorderAndPadding += border; + aBorderAndPadding += padding; + + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetBorder(nsMargin& aMargin) +{ + nsIFrame* frame = nsnull; + GetFrame(&frame); + + const nsStyleSpacing* spacing; + nsresult rv = frame->GetStyleData(eStyleStruct_Spacing, + (const nsStyleStruct*&) spacing); + + aMargin.SizeTo(0,0,0,0); + spacing->GetBorder(aMargin); + + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetPadding(nsMargin& aMargin) +{ + nsIFrame* frame = nsnull; + GetFrame(&frame); + + const nsStyleSpacing* spacing; + nsresult rv = frame->GetStyleData(eStyleStruct_Spacing, + (const nsStyleStruct*&) spacing); + + aMargin.SizeTo(0,0,0,0); + spacing->GetPadding(aMargin); + + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetMargin(nsMargin& aMargin) +{ + nsIFrame* frame = nsnull; + GetFrame(&frame); + + const nsStyleSpacing* spacing; + nsresult rv = frame->GetStyleData(eStyleStruct_Spacing, + (const nsStyleStruct*&) spacing); + + aMargin.SizeTo(0,0,0,0); + spacing->GetMargin(aMargin); + + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetChildBox(nsIBox** aBox) +{ + *aBox = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetNextBox(nsIBox** aBox) +{ + *aBox = mNextChild; + return NS_OK; +} + +NS_IMETHODIMP +nsBox::SetNextBox(nsIBox* aBox) +{ + mNextChild = aBox; + return NS_OK; +} + +NS_IMETHODIMP +nsBox::SetParentBox(nsIBox* aParent) +{ + mParentBox = aParent; + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetParentBox(nsIBox** aParent) +{ + *aParent = mParentBox; + return NS_OK; +} + +NS_IMETHODIMP +nsBox::NeedsRecalc() +{ + return NS_OK; +} + +nsresult +nsBox::SetDebug(nsBoxLayoutState& aState, PRBool aDebug) +{ + return NS_OK; +} + + +void +nsBox::SizeNeedsRecalc(nsSize& aSize) +{ + aSize.width = -1; + aSize.height = -1; +} + +void +nsBox::CoordNeedsRecalc(PRInt32& aFlex) +{ + aFlex = -1; +} + +PRBool +nsBox::DoesNeedRecalc(const nsSize& aSize) +{ + return (aSize.width == -1 || aSize.height == -1); +} + +PRBool +nsBox::DoesNeedRecalc(nscoord aCoord) +{ + return (aCoord == -1); +} + +PRBool +nsBox::GetWasCollapsed(nsBoxLayoutState& aState) +{ + nsIFrame* frame = nsnull; + GetFrame(&frame); + nsFrameState state; + frame->GetFrameState(&state); + + return (state & NS_STATE_IS_COLLAPSED); +} + +void +nsBox::SetWasCollapsed(nsBoxLayoutState& aState, PRBool aCollapsed) +{ + nsIFrame* frame; + GetFrame(&frame); + nsFrameState state; + frame->GetFrameState(&state); + if (aCollapsed) + state |= NS_STATE_IS_COLLAPSED; + else + state &= ~NS_STATE_IS_COLLAPSED; + + frame->SetFrameState(state); +} + +NS_IMETHODIMP +nsBox::Collapse(nsBoxLayoutState& aState) +{ + // if (GetWasCollapsed(aState)) + // return NS_OK; + + SetWasCollapsed(aState, PR_TRUE); + nsIFrame* frame; + GetFrame(&frame); + SetBounds(aState, nsRect(0,0,0,0)); + + return CollapseChild(aState, frame, PR_TRUE); +} + +nsresult +nsBox::CollapseChild(nsBoxLayoutState& aState, nsIFrame* aFrame, PRBool aHide) +{ + nsIPresContext* presContext = aState.GetPresContext(); + + // shrink the view + nsIView* view = nsnull; + aFrame->GetView(presContext, &view); + + // if we find a view stop right here. All views under it + // will be clipped. + if (view) { + // already hidden? We are done. + nsViewVisibility v; + view->GetVisibility(v); + //if (v == nsViewVisibility_kHide) + //return NS_OK; + + nsCOMPtr widget; + view->GetWidget(*getter_AddRefs(widget)); + if (aHide) { + view->SetVisibility(nsViewVisibility_kHide); + } else { + view->SetVisibility(nsViewVisibility_kShow); + } + if (widget) { + + return NS_OK; + } + } + + // Trees have to collapse their scrollbars manually, since you can't + // get to the scrollbar via the normal frame list. + nsISelfScrollingFrame* treeFrame; + if (NS_SUCCEEDED(aFrame->QueryInterface(NS_GET_IID(nsISelfScrollingFrame), (void**)&treeFrame)) && treeFrame) { + // Tell the tree frame to collapse its scrollbar. + treeFrame->CollapseScrollbar(presContext, aHide); + } + + // collapse the child + nsIFrame* child = nsnull; + aFrame->FirstChild(presContext, nsnull,&child); + + while (nsnull != child) + { + CollapseChild(aState, child, aHide); + nsresult rv = child->GetNextSibling(&child); + NS_ASSERTION(rv == NS_OK,"failed to get next child"); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsBox::UnCollapse(nsBoxLayoutState& aState) +{ + if (!GetWasCollapsed(aState)) + return NS_OK; + + SetWasCollapsed(aState, PR_FALSE); + + return UnCollapseChild(aState, this); +} + +nsresult +nsBox::UnCollapseChild(nsBoxLayoutState& aState, nsIBox* aBox) +{ + nsIPresContext* presContext = aState.GetPresContext(); + nsIFrame* frame; + aBox->GetFrame(&frame); + + // collapse the child + nsIBox* child = nsnull; + aBox->GetChildBox(&child); + + if (child == nsnull) { + nsFrameState childState; + frame->GetFrameState(&childState); + childState |= NS_FRAME_IS_DIRTY; + frame->SetFrameState(childState); + } else { + child->GetFrame(&frame); + nsFrameState childState; + frame->GetFrameState(&childState); + childState |= NS_FRAME_HAS_DIRTY_CHILDREN; + frame->SetFrameState(childState); + + while (nsnull != child) + { + UnCollapseChild(aState, child); + nsresult rv = child->GetNextBox(&child); + NS_ASSERTION(rv == NS_OK,"failed to get next child"); + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsBox::SetLayoutManager(nsIBoxLayout* aLayout) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetLayoutManager(nsIBoxLayout** aLayout) +{ + *aLayout = nsnull; + return NS_OK; +} + + +NS_IMETHODIMP +nsBox::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) +{ + aSize.width = 0; + aSize.height = 0; + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSPrefSize(aState, this, aSize); + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize) +{ + aSize.width = 0; + aSize.height = 0; + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSMinSize(aState, this, aSize); + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetMaxSize(nsBoxLayoutState& aState, nsSize& aSize) +{ + aSize.width = NS_INTRINSICSIZE; + aSize.height = NS_INTRINSICSIZE; + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSMaxSize(aState, this, aSize); + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetFlex(nsBoxLayoutState& aState, nscoord& aFlex) +{ + aFlex = 0; + PRBool collapsed = PR_FALSE; + nsIBox::AddCSSFlex(aState, this, aFlex); + + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetAscent(nsBoxLayoutState& aState, nscoord& aAscent) +{ + nsSize size(0,0); + nsresult rv = GetPrefSize(aState, size); + aAscent = size.height; + return rv; +} + +NS_IMETHODIMP +nsBox::IsCollapsed(nsBoxLayoutState& aState, PRBool& aCollapsed) +{ + aCollapsed = PR_FALSE; + nsIBox::AddCSSCollapsed(aState, this, aCollapsed); + + return NS_OK; +} + +NS_IMETHODIMP +nsBox::Layout(nsBoxLayoutState& aState) +{ + SyncLayout(aState); + + return NS_OK; +} + +NS_IMETHODIMP +nsBox::GetOrientation(PRBool& aIsHorizontal) +{ + nsIFrame* frame = nsnull; + GetFrame(&frame); + nsFrameState state; + frame->GetFrameState(&state); + aIsHorizontal = (state & NS_STATE_IS_HORIZONTAL); + return NS_OK; +} + +nsresult +nsBox::SyncLayout(nsBoxLayoutState& aState) +{ + /* + PRBool collapsed = PR_FALSE; + IsCollapsed(aState, collapsed); + if (collapsed) { + CollapseChild(aState, this, PR_TRUE); + return NS_OK; + } + */ + + + PRBool dirty = PR_FALSE; + IsDirty(dirty); + if (dirty || aState.GetLayoutReason() == nsBoxLayoutState::Initial) + Redraw(aState); + + nsFrameState state; + nsIFrame* frame; + GetFrame(&frame); + frame->GetFrameState(&state); + state &= ~(NS_FRAME_HAS_DIRTY_CHILDREN | NS_FRAME_IS_DIRTY | NS_FRAME_FIRST_REFLOW); + frame->SetFrameState(state); + + nsIPresContext* presContext = aState.GetPresContext(); + nsRect rect(0,0,0,0); + GetBounds(rect); + nsIView* view; + frame->GetView(presContext, &view); + +/* + // only if the origin changed + if ((mX != rect.x) || (mY != rect.y)) { + if (view) { + nsContainerFrame::PositionFrameView(presContext, frame, view); + } else + nsContainerFrame::PositionChildViews(presContext, frame); + + mX = rect.x; + mY = rect.y; + } +*/ + + if (view) { + // Make sure the frame's view is properly sized and positioned and has + // things like opacity correct + nsHTMLContainerFrame::SyncFrameViewAfterReflow( + presContext, + frame, + view, + nsnull, + NS_FRAME_NO_MOVE_VIEW); + + } + + + return NS_OK; +} + +NS_IMETHODIMP +nsBox::Redraw(nsBoxLayoutState& aState, + const nsRect* aDamageRect, + PRBool aImmediate) +{ + nsIPresContext* presContext = aState.GetPresContext(); + const nsHTMLReflowState* s = aState.GetReflowState(); + if (s) { + if (s->reason != eReflowReason_Incremental) + return NS_OK; + } + + nsIFrame* frame = nsnull; + GetFrame(&frame); + + nsCOMPtr viewManager; + nsRect damageRect(0,0,0,0); + if (aDamageRect) + damageRect = *aDamageRect; + else + GetContentRect(damageRect); + + // Checks to see if the damaged rect should be infalted + // to include the outline + const nsStyleSpacing* spacing; + frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing); + nscoord width; + spacing->GetOutlineWidth(width); + if (width > 0) { + damageRect.Inflate(width, width); + } + + PRUint32 flags = aImmediate ? NS_VMREFRESH_IMMEDIATE : NS_VMREFRESH_NO_SYNC; + nsIView* view; + + frame->GetView(presContext, &view); + if (view) { + view->GetViewManager(*getter_AddRefs(viewManager)); + viewManager->UpdateView(view, damageRect, flags); + + } else { + nsRect rect(damageRect); + nsPoint offset; + + frame->GetOffsetFromView(presContext, offset, &view); + NS_ASSERTION(nsnull != view, "no view"); + rect += offset; + view->GetViewManager(*getter_AddRefs(viewManager)); + viewManager->UpdateView(view, rect, flags); + } + + return NS_OK; +} + +// nsISupports +NS_IMPL_ADDREF(nsBox); +NS_IMPL_RELEASE(nsBox); + +// +// QueryInterface +// +NS_INTERFACE_MAP_BEGIN(nsBox) + NS_INTERFACE_MAP_ENTRY(nsIBox) + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +PRBool +nsIBox::AddCSSPrefSize(nsBoxLayoutState& aState, nsIBox* aBox, nsSize& aSize) +{ + nsIPresContext* presContext = aState.GetPresContext(); + PRBool widthSet = PR_FALSE; + PRBool heightSet = PR_FALSE; + nsIFrame* frame = nsnull; + aBox->GetFrame(&frame); + + // add in the css min, max, pref + const nsStylePosition* position; + frame->GetStyleData(eStyleStruct_Position, + (const nsStyleStruct*&) position); + + // see if the width or height was specifically set + if (position->mWidth.GetUnit() == eStyleUnit_Coord) { + aSize.width = position->mWidth.GetCoordValue(); + widthSet = PR_TRUE; + } + + if (position->mHeight.GetUnit() == eStyleUnit_Coord) { + aSize.height = position->mHeight.GetCoordValue(); + heightSet = PR_TRUE; + } + + nsCOMPtr content; + frame->GetContent(getter_AddRefs(content)); + + if (content) { + nsAutoString value; + PRInt32 error; + + if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, value)) + { + float p2t; + presContext->GetScaledPixelsToTwips(&p2t); + + value.Trim("%"); + + aSize.width = NSIntPixelsToTwips(value.ToInteger(&error), p2t); + widthSet = PR_TRUE; + } + + if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::height, value)) + { + float p2t; + presContext->GetScaledPixelsToTwips(&p2t); + + value.Trim("%"); + + aSize.height = NSIntPixelsToTwips(value.ToInteger(&error), p2t); + heightSet = PR_TRUE; + } + } + + return (widthSet && heightSet); +} + + +PRBool +nsIBox::AddCSSMinSize(nsBoxLayoutState& aState, nsIBox* aBox, nsSize& aSize) +{ + nsIPresContext* presContext = aState.GetPresContext(); + + PRBool widthSet = PR_FALSE; + PRBool heightSet = PR_FALSE; + + nsIFrame* frame = nsnull; + aBox->GetFrame(&frame); + + // add in the css min, max, pref + const nsStylePosition* position; + frame->GetStyleData(eStyleStruct_Position, + (const nsStyleStruct*&) position); + + // same for min size. Unfortunately min size is always set to 0. So for now + // we will assume 0 means not set. + if (position->mMinWidth.GetUnit() == eStyleUnit_Coord) { + nscoord min = position->mMinWidth.GetCoordValue(); + if (min != 0) { + aSize.width = min; + widthSet = PR_TRUE; + } + } + + if (position->mMinHeight.GetUnit() == eStyleUnit_Coord) { + nscoord min = position->mMinHeight.GetCoordValue(); + if (min != 0) { + aSize.height = min; + heightSet = PR_TRUE; + } + } + + return (widthSet && heightSet); +} + +PRBool +nsIBox::AddCSSMaxSize(nsBoxLayoutState& aState, nsIBox* aBox, nsSize& aSize) +{ + nsIPresContext* presContext = aState.GetPresContext(); + + PRBool widthSet = PR_FALSE; + PRBool heightSet = PR_FALSE; + + nsIFrame* frame = nsnull; + aBox->GetFrame(&frame); + + // add in the css min, max, pref + const nsStylePosition* position; + frame->GetStyleData(eStyleStruct_Position, + (const nsStyleStruct*&) position); + + // and max + if (position->mMaxWidth.GetUnit() == eStyleUnit_Coord) { + nscoord max = position->mMaxWidth.GetCoordValue(); + aSize.width = max; + widthSet = PR_TRUE; + } + + if (position->mMaxHeight.GetUnit() == eStyleUnit_Coord) { + nscoord max = position->mMaxHeight.GetCoordValue(); + aSize.height = max; + heightSet = PR_TRUE; + } + + + return NS_OK; +} + +PRBool +nsIBox::AddCSSFlex(nsBoxLayoutState& aState, nsIBox* aBox, nscoord& aFlex) +{ + PRBool flexSet = PR_FALSE; + + nsIFrame* frame = nsnull; + aBox->GetFrame(&frame); + + // get the flexibility + nsCOMPtr content; + frame->GetContent(getter_AddRefs(content)); + + if (content) { + PRInt32 error; + nsAutoString value; + + if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::flex, value)) + { + value.Trim("%"); + aFlex = value.ToInteger(&error); + flexSet = PR_TRUE; + } + } + + return flexSet; +} + +PRBool +nsIBox::AddCSSCollapsed(nsBoxLayoutState& aState, nsIBox* aBox, PRBool& aCollapsed) +{ + nsIFrame* frame = nsnull; + aBox->GetFrame(&frame); + const nsStyleDisplay* disp; + frame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)disp)); + aCollapsed = disp->mVisible == NS_STYLE_VISIBILITY_COLLAPSE; + return PR_TRUE; +} + +void +nsBox::AddBorderAndPadding(nsSize& aSize) +{ + AddBorderAndPadding(this, aSize); +} + +void +nsBox::AddMargin(nsSize& aSize) +{ + AddMargin(this, aSize); +} + +void +nsBox::AddInset(nsSize& aSize) +{ + AddInset(this, aSize); +} + +void +nsBox::AddBorderAndPadding(nsIBox* aBox, nsSize& aSize) +{ + nsMargin borderPadding(0,0,0,0); + aBox->GetBorderAndPadding(borderPadding); + AddMargin(aSize, borderPadding); +} + +void +nsBox::AddMargin(nsIBox* aChild, nsSize& aSize) +{ + nsMargin margin(0,0,0,0); + aChild->GetMargin(margin); + AddMargin(aSize, margin); +} + +void +nsBox::AddMargin(nsSize& aSize, const nsMargin& aMargin) +{ + if (aSize.width != NS_INTRINSICSIZE) + aSize.width += aMargin.left + aMargin.right; + + if (aSize.height != NS_INTRINSICSIZE) + aSize.height += aMargin.top + aMargin.bottom; +} + +void +nsBox::AddInset(nsIBox* aBox, nsSize& aSize) +{ + nsMargin margin(0,0,0,0); + aBox->GetInset(margin); + AddMargin(aSize, margin); +} + +void +nsBox::BoundsCheck(nsSize& aMinSize, nsSize& aPrefSize, nsSize& aMaxSize) +{ + + if (aMinSize.width > aMaxSize.width) + aMinSize.width = aMaxSize.width; + + if (aMinSize.height > aMaxSize.height) + aMinSize.height = aMaxSize.height; + + +/* + if (aMinSize.width > aMaxSize.width) + aMaxSize.width = aMinSize.width; + + if (aMinSize.height > aMaxSize.height) + aMaxSize.height = aMinSize.height; +*/ + + if (aPrefSize.width > aMaxSize.width) + aPrefSize.width = aMaxSize.width; + + if (aPrefSize.height > aMaxSize.height) + aPrefSize.height = aMaxSize.height; + + if (aPrefSize.width < aMinSize.width) + aPrefSize.width = aMinSize.width; + + if (aPrefSize.height < aMinSize.height) + aPrefSize.height = aMinSize.height; +} + +NS_IMETHODIMP +nsBox::GetDebugBoxAt( const nsPoint& aPoint, + nsIBox** aBox) +{ + nsPoint tmp; + + nsRect rect; + GetBounds(rect); + + if (!rect.Contains(aPoint)) + return NS_ERROR_FAILURE; + + nsIBox* child = nsnull; + nsIBox* hit = nsnull; + GetChildBox(&child); + + *aBox = nsnull; + tmp.MoveTo(aPoint.x - rect.x, aPoint.y - rect.y); + while (nsnull != child) { + nsresult rv = child->GetDebugBoxAt(tmp, &hit); + + if (NS_SUCCEEDED(rv) && hit) { + *aBox = hit; + } + child->GetNextBox(&child); + } + + // found a child + if (*aBox) { + return NS_OK; + } + + // see if it is in our in our insets + nsMargin m; + GetBorderAndPadding(m); + rect.Deflate(m); + if (rect.Contains(aPoint)) { + GetInset(m); + rect.Deflate(m); + if (!rect.Contains(aPoint)) { + *aBox = this; + return NS_OK; + } + } + + return NS_ERROR_FAILURE; +} + + +NS_IMETHODIMP +nsBox::GetDebug(PRBool& aDebug) +{ + aDebug = PR_FALSE; + return NS_OK; +} + diff --git a/mozilla/layout/xul/base/src/nsBox.h b/mozilla/layout/xul/base/src/nsBox.h new file mode 100644 index 00000000000..995534b96e1 --- /dev/null +++ b/mozilla/layout/xul/base/src/nsBox.h @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Author: + * Eric D Vaughan + * + * Contributor(s): + */ + +#ifndef nsBox_h___ +#define nsBox_h___ + +#include "nsIBox.h" + +class nsBox : public nsIBox { + +public: + + NS_DECL_ISUPPORTS + + NS_IMETHOD GetChildBox(nsIBox** aBox); + NS_IMETHOD GetNextBox(nsIBox** aBox); + NS_IMETHOD SetNextBox(nsIBox* aBox); + NS_IMETHOD GetParentBox(nsIBox** aParent); + NS_IMETHOD SetParentBox(nsIBox* aParent); + NS_IMETHOD IsDirty(PRBool& aIsDirty); + NS_IMETHOD HasDirtyChildren(PRBool& aIsDirty); + NS_IMETHOD MarkDirty(nsBoxLayoutState& aState); + NS_IMETHOD MarkDirtyChildren(nsBoxLayoutState& aState); + NS_IMETHOD SetDebug(nsBoxLayoutState& aState, PRBool aDebug); + NS_IMETHOD SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect); + NS_IMETHOD GetBounds(nsRect& aRect); + NS_IMETHOD GetBorderAndPadding(nsMargin& aBorderAndPadding); + NS_IMETHOD GetBorder(nsMargin& aBorderAndPadding); + NS_IMETHOD GetPadding(nsMargin& aBorderAndPadding); + + NS_IMETHOD GetMargin(nsMargin& aMargin); + NS_IMETHOD SetLayoutManager(nsIBoxLayout* aLayout); + NS_IMETHOD GetLayoutManager(nsIBoxLayout** aLayout); + NS_IMETHOD GetContentRect(nsRect& aContentRect); + NS_IMETHOD GetClientRect(nsRect& aContentRect); + NS_IMETHOD GetVAlign(Valignment& aAlign); + NS_IMETHOD GetHAlign(Halignment& aAlign); + NS_IMETHOD GetInset(nsMargin& aInset); + NS_IMETHOD GetOrientation(PRBool& aIsHorizontal); + + NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetFlex(nsBoxLayoutState& aBoxLayoutState, nscoord& aFlex); + NS_IMETHOD GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent); + NS_IMETHOD IsCollapsed(nsBoxLayoutState& aBoxLayoutState, PRBool& aCollapsed); + NS_IMETHOD Collapse(nsBoxLayoutState& aBoxLayoutState); + NS_IMETHOD UnCollapse(nsBoxLayoutState& aBoxLayoutState); + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); + NS_IMETHOD Redraw(nsBoxLayoutState& aState, const nsRect* aRect = nsnull, PRBool aImmediate = PR_FALSE); + NS_IMETHOD NeedsRecalc(); + NS_IMETHOD GetDebugBoxAt(const nsPoint& aPoint, nsIBox** aBox); + NS_IMETHOD GetDebug(PRBool& aDebug); + + nsBox(nsIPresShell* aShell); + + virtual nsresult SyncLayout(nsBoxLayoutState& aBoxLayoutState); + + virtual PRBool DoesNeedRecalc(const nsSize& aSize); + virtual PRBool DoesNeedRecalc(nscoord aCoord); + virtual void SizeNeedsRecalc(nsSize& aSize); + virtual void CoordNeedsRecalc(nscoord& aCoord); + + virtual void AddBorderAndPadding(nsSize& aSize); + virtual void AddInset(nsSize& aSize); + virtual void AddMargin(nsSize& aSize); + + static void AddBorderAndPadding(nsIBox* aBox, nsSize& aSize); + static void AddInset(nsIBox* aBox, nsSize& aSize); + static void AddMargin(nsIBox* aChild, nsSize& aSize); + static void AddMargin(nsSize& aSize, const nsMargin& aMargin); + + static nsresult UnCollapseChild(nsBoxLayoutState& aState, nsIBox* aFrame); + static nsresult CollapseChild(nsBoxLayoutState& aState, nsIFrame* aFrame, PRBool aHide); + + static void BoundsCheck(nsSize& aMinSize, nsSize& aPrefSize, nsSize& aMaxSize); + +protected: + virtual PRBool GetWasCollapsed(nsBoxLayoutState& aState); + virtual void SetWasCollapsed(nsBoxLayoutState& aState, PRBool aWas); + + enum eMouseThrough { + never, + sometimes, + always + }; + + eMouseThrough mMouseThrough; +private: + + nsIBox* mNextChild; + nsIBox* mParentBox; + //nscoord mX; + //nscoord mY; +}; + +#endif + diff --git a/mozilla/layout/xul/base/src/nsBoxFrame.cpp b/mozilla/layout/xul/base/src/nsBoxFrame.cpp index 688bfc77255..e6c8be56244 100644 --- a/mozilla/layout/xul/base/src/nsBoxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsBoxFrame.cpp @@ -46,9 +46,9 @@ // Boxes layout out top down by adding up their childrens min, max, and preferred sizes. Only problem is if a incremental // reflow occurs. The preferred size of a child deep in the hierarchy could change. And this could change // any number of syblings around the box. Basically any children in the reflow chain must have their caches cleared -// so when asked for there current size they can relayout themselves. Thats where the Dirty method comes in. This -// moves down the reflow chain until it reaches something that is not a box marking each child as being dirty. +// so when asked for there current size they can relayout themselves. +#include "nsBoxLayoutState.h" #include "nsBoxFrame.h" #include "nsIStyleContext.h" #include "nsIPresContext.h" @@ -71,6 +71,9 @@ #include "nsISelfScrollingFrame.h" #include "nsIPref.h" #include "nsIServiceManager.h" +#include "nsBoxToBlockAdaptor.h" +#include "nsIBoxLayout.h" +#include "nsSprocketLayout.h" #define CONSTANT 0 //#define DEBUG_REFLOW @@ -81,88 +84,6 @@ //#define TEST_SANITY -/** - * Only created when the box is in debug mode - */ -class nsBoxDebug -{ -public: - - nsBoxDebug(nsIPresContext* aPresContext, nsBoxFrame* aBoxFrame); - - static void AddRef(nsIPresContext* aPresContext, nsBoxFrame* aBox); - static void Release(nsIPresContext* aPresContext); - static void GetPref(nsIPresContext* aPresContext); - - void GetValue(nsIPresContext* aPresContext, const nsSize& a, const nsSize& b, char* value); - void GetValue(nsIPresContext* aPresContext, PRInt32 a, PRInt32 b, char* value); - void DrawSpring(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, PRBool aHorizontal, PRInt32 flex, nscoord x, nscoord y, nscoord size, nscoord springSize); - void PaintSprings(nsIPresContext* aPresContext, nsBoxFrame* aBoxFrame, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect); - void DrawLine(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x1, nscoord y1, nscoord x2, nscoord y2); - void FillRect(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x, nscoord y, nscoord width, nscoord height); - - PRBool DisplayDebugInfoFor(nsIPresContext* aPresContext, - nsBoxFrame* aBoxFrame, - nsPoint& aPoint, - PRInt32& aCursor); - - nsCOMPtr mHorizontalDebugStyle; - nsCOMPtr mVerticalDebugStyle; - PRInt32 mRefCount; - nsIFrame* mDebugChild; - - static PRBool gDebug; - static nsBoxDebug* gInstance; -}; - -PRBool nsBoxDebug::gDebug = PR_FALSE; -nsBoxDebug* nsBoxDebug::gInstance = nsnull; - -class nsInfoListImpl: public nsInfoList -{ -public: - void* operator new(size_t sz, nsIPresShell* aPresShell); - void operator delete(void* aPtr, size_t sz); - void Recycle(nsIPresShell* aShell); - - nsInfoListImpl(); - virtual ~nsInfoListImpl(); - virtual nsCalculatedBoxInfo* GetFirst(); - virtual nsCalculatedBoxInfo* GetLast(); - virtual PRInt32 GetCount(); - virtual nsresult SetDebug(nsIPresContext* aPresContext, PRBool aDebug); - - void Clear(nsIPresShell* aShell); - PRInt32 CreateInfosFor(nsIPresShell* aShell, nsIFrame* aList, nsCalculatedBoxInfo*& first, nsCalculatedBoxInfo*& last); - void RemoveAfter(nsIPresShell* aShell, nsCalculatedBoxInfo* aPrev); - void Remove(nsIPresShell* aShell, nsIFrame* aChild); - void Prepend(nsIPresShell* aShell, nsIFrame* aList); - void Append(nsIPresShell* aShell, nsIFrame* aList); - void Insert(nsIPresShell* aShell, nsIFrame* aPrevFrame, nsIFrame* aList); - void InsertAfter(nsIPresShell* aShell, nsCalculatedBoxInfo* aPrev, nsIFrame* aList); - void Init(nsIPresShell* aShell, nsIFrame* aList); - nsCalculatedBoxInfo* GetPrevious(nsIFrame* aChild); - nsCalculatedBoxInfo* GetInfo(nsIFrame* aChild); - void SanityCheck(nsFrameList& aFrameList); - - - nsCalculatedBoxInfo* mFirst; - nsCalculatedBoxInfo* mLast; - PRInt32 mCount; -}; - -class nsCalculatedBoxInfoImpl: public nsCalculatedBoxInfo -{ -public: - nsCalculatedBoxInfoImpl(nsIFrame* aFrame); - virtual ~nsCalculatedBoxInfoImpl(); - nsCalculatedBoxInfoImpl(const nsBoxInfo& aInfo); - virtual void Clear(); - void* operator new(size_t sz, nsIPresShell* aPresShell); - void operator delete(void* aPtr, size_t sz); - virtual void Recycle(nsIPresShell* aShell); -}; - /** * The boxes private implementation */ @@ -172,14 +93,16 @@ public: nsBoxFrameInner(nsIPresShell* aPresShell, nsBoxFrame* aThis) { mOuter = aThis; - mInfoList = new (aPresShell) nsInfoListImpl(); - } ~nsBoxFrameInner() { } + //----- Sibling/Child ---- + + nsresult SetDebug(nsIPresContext* aPresContext, PRBool aDebug); + void Recycle(nsIPresShell* aPresShell); // Overloaded new operator. Initializes the memory to 0 and relies on an arena @@ -193,69 +116,62 @@ public: void operator delete(void* aPtr, size_t sz); // helper methods - static void* Allocate(size_t sz, nsIPresShell* aPresShell); - static void Free(void* aPtr, size_t sz); - static void RecycleFreedMemory(nsIPresShell* aPresShell, void* mem); - void GetDebugInset(nsMargin& inset); - void AdjustChildren(nsIPresContext* aPresContext, nsBoxFrame* aBox); - nsresult GetContentOf(nsIFrame* aFrame, nsIContent** aContent); - void SanityCheck(); - - nsresult FlowChildren(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame*& aIncrementalChild, - nsRect& aRect, - nsSize& aActualSize, - nscoord& aMaxAscent); - - nsresult FlowChildAt(nsIFrame* frame, - nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsCalculatedBoxInfo& aInfo, - nscoord aX, - nscoord aY, - PRBool aMoveFrame, - nsIFrame*& aIncrementalChild, - PRBool& needsRedraw, - const nsString& aReason); - - void PlaceChild(nsIPresContext* aPresContext, nsIFrame* aFrame, nscoord aX, nscoord aY); void TranslateEventCoords(nsIPresContext* aPresContext, const nsPoint& aPoint, nsPoint& aResult); - static void InvalidateCachesTo(nsIFrame* aTargetFrame); - static void InvalidateAllCachesBelow(nsIPresContext* aPresContext, nsIFrame* aTargetFrame); static PRBool AdjustTargetToScope(nsIFrame* aParent, nsIFrame*& aTargetFrame); + PRBool GetInitialDebug(PRBool& aDebug); + void GetDebugPref(nsIPresContext* aPresContext); + + nsresult PaintDebug(nsIBox* aBox, + nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + + nsresult DisplayDebugInfoFor(nsIBox* aBox, + nsIPresContext* aPresContext, + nsPoint& aPoint, + PRInt32& aCursor); + + nsresult GetFrameSizeWithMargin(nsIBox* aBox, nsSize& aSize); + + void GetDebugBorder(nsMargin& aInset); + void GetDebugPadding(nsMargin& aInset); + void GetDebugMargin(nsMargin& aInset); + void PixelMarginToTwips(nsIPresContext* aPresContext, nsMargin& aMarginPixels); + + void GetValue(nsIPresContext* aPresContext, const nsSize& a, const nsSize& b, char* value); + void GetValue(nsIPresContext* aPresContext, PRInt32 a, PRInt32 b, char* value); + void DrawSpring(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, PRBool aHorizontal, PRInt32 flex, nscoord x, nscoord y, nscoord size, nscoord springSize); + void DrawLine(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x1, nscoord y1, nscoord x2, nscoord y2); + void FillRect(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x, nscoord y, nscoord width, nscoord height); + nsBoxFrame::Halignment GetHAlign(); nsBoxFrame::Valignment GetVAlign(); - void InitializeReflowState(nsIPresContext* aPresContext, const nsCalculatedBoxInfo& aInfo, nsHTMLReflowState& aReflowState, const nsHTMLReflowState& aParentReflowState, nsIFrame* aFrame, const nsSize& aAvailSize, nsReflowReason reason); - void CreateResizedArray(PRBool*& aResized, PRInt32 aCount); - -#ifdef DEBUG_REFLOW - void MakeReason(nsIFrame* aFrame, const nsString& aText, nsString& aReason); - void AddIndents(); -#endif - - nsCOMPtr mSpaceManager; // We own this [OWNER]. nsBoxFrame* mOuter; - nsInfoListImpl* mInfoList; - - // XXX make these flags! nscoord mInnerSize; nsBoxFrame::Valignment mValign; nsBoxFrame::Halignment mHalign; + + nsSize mPrefSize; + nsSize mMinSize; + nsSize mMaxSize; + nscoord mFlex; + nscoord mAscent; + nsIPresContext* mPresContext; + + static PRBool gDebug; + static nsIBox* mDebugChild; + #ifdef DEBUG_REFLOW PRInt32 reflowCount; @@ -263,6 +179,9 @@ public: }; +PRBool nsBoxFrameInner::gDebug = PR_FALSE; +nsIBox* nsBoxFrameInner::mDebugChild = nsnull; + #ifdef DEBUG_REFLOW PRInt32 gIndent = 0; @@ -270,12 +189,6 @@ PRInt32 gReflows = 0; #endif -#define GET_WIDTH(size) (IsHorizontal() ? size.width : size.height) -#define GET_HEIGHT(size) (IsHorizontal() ? size.height : size.width) - -#define SET_WIDTH(size, coord) if (IsHorizontal()) { (size).width = (coord); } else { (size).height = (coord); } -#define SET_HEIGHT(size, coord) if (IsHorizontal()) { (size).height = (coord); } else { (size).width = (coord); } - nsresult NS_NewBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoot) { @@ -284,6 +197,7 @@ NS_NewBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoot) return NS_ERROR_NULL_POINTER; } nsBoxFrame* it = new (aPresShell) nsBoxFrame(aPresShell, aIsRoot); + if (nsnull == it) return NS_ERROR_OUT_OF_MEMORY; @@ -292,7 +206,7 @@ NS_NewBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoot) } // NS_NewBoxFrame -nsBoxFrame::nsBoxFrame(nsIPresShell* aPresShell, PRBool aIsRoot) +nsBoxFrame::nsBoxFrame(nsIPresShell* aPresShell, PRBool aIsRoot):nsContainerBox(aPresShell) { mInner = new (aPresShell) nsBoxFrameInner(aPresShell, this); @@ -300,71 +214,23 @@ nsBoxFrame::nsBoxFrame(nsIPresShell* aPresShell, PRBool aIsRoot) mState |= NS_STATE_IS_HORIZONTAL; mState |= NS_STATE_AUTO_STRETCH; - if (aIsRoot) + if (aIsRoot) mState |= NS_STATE_IS_ROOT; mInner->mValign = nsBoxFrame::vAlign_Top; mInner->mHalign = nsBoxFrame::hAlign_Left; mInner->mInnerSize = 0; + NeedsRecalc(); + + nsSprocketLayout* layout = new nsSprocketLayout(aPresShell); + SetLayoutManager(layout); + #ifdef DEBUG_REFLOW mInner->reflowCount = 100; #endif } -void* -nsBoxFrameInner::operator new(size_t sz, nsIPresShell* aPresShell) -{ - return nsBoxFrameInner::Allocate(sz,aPresShell); -} - -void -nsBoxFrameInner::Recycle(nsIPresShell* aPresShell) -{ - // recyle out info list. - mInfoList->Recycle(aPresShell); - delete this; - nsBoxFrameInner::RecycleFreedMemory(aPresShell, this); -} - -// Overridden to prevent the global delete from being called, since the memory -// came out of an nsIArena instead of the global delete operator's heap. -void -nsBoxFrameInner::operator delete(void* aPtr, size_t sz) -{ - nsBoxFrameInner::Free(aPtr, sz); -} - -void* -nsBoxFrameInner::Allocate(size_t sz, nsIPresShell* aPresShell) -{ - // Check the recycle list first. - void* result = nsnull; - aPresShell->AllocateFrame(sz, &result); - - if (result) { - nsCRT::zero(result, sz); - } - - return result; -} - -// Overridden to prevent the global delete from being called, since the memory -// came out of an nsIArena instead of the global delete operator's heap. -void -nsBoxFrameInner::Free(void* aPtr, size_t sz) -{ - // Don't let the memory be freed, since it will be recycled - // instead. Don't call the global operator delete. - - // Stash the size of the object in the first four bytes of the - // freed up memory. The Destroy method can then use this information - // to recycle the object. - size_t* szPtr = (size_t*)aPtr; - *szPtr = sz; -} - - nsBoxFrame::~nsBoxFrame() { NS_ASSERTION(mInner == nsnull,"Error Destroy was never called on this Frame!!!"); @@ -372,57 +238,49 @@ nsBoxFrame::~nsBoxFrame() NS_IMETHODIMP -nsBoxFrame::InvalidateCache(nsIFrame* aChild) +nsBoxFrame::GetVAlign(Valignment& aAlign) { - nsCalculatedBoxInfo* info = mInner->mInfoList->GetFirst(); - - // if the child is null then blow away all caches. Otherwise just blow away the - // specified kids cache. - if (aChild == nsnull) { - while(info != nsnull) { - info->mFlags |= NS_FRAME_BOX_NEEDS_RECALC; - info = info->next; - } - } else { - while(info != nsnull) { - if (info->frame == aChild) { - info->mFlags |= NS_FRAME_BOX_NEEDS_RECALC; - return NS_OK; - } - info = info->next; - } - } - + aAlign = mInner->mValign; return NS_OK; } +NS_IMETHODIMP +nsBoxFrame::GetHAlign(Halignment& aAlign) +{ + aAlign = mInner->mHalign; + return NS_OK; +} NS_IMETHODIMP nsBoxFrame::SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList) { - mInner->SanityCheck(); - - nsresult r = nsHTMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); + SanityCheck(mFrames); nsCOMPtr shell; aPresContext->GetShell(getter_AddRefs(shell)); - // initialize our list of infos. - mInner->mInfoList->Init(shell, aChildList); + nsresult r = nsHTMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); + if (r == NS_OK) { + // initialize our list of infos. + InitChildren(shell, aChildList); + } else { + printf("Warning add child failed!!\n"); + } - mInner->SanityCheck(); + SanityCheck(mFrames); return r; } - -PRBool nsBoxFrame::IsHorizontal() const +PRBool +nsBoxFrame::IsHorizontal() const { return mState & NS_STATE_IS_HORIZONTAL; } + /** * Initialize us. This is a good time to get the alignment of the box */ @@ -433,13 +291,11 @@ nsBoxFrame::Init(nsIPresContext* aPresContext, nsIStyleContext* aContext, nsIFrame* aPrevInFlow) { + mInner->mPresContext = aPresContext; + nsresult rv = nsHTMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - - - nsSpaceManager* spaceManager = new nsSpaceManager(this); - mInner->mSpaceManager = spaceManager; - + mInner->mValign = nsBoxFrame::vAlign_Top; mInner->mHalign = nsBoxFrame::hAlign_Left; @@ -476,25 +332,36 @@ nsBoxFrame::Init(nsIPresContext* aPresContext, // if we are root and this if (mState & NS_STATE_IS_ROOT) - nsBoxDebug::GetPref(aPresContext); + mInner->GetDebugPref(aPresContext); + + + mMouseThrough = always; + + if (mContent) { + nsAutoString value; + if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::mousethrough, value)) { + if (value.EqualsIgnoreCase("never")) + mMouseThrough = never; + else if (value.EqualsIgnoreCase("always")) + mMouseThrough = always; + + } + } return rv; } -PRBool -nsBoxFrame::GetDefaultFlex(PRInt32& aFlex) -{ - aFlex = 0; - return PR_TRUE; -} - PRBool nsBoxFrameInner::GetInitialDebug(PRBool& aDebug) { - nsString value; + nsAutoString value; nsCOMPtr content; - GetContentOf(mOuter, getter_AddRefs(content)); + mOuter->GetContentOf(getter_AddRefs(content)); + + if (!content) + return PR_FALSE; + if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::debug, value)) { if (value.EqualsIgnoreCase("true")) { @@ -515,7 +382,9 @@ nsBoxFrame::GetInitialHAlignment(nsBoxFrame::Halignment& aHalign) nsAutoString value; nsCOMPtr content; - mInner->GetContentOf(this, getter_AddRefs(content)); + GetContentOf(getter_AddRefs(content)); + if (!content) + return PR_FALSE; if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::align, value)) { if (value.EqualsIgnoreCase("left")) { @@ -563,7 +432,9 @@ nsBoxFrame::GetInitialVAlignment(nsBoxFrame::Valignment& aValign) nsAutoString value; nsCOMPtr content; - mInner->GetContentOf(this, getter_AddRefs(content)); + GetContentOf(getter_AddRefs(content)); + if (!content) + return PR_FALSE; if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::valign, value)) { if (value.EqualsIgnoreCase("top")) { @@ -627,7 +498,10 @@ nsBoxFrame::GetInitialOrientation(PRBool& aIsHorizontal) nsAutoString value; nsCOMPtr content; - mInner->GetContentOf(this, getter_AddRefs(content)); + GetContentOf(getter_AddRefs(content)); + + if (!content) + return PR_FALSE; if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::orient, value)) { @@ -662,7 +536,10 @@ nsBoxFrame::GetInitialAutoStretch(PRBool& aStretch) nsAutoString value; nsCOMPtr content; - mInner->GetContentOf(this, getter_AddRefs(content)); + GetContentOf(getter_AddRefs(content)); + + if (!content) + return PR_FALSE; if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::autostretch, value)) { @@ -678,888 +555,245 @@ nsBoxFrame::GetInitialAutoStretch(PRBool& aStretch) return PR_FALSE; } -nsInfoList* -nsBoxFrame::GetInfoList() -{ - return mInner->mInfoList; -} - - - - -void -nsBoxFrame::GetInnerRect(nsRect& aInner) -{ - const nsStyleSpacing* spacing; - - GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - nsMargin border(0,0,0,0); - spacing->GetBorderPadding(border); - - aInner = mRect; - aInner.x = 0; - aInner.y = 0; - aInner.Deflate(border); - - border.SizeTo(0,0,0,0); - mInner->GetDebugInset(border); - aInner.Deflate(border); -} - -/** - * Looks at the given frame and sees if its redefined preferred, min, or max sizes - * if so it used those instead. Currently it gets its values from css - */ -void -nsBoxFrame::GetRedefinedMinPrefMax(nsIPresContext* aPresContext, nsIFrame* aFrame, nsCalculatedBoxInfo& aSize) -{ - // add in the css min, max, pref - const nsStylePosition* position; - aFrame->GetStyleData(eStyleStruct_Position, - (const nsStyleStruct*&) position); - - // see if the width or height was specifically set - if (position->mWidth.GetUnit() == eStyleUnit_Coord) { - aSize.prefSize.width = position->mWidth.GetCoordValue(); - //aSize.prefWidthIntrinsic = PR_FALSE; - } - - if (position->mHeight.GetUnit() == eStyleUnit_Coord) { - aSize.prefSize.height = position->mHeight.GetCoordValue(); - //aSize.prefHeightIntrinsic = PR_FALSE; - } - - // same for min size. Unfortunately min size is always set to 0. So for now - // we will assume 0 means not set. - if (position->mMinWidth.GetUnit() == eStyleUnit_Coord) { - nscoord min = position->mMinWidth.GetCoordValue(); - if (min != 0) - aSize.minSize.width = min; - } - - if (position->mMinHeight.GetUnit() == eStyleUnit_Coord) { - nscoord min = position->mMinHeight.GetCoordValue(); - if (min != 0) - aSize.minSize.height = min; - } - - // and max - if (position->mMaxWidth.GetUnit() == eStyleUnit_Coord) { - nscoord max = position->mMaxWidth.GetCoordValue(); - aSize.maxSize.width = max; - } - - if (position->mMaxHeight.GetUnit() == eStyleUnit_Coord) { - nscoord max = position->mMaxHeight.GetCoordValue(); - aSize.maxSize.height = max; - } - - // get the flexibility - nsCOMPtr content; - aFrame->GetContent(getter_AddRefs(content)); - - if (content) { - PRInt32 error; - nsAutoString value; - - if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::flex, value)) - { - value.Trim("%"); - aSize.flex = value.ToInteger(&error); - } - - if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, value)) - { - float p2t; - aPresContext->GetScaledPixelsToTwips(&p2t); - - value.Trim("%"); - - aSize.prefSize.width = NSIntPixelsToTwips(value.ToInteger(&error), p2t); - } - - if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::height, value)) - { - float p2t; - aPresContext->GetScaledPixelsToTwips(&p2t); - - value.Trim("%"); - - aSize.prefSize.height = NSIntPixelsToTwips(value.ToInteger(&error), p2t); - } - } - - // make sure pref size is inside min and max values. - if (aSize.prefSize.width < aSize.minSize.width) - aSize.prefSize.width = aSize.minSize.width; - - if (aSize.prefSize.height < aSize.minSize.height) - aSize.prefSize.height = aSize.minSize.height; - - if (aSize.prefSize.width > aSize.maxSize.width) - aSize.prefSize.width = aSize.maxSize.width; - - if (aSize.prefSize.height > aSize.maxSize.height) - aSize.prefSize.height = aSize.maxSize.height; - - - // if we are not flexible then our min, max, and pref sizes are all the same. - // if (aSize.flex == 0) { - // SET_WIDTH(aSize.minSize, GET_WIDTH(aSize.prefSize)); - /// SET_WIDTH(aSize.maxSize, GET_WIDTH(aSize.prefSize)); - /// } - -} - -/** - * Given a frame gets its box info. If it does not have a box info then it will merely - * get the normally defined min, pref, max stuff. - * - */ -nsresult -nsBoxFrame::GetChildBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame* aFrame, nsCalculatedBoxInfo& aSize) -{ -#ifdef DEBUG_REFLOW - gIndent++; -#endif - - nsIFrame* incrementalChild; - if (aReflowState.reason == eReflowReason_Incremental) { - // then get the child we need to flow incrementally - aReflowState.reflowCommand->GetNext(incrementalChild, PR_FALSE); - } - - aSize.Clear(); - - // see if the frame Innerements IBox interface - - // since frames are not refCounted, don't use nsCOMPtr with them - // if it does ask it for its BoxSize and we are done - nsIBox* ibox = nsnull; - if (NS_SUCCEEDED(aFrame->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) { - if (aReflowState.reason == eReflowReason_Incremental) { - // then get the child we need to flow incrementally - if (incrementalChild == aFrame) { - aReflowState.reflowCommand->GetNext(incrementalChild); - // dirty the incremental child - nsFrameState childState; - aFrame->GetFrameState(&childState); - childState |= NS_FRAME_IS_DIRTY; - aFrame->SetFrameState(childState); - } - } - ibox->GetBoxInfo(aPresContext, aReflowState, aSize); - aSize.mFlags |= NS_FRAME_IS_BOX; - // add in the border, padding, width, min, max - GetRedefinedMinPrefMax(aPresContext, aFrame, aSize); - -#ifdef DEBUG_REFLOW - gIndent--; -#endif - return NS_OK; - } - - // so the child is not a box. So we will have to be creative. We need to get its min, max, and preferred - // sizes. Min and Max are easy you get them for CSS. But preferred size? First we will see if they are set in - // css. If not we will have to flow the child intrinically. - - // start the preferred size as intrinsic - aSize.prefSize.width = NS_INTRINSICSIZE; - aSize.prefSize.height = NS_INTRINSICSIZE; - - // redefine anything depending on css - GetRedefinedMinPrefMax(aPresContext, aFrame, aSize); - - // if we are still intrinsically sized the flow to get the size otherwise - // we are done. - if (aSize.prefSize.width == NS_INTRINSICSIZE || aSize.prefSize.height == NS_INTRINSICSIZE) - { - // subtract out the childs margin and border - const nsStyleSpacing* spacing; - nsresult rv = aFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - NS_ASSERTION(rv == NS_OK,"failed to get spacing"); - if (NS_FAILED(rv)) - return rv; - - nsMargin margin(0,0,0,0);; - spacing->GetMargin(margin); - nsMargin border(0,0,0,0); - spacing->GetBorderPadding(border); - nsMargin total = margin + border; - - // add in childs margin and border - if (aSize.prefSize.width != NS_INTRINSICSIZE) - aSize.prefSize.width += (total.left + total.right); - - if (aSize.prefSize.height != NS_INTRINSICSIZE) - aSize.prefSize.height += (total.top + total.bottom); - - - // flow child at preferred size - nsHTMLReflowMetrics desiredSize(nsnull); - - aSize.calculatedSize = aSize.prefSize; - - - nsReflowStatus status; - PRBool redraw; - nsAutoString reason("To get pref size"); - - nsHTMLReflowState state(aReflowState); - state.availableWidth = NS_INTRINSICSIZE; - state.availableHeight = NS_INTRINSICSIZE; - //state.reason = eReflowReason_Resize; - - nsIFrame* incrementalChild = nsnull; - - mInner->FlowChildAt(aFrame, aPresContext, desiredSize, state, status, aSize, 0, 0, PR_FALSE, incrementalChild, redraw, reason); - - // remove margin and border - desiredSize.height -= (total.top + total.bottom); - desiredSize.width -= (total.left + total.right); - - // get the size returned and the it as the preferredsize. - aSize.prefSize.width = desiredSize.width; - aSize.prefSize.height = desiredSize.height; - aSize.ascent = desiredSize.ascent; - -#ifdef DEBUG_REFLOW - mInner->AddIndents(); - printf("pref-size: (%d,%d)\n", aSize.prefSize.width, aSize.prefSize.height); -#endif - - // aSize.prefSize.width = 0; - // aSize.prefSize.height = 0; - - // redefine anything depending on css - GetRedefinedMinPrefMax(aPresContext, aFrame, aSize); - } - -#ifdef DEBUG_REFLOW - gIndent--; -#endif - - return NS_OK; -} NS_IMETHODIMP nsBoxFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild) { - InvalidateCache(aChild); - // if we are not dirty mark ourselves dirty and tell our parent we are dirty too. - if (!(mState & NS_FRAME_IS_DIRTY)) { - // Mark yourself as dirty - mState |= NS_FRAME_IS_DIRTY; + if (!(mState & NS_FRAME_HAS_DIRTY_CHILDREN)) { + // Mark yourself as dirty and needing to be recalculated + mState |= NS_FRAME_HAS_DIRTY_CHILDREN; + NeedsRecalc(); return mParent->ReflowDirtyChild(aPresShell, this); } return NS_OK; } - -/* -void -nsIBox::HandleRootBoxReflow(nsIPresContext* aPresContext, - nsIFrame* aBox, - const nsHTMLReflowState& aReflowState) +NS_IMETHODIMP +nsBoxFrame::DidReflow(nsIPresContext* aPresContext, + nsDidReflowStatus aStatus) { - // if its an incremental reflow - if ( aReflowState.reason == eReflowReason_Incremental ) { + PRBool isDirty = mState & NS_FRAME_IS_DIRTY; + PRBool hasDirtyChildren = mState & NS_FRAME_HAS_DIRTY_CHILDREN; + nsresult rv = nsFrame::DidReflow(aPresContext, aStatus); + if (isDirty) + mState |= NS_FRAME_IS_DIRTY; - nsIReflowCommand::ReflowType reflowType; - aReflowState.reflowCommand->GetType(reflowType); + if (hasDirtyChildren) + mState |= NS_FRAME_HAS_DIRTY_CHILDREN; - // See if it's targeted at us - nsIFrame* targetFrame; - aReflowState.reflowCommand->GetTarget(targetFrame); + return rv; - if (aBox != targetFrame) { - // clear the caches down the chain - nsBoxFrameInner::InvalidateCachesTo(targetFrame); - - // if the type is style changed then make sure we - // invalidate all caches under the target - if (reflowType == nsIReflowCommand::StyleChanged) - nsBoxFrameInner::InvalidateAllCachesBelow(aPresContext, targetFrame); - } - } } -*/ - -/** - * Ok what we want to do here is get all the children, figure out - * their flexibility, preferred, min, max sizes and then stretch or - * shrink them to fit in the given space. - * - * So we will have 3 passes. - * 1) get our min,max,preferred size. - * 2) flow all our children to fit into the size we are given layout in - * 3) move all the children to the right locations. - */ NS_IMETHODIMP nsBoxFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + #ifdef DEBUG_REFLOW + gIndent++; + #endif -#ifdef DEBUG_REFLOW - gIndent++; -#endif + NS_ASSERTION(aReflowState.mComputedWidth >=0 && aReflowState.mComputedHeight >= 0, "Computed Size < 0"); - - mInner->SanityCheck(); - - // If we have a space manager, then set it in the reflow state - if (mInner->mSpaceManager) { - // Modify the reflow state and set the space manager - nsHTMLReflowState& reflowState = (nsHTMLReflowState&)aReflowState; - reflowState.mSpaceManager = mInner->mSpaceManager; - - // Clear the spacemanager's regions. - mInner->mSpaceManager->ClearRegions(); - } - - //-------------------------------------------------------------------- - //-------------- figure out the rect we need to fit into ------------- - //-------------------------------------------------------------------- - - // this is the size of our box. Remember to subtract our our border. The size we are given - // does not include it. So we have to adjust our rect accordingly. - - nscoord x = aReflowState.mComputedBorderPadding.left; - nscoord y = aReflowState.mComputedBorderPadding.top; - - nsRect rect(x,y,aReflowState.mComputedWidth,aReflowState.mComputedHeight); - - //--------------------------------------------------------- - //------- handle incremental reflow -------------------- - //--------------------------------------------------------- - nsIFrame* incrementalChild = nsnull; - - // update our debug state if it needs it. - // see if the debug was set. If it was then propagate it - // if it wasn't and we are root then get it from the global pref. - if (mState & NS_STATE_DEBUG_WAS_SET) { - if (mState & NS_STATE_SET_TO_DEBUG) - SetDebug(aPresContext, PR_TRUE); - else - SetDebug(aPresContext, PR_FALSE); - } else if (mState & NS_STATE_IS_ROOT) { - SetDebug(aPresContext, nsBoxDebug::gDebug); - } - - if ( aReflowState.reason == eReflowReason_Incremental ) { - nsIReflowCommand::ReflowType reflowType; - aReflowState.reflowCommand->GetType(reflowType); - - // See if it's targeted at us - nsIFrame* targetFrame; - aReflowState.reflowCommand->GetTarget(targetFrame); - - if (this == targetFrame) { - // if we are the target see what the type was - // and generate a normal non incremental reflow. - switch (reflowType) { - - case nsIReflowCommand::StyleChanged: - { - nsHTMLReflowState newState(aReflowState); - newState.reason = eReflowReason_StyleChange; - newState.reflowCommand = nsnull; - #ifdef DEBUG_REFLOW - gIndent--; - #endif - return Reflow(aPresContext, aDesiredSize, newState, aStatus); - } - break; - - // if its a dirty type then reflow us with a dirty reflow - case nsIReflowCommand::ReflowDirty: - { - nsHTMLReflowState newState(aReflowState); - newState.reason = eReflowReason_Dirty; - newState.reflowCommand = nsnull; - #ifdef DEBUG_REFLOW - gIndent--; - #endif - return Reflow(aPresContext, aDesiredSize, newState, aStatus); - } - break; - - default: - NS_ASSERTION(PR_FALSE, "unexpected reflow command type"); - } - - } else { - /* - // ok we are not the target, see if our parent is a box. If its not then we - // are the first box so its our responsibility - // to blow away the caches for each child in the incremental - // reflow chain. only mark those children whose parents are boxes - if (mState & NS_STATE_IS_ROOT) { - HandleRootBoxReflow(aPresContext, this, aReflowState); - } - */ - - } - - // then get the child we need to flow incrementally - //aReflowState.reflowCommand->GetNext(incrementalChild); - } - - -#ifdef DEBUG_REFLOW - if (mState & NS_STATE_IS_ROOT) - printf("--------REFLOW %d--------\n", gReflows++); -#endif - - - - -#if 0 -ListTag(stdout); -printf(": begin reflow reason=%s", - aReflowState.reason == eReflowReason_Incremental ? "incremental" : "other"); -if (incrementalChild) { printf(" frame="); nsFrame::ListTag(stdout, incrementalChild); } -printf("\n"); -#endif - - //------------------------------------------------------------------------------------------------ - //------- Figure out what our box size is. This will calculate our children's sizes as well ------ - //------------------------------------------------------------------------------------------------ - - // get our size. This returns a boxSize that contains our min, max, pref sizes. It also - // calculates all of our children sizes as well. It does not include our border we will have to include that - // later - nsBoxInfo ourSize; - GetBoxInfo(aPresContext, aReflowState, ourSize); - - //------------------------------------------------------------------------------------------------ - //------- Make sure the space we need to layout into adhears to our min, max, pref sizes ------ - //------------------------------------------------------------------------------------------------ - - BoundsCheck(ourSize, rect); - - // subtract out the insets. Insets are so subclasses like toolbars can wedge controls in and around the - // box. GetBoxInfo automatically adds them in. But we want to know the size we need to layout our children - // in so lets subtract them our for now. - nsMargin inset(0,0,0,0); - GetInset(inset); - - //nsMargin debugInset(0,0,0,0); - //mInner->GetDebugInset(debugInset); - //inset += debugInset; - - rect.Deflate(inset); - - //----------------------------------------------------------------------------------- - //------------------------- figure our our children's sizes ------------------------- - //----------------------------------------------------------------------------------- - - // now that we know our child's min, max, pref sizes. Stretch our children out to fit into our size. - // this will calculate each of our childs sizes. - InvalidateChildren(); - - nscoord maxAscent; - - LayoutChildrenInRect(rect, maxAscent); - - - //----------------------------------------------------------------------------------- - //------------------------- flow all the children ----------------------------------- - //----------------------------------------------------------------------------------- - - // get the layout rect. - nsRect layoutRect = rect; - - // set up our actual size - layoutRect.Inflate(inset); - - if (aReflowState.mComputedWidth != NS_INTRINSICSIZE && layoutRect.width < aReflowState.mComputedWidth) - layoutRect.width = aReflowState.mComputedWidth; - - if (aReflowState.mComputedHeight != NS_INTRINSICSIZE && layoutRect.height < aReflowState.mComputedHeight) - layoutRect.height = aReflowState.mComputedHeight; - - nsRect actualRect(layoutRect); - actualRect.Deflate(inset); - - nsSize actualSize(actualRect.width, actualRect.height); - - // flow each child at the new sizes we have calculated. With the actual size we are giving them to layout our and the - // size of the rect they were computed to layout in. - mInner->FlowChildren(aPresContext, aDesiredSize, aReflowState, aStatus, incrementalChild, rect, actualSize, maxAscent); - - //----------------------------------------------------------------------------------- - //------------------------- Add our border and insets in ---------------------------- - //----------------------------------------------------------------------------------- - - - // flow children may have changed the rect so lets use it. - rect.Inflate(inset); - - if (aReflowState.mComputedWidth != NS_INTRINSICSIZE && rect.width < aReflowState.mComputedWidth) - rect.width = aReflowState.mComputedWidth; - - if (aReflowState.mComputedHeight != NS_INTRINSICSIZE && rect.height < aReflowState.mComputedHeight) - rect.height = aReflowState.mComputedHeight; - - - rect.Inflate(aReflowState.mComputedBorderPadding); - - // the rect might have gotten bigger so recalc ourSize - aDesiredSize.width = rect.width; - aDesiredSize.height = rect.height; - - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; - aStatus = NS_FRAME_COMPLETE; - -#if 0 -ListTag(stdout); printf(": reflow done\n"); -#endif - mInner->SanityCheck(); + // create the layout state + nsBoxLayoutState state(aPresContext, aReflowState); - -#ifdef DEBUG_REFLOW - gIndent--; -#endif + // coelesce reflows if we are root. + if (state.HandleReflow(this, (mState & NS_STATE_IS_ROOT))) { + aDesiredSize.width = 10; + aDesiredSize.height = 10; + aDesiredSize.ascent = 0; + aDesiredSize.descent = 0; + return NS_OK; + } - return NS_OK; -} + nsSize computedSize(aReflowState.mComputedWidth,aReflowState.mComputedHeight); -void -nsBoxFrameInner::InvalidateCachesTo(nsIFrame* aTargetFrame) -{ - // walk up the tree from the target frame to the root invalidating each childs cached layout infomation - - nsIFrame* parent; - aTargetFrame->GetParent(&parent); - if (parent == nsnull) - return; + nsMargin m; + m = aReflowState.mComputedBorderPadding; + //GetBorderAndPadding(m); - InvalidateCachesTo(parent); + // this happens sometimes. So lets handle it gracefully. + if (aReflowState.mComputedHeight == 0) { + nsSize minSize(0,0); + GetMinSize(state, minSize); + computedSize.height = minSize.height - m.top - m.bottom; + } - // only mark those children whose parents are boxes - nsIBox* ibox = nsnull; - if (NS_SUCCEEDED(parent->QueryInterface(nsIBox::GetIID(), (void**)&ibox)) && ibox) { - ibox->InvalidateCache(aTargetFrame); - } -} + nsSize prefSize(0,0); + // if we are told to layout intrinic then get our preferred size. + if (computedSize.width == NS_INTRINSICSIZE || computedSize.height == NS_INTRINSICSIZE) { + nsSize minSize; + nsSize maxSize; + GetPrefSize(state, prefSize); + GetMinSize(state, minSize); + GetMaxSize(state, maxSize); + BoundsCheck(minSize, prefSize, maxSize); + } -void -nsBoxFrameInner::InvalidateAllCachesBelow(nsIPresContext* aPresContext, nsIFrame* aTargetFrame) -{ - // walk the whole tree under the target frame and clear each childs cached layout information - // but make sure we only mark children whose parent is a box. - nsIBox* ibox = nsnull; - if (NS_FAILED(aTargetFrame->QueryInterface(nsIBox::GetIID(), (void**)&ibox))) { - return; - } - - ibox->InvalidateCache(nsnull); - - nsIFrame* child = nsnull; - aTargetFrame->FirstChild(aPresContext, nsnull, &child); - - while (nsnull != child) - { - InvalidateAllCachesBelow(aPresContext, child); - nsresult rv = child->GetNextSibling(&child); - NS_ASSERTION(rv == NS_OK,"failed to get next child"); - } -} - -void -nsBoxFrame::ComputeChildsNextPosition(nsCalculatedBoxInfo* aInfo, nscoord& aCurX, nscoord& aCurY, nscoord& aNextX, nscoord& aNextY, const nsSize& aCurrentChildSize, const nsRect& aBoxRect, nscoord aMaxAscent) -{ - if (mState & NS_STATE_IS_HORIZONTAL) { - aNextX = aCurX + aCurrentChildSize.width; - - if (mState & NS_STATE_AUTO_STRETCH) { - aCurY = aBoxRect.y; - } else { - switch (mInner->mValign) - { - case nsBoxFrame::vAlign_BaseLine: - aCurY = aBoxRect.y + (aMaxAscent - aInfo->ascent); - break; - - case nsBoxFrame::vAlign_Top: - aCurY = aBoxRect.y; - break; - case nsBoxFrame::vAlign_Middle: - aCurY = aBoxRect.y + (aBoxRect.height/2 - aCurrentChildSize.height/2); - break; - case nsBoxFrame::vAlign_Bottom: - aCurY = aBoxRect.y + aBoxRect.height - aCurrentChildSize.height; - break; - } - } - } else { - aNextY = aCurY + aCurrentChildSize.height; - if (mState & NS_STATE_AUTO_STRETCH) { - aCurX = aBoxRect.x; - } else { - switch (mInner->mHalign) - { - case nsBoxFrame::hAlign_Left: - aCurX = aBoxRect.x; - break; - case nsBoxFrame::hAlign_Center: - aCurX = aBoxRect.x + (aBoxRect.width/2 - aCurrentChildSize.width/2); - break; - case nsBoxFrame::hAlign_Right: - aCurX = aBoxRect.x + aBoxRect.width - aCurrentChildSize.width; - break; - } - } - } -} - -/** - * When all the childrens positions have been calculated and layed out. Flow each child - * at its not size. - */ -nsresult -nsBoxFrameInner::FlowChildren(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame*& aIncrementalChild, - nsRect& aRect, - nsSize& aActualSize, - nscoord& aMaxAscent) -{ - - // ------- set the childs positions --------- - - PRBool redraw = PR_FALSE; - - PRBool finished; - nscoord passes = 0; - nscoord changedIndex = -1; - nsAutoString reason; - nsAutoString nextReason; - PRInt32 infoCount = mInfoList->GetCount(); - PRBool* resized = nsnull; - - // ---------------------- - // Flow all children - // ---------------------- - - // ok what we want to do if flow each child at the location given in the spring. - // unfortunately after flowing a child it might get bigger. We have not control over this - // so it the child gets bigger or smaller than we expected we will have to do a 2nd, 3rd, 4th pass to - // adjust. When we adjust make sure the new reason is resize. - - changedIndex = -1; - - passes = 0; - do - { - #ifdef DEBUG_REFLOW - if (passes > 0) { - AddIndents(); - printf("ChildResized doing pass: %d\n", passes); - } - #endif - - finished = PR_TRUE; - nscoord count = 0; - nsCalculatedBoxInfo* info = mInfoList->GetFirst(); - - nscoord x = aRect.x; - nscoord y = aRect.y; - - if (!(mOuter->mState & NS_STATE_AUTO_STRETCH)) { - if (mOuter->mState & NS_STATE_IS_HORIZONTAL) { - switch(mHalign) { - case nsBoxFrame::hAlign_Left: - x = aRect.x; - break; - - case nsBoxFrame::hAlign_Center: - x = aRect.x + (aActualSize.width - aRect.width)/2; - break; - - case nsBoxFrame::hAlign_Right: - x = aRect.x + (aActualSize.width - aRect.width); - break; - } - } else { - switch(mValign) { - case nsBoxFrame::vAlign_Top: - case nsBoxFrame::vAlign_BaseLine: - y = aRect.y; - break; - - case nsBoxFrame::vAlign_Middle: - y = aRect.y + (aActualSize.height - aRect.height)/2; - break; - - case nsBoxFrame::vAlign_Bottom: - y = aRect.y + (aActualSize.height - aRect.height); - break; - } - } - } - - while (nsnull != info) - { - - nsIFrame* childFrame = info->frame; - - NS_ASSERTION(info, "ERROR not info object!!"); - - // if we reached the index that changed we are done. - //if (count == changedIndex) - // break; - - // make collapsed children not show up - if (info->mFlags & NS_FRAME_BOX_IS_COLLAPSED) { - - if (aReflowState.reason == eReflowReason_Initial) - { - FlowChildAt(childFrame, aPresContext, aDesiredSize, aReflowState, aStatus, *info, x, y, PR_TRUE, aIncrementalChild, redraw, reason); - - // if the child got bigger then adjust our rect and all the children. - mOuter->ChildResized(childFrame, aDesiredSize, aRect, aMaxAscent, *info, resized, infoCount, changedIndex, finished, count, nextReason); - } - - // ok if we are collapsed make sure the view and all its children - // are collapsed as well. - - nsRect rect(0,0,0,0); - childFrame->GetRect(rect); - if (rect.width > 0 || rect.height > 0) - { - childFrame->SizeTo(aPresContext, 0,0); - mOuter->CollapseChild(aPresContext, childFrame, PR_TRUE); - } - - /* - nsRect rect(0,0,0,0); - childFrame->GetRect(rect); - if (rect.width > 0 || rect.height > 0) { - nsIView* view; - childFrame->GetView(aPresContext, &view); - if (view) { - nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, childFrame, - view, nsnull); - } else { - // Re-position any child frame views - nsContainerFrame::PositionChildViews(aPresContext, childFrame); - } - } - */ - - } else { - - nscoord nextX = x; - nscoord nextY = y; - - mOuter->ComputeChildsNextPosition(info, x, y, nextX, nextY, info->calculatedSize, aRect, aMaxAscent); - - // reflow if the child needs it or we are on a second pass - FlowChildAt(childFrame, aPresContext, aDesiredSize, aReflowState, aStatus, *info, x, y, PR_TRUE, aIncrementalChild, redraw, reason); - - // if the child got bigger then adjust our rect and all the children. - mOuter->ChildResized(childFrame, aDesiredSize, aRect, aMaxAscent, *info, resized, infoCount, changedIndex, finished, count, nextReason); - - /* -#ifdef DEBUG_REFLOW - - if (!finished) { - AddIndents(); - printf("**** Child "); - nsFrame::ListTag(stdout, childFrame); - printf(" resized!******\n"); - AddIndents(); - char ch[100]; - nextReason.ToCString(ch,100); - printf("because (%s)\n", ch); - } -#endif - */ - - // always do 1 pass for now. - //finished = PR_TRUE; - - // if the child resized then recompute it position. - if (!finished) { - mOuter->ComputeChildsNextPosition(info, x, y, nextX, nextY, nsSize(aDesiredSize.width, aDesiredSize.height), aRect, aMaxAscent); - } - - x = nextX; - y = nextY; - - } - - info = info->next; - count++; - } - - // ok if something go bigger and we need to do another pass then - // the second pass will be reflow resize - reason = nextReason; - - // if we get over 10 passes something probably when wrong. - passes++; - if (passes > 5) { -// mOuter->NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, - // ("bug")); - } - - //NS_ASSERTION(passes <= 10,"Error infinte loop too many passes"); - if (passes > 10) { - break; - } - - - } while (PR_FALSE == finished); - - - // if the rect inside us changes size. Mainly if it gets smaller redraw. - // this will make use draw when children have removed. - nscoord newInnerSize; - if (mOuter->mState & NS_STATE_IS_HORIZONTAL) - newInnerSize = aRect.width; + // get our desiredSize + if (aReflowState.mComputedWidth == NS_INTRINSICSIZE) + computedSize.width = prefSize.width; else - newInnerSize = aRect.height; + computedSize.width += m.left + m.right; - if (mInnerSize != newInnerSize) - { - mInnerSize = newInnerSize; - redraw = PR_TRUE; - } - - // redraw things if needed. - if (redraw) { -#ifdef DEBUG_REDRAW - mInner->ListTag(stdout); - printf("is being redrawn\n"); -#endif - mOuter->Invalidate(aPresContext, nsRect(0,0,mOuter->mRect.width, mOuter->mRect.height), PR_FALSE); - } + if (aReflowState.mComputedHeight == NS_INTRINSICSIZE || aReflowState.mComputedHeight == 0) + computedSize.height = prefSize.height; + else + computedSize.height += m.top + m.bottom; - if (resized) - delete[] resized; + nsRect r(0,0,computedSize.width, computedSize.height); + r.Inflate(m); + r.x = mRect.x; + r.y = mRect.y; + + SetBounds(state, r); + + // layout our children + Layout(state); + + // ok our child could have gotten bigger. So lets get its bounds + GetBounds(r); + + // get the ascent + nscoord ascent = r.height; + + // getting the ascent could be a lot of work. Don't get it if + // we are the root. The viewport doesn't care about it. + if (!(mState & NS_STATE_IS_ROOT)) + GetAscent(state, ascent); + + aDesiredSize.width = r.width; + aDesiredSize.height = r.height; + aDesiredSize.ascent = ascent; + aDesiredSize.descent = 0; return NS_OK; } +NS_IMETHODIMP +nsBoxFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + if (!DoesNeedRecalc(mInner->mPrefSize)) { + aSize = mInner->mPrefSize; + return NS_OK; + } + + PropagateDebug(aBoxLayoutState); + + nsresult rv = NS_OK; + rv = nsContainerBox::GetPrefSize(aBoxLayoutState, mInner->mPrefSize); + + aSize = mInner->mPrefSize; + + return rv; +} + +NS_IMETHODIMP +nsBoxFrame::GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent) +{ + if (!DoesNeedRecalc(mInner->mAscent)) { + aAscent = mInner->mAscent; + return NS_OK; + } + + PropagateDebug(aBoxLayoutState); + + nsresult rv = NS_OK; + rv = nsContainerBox::GetAscent(aBoxLayoutState, mInner->mAscent); + + aAscent = mInner->mAscent; + + return rv; +} + +NS_IMETHODIMP +nsBoxFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + if (!DoesNeedRecalc(mInner->mMinSize)) { + aSize = mInner->mMinSize; + return NS_OK; + } + + PropagateDebug(aBoxLayoutState); + + nsresult rv = NS_OK; + + mInner->mMinSize.SizeTo(0,0); + rv = nsContainerBox::GetMinSize(aBoxLayoutState, mInner->mMinSize); + + aSize = mInner->mMinSize; + + return rv; +} + +NS_IMETHODIMP +nsBoxFrame::GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + if (!DoesNeedRecalc(mInner->mMaxSize)) { + aSize = mInner->mMaxSize; + return NS_OK; + } + + PropagateDebug(aBoxLayoutState); + + nsresult rv = NS_OK; + + mInner->mMaxSize.SizeTo(0,0); + nsContainerBox::GetMaxSize(aBoxLayoutState, mInner->mMaxSize); + + aSize = mInner->mMaxSize; + + return rv; +} + +NS_IMETHODIMP +nsBoxFrame::GetFlex(nsBoxLayoutState& aBoxLayoutState, nscoord& aFlex) +{ + if (!DoesNeedRecalc(mInner->mFlex)) { + aFlex = mInner->mFlex; + return NS_OK; + } + + nsresult rv = NS_OK; + + mInner->mFlex = 0; + rv = nsContainerBox::GetFlex(aBoxLayoutState, mInner->mFlex); + aFlex = mInner->mFlex; + + return rv; +} + +void +nsBoxFrame::PropagateDebug(nsBoxLayoutState& aState) +{ + // propagate debug information + if (mState & NS_STATE_DEBUG_WAS_SET) { + if (mState & NS_STATE_SET_TO_DEBUG) + SetDebug(aState, PR_TRUE); + else + SetDebug(aState, PR_FALSE); + } else if (mState & NS_STATE_IS_ROOT) { + SetDebug(aState, nsBoxFrameInner::gDebug); + } +} + +NS_IMETHODIMP +nsBoxFrame::Layout(nsBoxLayoutState& aState) +{ + PropagateDebug(aState); + return nsContainerBox::Layout(aState); +} + + #ifdef DEBUG_REFLOW void nsBoxFrameInner::AddIndents() @@ -1571,897 +805,6 @@ nsBoxFrameInner::AddIndents() } #endif -#ifdef DEBUG_REFLOW -void -nsBoxFrameInner::MakeReason(nsIFrame* aFrame, const nsString& aText, nsString& aReason) -{ - nsAutoString type; - nsIFrameDebug* frameDebug; - - if (NS_SUCCEEDED(aFrame->QueryInterface(nsIFrameDebug::GetIID(), (void**)&frameDebug))) { - frameDebug->GetFrameName(type); - } - - char address[100]; - sprintf(address, "@%p", aFrame); - - aReason = "("; - aReason += type; - aReason += address; - aReason += " "; - aReason += aText; - aReason += ")"; -} -#endif - -void -nsBoxFrameInner::CreateResizedArray(PRBool*& aResized, PRInt32 aCount) -{ - aResized = new PRBool[aCount]; - - for (int i=0; i < aCount; i++) - aResized[i] = PR_FALSE; -} - -void -nsBoxFrame::ChildResized(nsIFrame* aFrame, nsHTMLReflowMetrics& aDesiredSize, nsRect& aRect, nscoord& aMaxAscent, nsCalculatedBoxInfo& aInfo, PRBool*& aResized, PRInt32 aInfoCount, nscoord& aChangedIndex, PRBool& aFinished, nscoord aIndex, nsString& aReason) -{ - if (mState & NS_STATE_IS_HORIZONTAL) { - // if we are a horizontal box see if the child will fit inside us. - if ( aDesiredSize.height > aRect.height) { - // if we are a horizontal box and the the child it bigger than our height - - // ok if the height changed then we need to reflow everyone but us at the new height - // so we will set the changed index to be us. And signal that we need a new pass. - - aRect.height = aDesiredSize.height; - - // remember we do not need to clear the resized list because changing the height of a horizontal box - // will not affect the width of any of its children because block flow left to right, top to bottom. Just trust me - // on this one. - aFinished = PR_FALSE; - aChangedIndex = aIndex; - - // relayout everything - InvalidateChildren(); - LayoutChildrenInRect(aRect, aMaxAscent); -#ifdef DEBUG_REFLOW - mInner->MakeReason(aFrame, "height got bigger", aReason); -#endif - - } else if (aDesiredSize.width > aInfo.calculatedSize.width) { - // if the child is wider than we anticipated. This can happend for children that we were not able to get a - // take on their min width. Like text, or tables. - - // because things flow from left to right top to bottom we know that - // if we get wider that we can set the min size. This will only work - // for width not height. Height must always be recalculated! - - // however we must see whether the min size was set in css. - // if it was then this size should not override it. - - // add in the css min, max, pref - const nsStylePosition* position; - aFrame->GetStyleData(eStyleStruct_Position, - (const nsStyleStruct*&) position); - - - // same for min size. Unfortunately min size is always set to 0. So for now - // we will assume 0 means not set. - if (position->mMinWidth.GetUnit() == eStyleUnit_Coord) { - nscoord min = position->mMinWidth.GetCoordValue(); - if (min != 0) - return; - } - - aInfo.minSize.width = aDesiredSize.width; - - // our width now becomes the new size - aInfo.calculatedSize.width = aDesiredSize.width; - - InvalidateChildren(); - - if (aResized == nsnull) - mInner->CreateResizedArray(aResized, aInfoCount); - - // our index resized - aResized[aIndex] = PR_TRUE; - - // if the width changed. mark our child as being resized - nsCalculatedBoxInfo* info = mInner->mInfoList->GetFirst(); - PRInt32 infoCount = 0; - while(info) { - if (aResized[infoCount]) - info->mFlags |= NS_FRAME_BOX_SIZE_VALID; - else - info->mFlags &= ~NS_FRAME_BOX_SIZE_VALID; - - - info = info->next; - infoCount++; - } - - LayoutChildrenInRect(aRect, aMaxAscent); - aFinished = PR_FALSE; - aChangedIndex = aIndex; -#ifdef DEBUG_REFLOW - mInner->MakeReason(aFrame, "width got bigger", aReason); -#endif - - } - } else { - if ( aDesiredSize.width > aRect.width) { - // ok if the height changed then we need to reflow everyone but us at the new height - // so we will set the changed index to be us. And signal that we need a new pass. - aRect.width = aDesiredSize.width; - - // add in the css min, max, pref - const nsStylePosition* position; - aFrame->GetStyleData(eStyleStruct_Position, - (const nsStyleStruct*&) position); - - // same for min size. Unfortunately min size is always set to 0. So for now - // we will assume 0 means not set. - if (position->mMinWidth.GetUnit() == eStyleUnit_Coord) { - nscoord min = position->mMinWidth.GetCoordValue(); - if (min != 0) - return; - } - - // because things flow from left to right top to bottom we know that - // if we get wider that we can set the min size. This will only work - // for width not height. Height must always be recalculated! - aInfo.minSize.width = aDesiredSize.width; - - // if the width changed then clear out the resized list - // but only do this if we are vertical box. On a horizontal box increasing the height will not change the - // width of its children. - if (aResized == nsnull) - mInner->CreateResizedArray(aResized, aInfoCount); - - PRInt32 infoCount = mInner->mInfoList->GetCount(); - for (int i=0; i < infoCount; i++) - aResized[i] = PR_FALSE; - - aFinished = PR_FALSE; - aChangedIndex = aIndex; - - // relayout everything - InvalidateChildren(); - LayoutChildrenInRect(aRect, aMaxAscent); -#ifdef DEBUG_REFLOW - mInner->MakeReason(aFrame, "width got bigger", aReason); -#endif - - } else if (aDesiredSize.height > aInfo.calculatedSize.height) { - // our width now becomes the new size - aInfo.calculatedSize.height = aDesiredSize.height; - - InvalidateChildren(); - - if (aResized == nsnull) - mInner->CreateResizedArray(aResized, aInfoCount); - - // our index resized - aResized[aIndex] = PR_TRUE; - - // if the width changed. mark our child as being resized - nsCalculatedBoxInfo* info = mInner->mInfoList->GetFirst(); - PRInt32 infoCount = 0; - while(info) { - if (aResized[infoCount]) - info->mFlags |= NS_FRAME_BOX_SIZE_VALID; - else - info->mFlags &= ~NS_FRAME_BOX_SIZE_VALID; - - info = info->next; - infoCount++; - } - - LayoutChildrenInRect(aRect, aMaxAscent); - aFinished = PR_FALSE; - aChangedIndex = aIndex; -#ifdef DEBUG_REFLOW - mInner->MakeReason(aFrame, "height got bigger", aReason); -#endif - - } - } -} - -void -nsBoxFrame::CollapseChild(nsIPresContext* aPresContext, nsIFrame* frame, PRBool hide) -{ - // shrink the view - nsIView* view = nsnull; - frame->GetView(aPresContext, &view); - - // if we find a view stop right here. All views under it - // will be clipped. - if (view) { - nsViewVisibility v; - view->GetVisibility(v); - nsCOMPtr widget; - view->GetWidget(*getter_AddRefs(widget)); - if (hide) { - view->SetVisibility(nsViewVisibility_kHide); - } else { - view->SetVisibility(nsViewVisibility_kShow); - } - if (widget) { - - return; - } - } - - // Trees have to collapse their scrollbars manually, since you can't - // get to the scrollbar via the normal frame list. - nsISelfScrollingFrame* treeFrame; - if (NS_SUCCEEDED(frame->QueryInterface(NS_GET_IID(nsISelfScrollingFrame), (void**)&treeFrame)) && treeFrame) { - // Tell the tree frame to collapse its scrollbar. - treeFrame->CollapseScrollbar(aPresContext, hide); - } - - // collapse the child - nsIFrame* child = nsnull; - frame->FirstChild(aPresContext, nsnull, &child); - - while (nsnull != child) - { - CollapseChild(aPresContext, child, hide); - nsresult rv = child->GetNextSibling(&child); - NS_ASSERTION(rv == NS_OK,"failed to get next child"); - } -} - -NS_IMETHODIMP -nsBoxFrame::DidReflow(nsIPresContext* aPresContext, - nsDidReflowStatus aStatus) -{ - nsresult rv = nsHTMLContainerFrame::DidReflow(aPresContext, aStatus); - NS_ASSERTION(rv == NS_OK,"DidReflow failed"); - - /* - nsCalculatedBoxInfo* info = mInner->mInfoList->GetFirst(); - - while (info) - { - // make collapsed children not show up - if (info->collapsed) { - nsRect rect(0,0,0,0); - info->frame->GetRect(rect); - if (rect.width == 0 && rect.height == 0) - return; - - CollapseChild(aPresContext, info->frame, PR_TRUE); - } - - info = info->next; - } - */ - return rv; -} - -/** - * Given the boxes rect. Set the x,y locations of all its children. Taking into account - * their margins - */ -nsresult -nsBoxFrame::PlaceChildren(nsIPresContext* aPresContext, nsRect& boxRect) -{ - // ------- set the childs positions --------- - nscoord x = boxRect.x; - nscoord y = boxRect.y; - - nsCalculatedBoxInfo* info = mInner->mInfoList->GetFirst(); - - while (info) - { - nsIFrame* childFrame = info->frame; - - nsresult rv; - - // make collapsed children not show up - if (info->mFlags & NS_FRAME_BOX_IS_COLLAPSED) { - nsRect rect(0,0,0,0); - childFrame->GetRect(rect); - if (rect.width > 0 || rect.height > 0) { - childFrame->SizeTo(aPresContext, 0,0); - CollapseChild(aPresContext, childFrame, PR_TRUE); - } - } else { - const nsStyleSpacing* spacing; - rv = childFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - nsMargin margin(0,0,0,0); - spacing->GetMargin(margin); - - if (mState & NS_STATE_IS_HORIZONTAL) { - x += margin.left; - y = boxRect.y + margin.top; - } else { - y += margin.top; - x = boxRect.x + margin.left; - } - - nsRect rect; - nsIView* view; - childFrame->GetRect(rect); - rect.x = x; - rect.y = y; - childFrame->SetRect(aPresContext, rect); - childFrame->GetView(aPresContext, &view); - // XXX Because we didn't position the frame or its view when reflowing - // it we must re-position all child views. This isn't optimal, and if - // we knew its final position, it would be better to position the frame - // and its view when doing the reflow... - if (view) { - nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, childFrame, - view, nsnull); - } else { - // Re-position any child frame views - nsContainerFrame::PositionChildViews(aPresContext, childFrame); - } - - // add in the right margin - if (mState & NS_STATE_IS_HORIZONTAL) - x += margin.right; - else - y += margin.bottom; - - if (mState & NS_STATE_IS_HORIZONTAL) { - x += rect.width; - //width += rect.width + margin.left + margin.right; - } else { - y += rect.height; - //height += rect.height + margin.top + margin.bottom; - } - } - - info = info->next; - } - - return NS_OK; -} - -void -nsBoxFrameInner::PlaceChild(nsIPresContext* aPresContext, nsIFrame* aFrame, nscoord aX, nscoord aY) -{ - nsPoint curOrigin; - aFrame->GetOrigin(curOrigin); - - // only if the origin changed - if ((curOrigin.x != aX) || (curOrigin.y != aY)) { - aFrame->MoveTo(aPresContext, aX, aY); - - nsIView* view; - aFrame->GetView(aPresContext, &view); - if (view) { - nsContainerFrame::PositionFrameView(aPresContext, aFrame, view); - } else - nsContainerFrame::PositionChildViews(aPresContext, aFrame); - } -} - - -void -nsBoxFrameInner::InitializeReflowState(nsIPresContext* aPresContext, const nsCalculatedBoxInfo& aInfo, nsHTMLReflowState& aReflowState, const nsHTMLReflowState& aParentReflowState, nsIFrame* aFrame, const nsSize& aAvailSize, nsReflowReason aReason) -{ - aFrame->GetStyleData(eStyleStruct_Position, - (const nsStyleStruct*&)aReflowState.mStylePosition); - aFrame->GetStyleData(eStyleStruct_Display, - (const nsStyleStruct*&)aReflowState.mStyleDisplay); - aFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&)aReflowState.mStyleSpacing); - - aReflowState.mReflowDepth = aParentReflowState.mReflowDepth + 1; - aReflowState.parentReflowState = &aParentReflowState; - aReflowState.frame = aFrame; - aReflowState.reason = aReason; - aReflowState.reflowCommand = aReflowState.reflowCommand; - aReflowState.availableWidth = aAvailSize.width; - aReflowState.availableHeight = aAvailSize.height; - - aReflowState.rendContext = aParentReflowState.rendContext; - aReflowState.mSpaceManager = aParentReflowState.mSpaceManager; - aReflowState.mLineLayout = aParentReflowState.mLineLayout; - aReflowState.isTopOfPage = aParentReflowState.isTopOfPage; - - // if we are not a box then to the regular html thing. - // otherwise do the efficient thing for boxes. - // if (!(aInfo.mFlags & NS_FRAME_IS_BOX)) { - // aReflowState.Init(aPresContext); - /// } else { - aReflowState.mComputedMargin.SizeTo(0,0,0,0); - aReflowState.mStyleSpacing->GetMargin(aReflowState.mComputedMargin); - aReflowState.mComputedBorderPadding.SizeTo(0,0,0,0); - aReflowState.mStyleSpacing->GetBorderPadding(aReflowState.mComputedBorderPadding); - aReflowState.mComputedPadding.SizeTo(0,0,0,0); - aReflowState.mStyleSpacing->GetPadding(aReflowState.mComputedPadding); - aReflowState.mComputedOffsets.SizeTo(0, 0, 0, 0); - aReflowState.mComputedMinWidth = aReflowState.mComputedMinHeight = 0; - aReflowState.mComputedMaxWidth = aReflowState.mComputedMaxHeight = NS_UNCONSTRAINEDSIZE; - aReflowState.mCompactMarginWidth = 0; - aReflowState.mAlignCharOffset = 0; - aReflowState.mUseAlignCharOffset = 0; - aReflowState.mFrameType = NS_CSS_FRAME_TYPE_BLOCK; - //} -} - -/** - * Flow an individual child. Special args: - * count: the spring that will be used to lay out the child - * incrementalChild: If incremental reflow this is the child that need to be reflowed. - * when we finally do reflow the child we will set the child to null - */ - -nsresult -nsBoxFrameInner::FlowChildAt(nsIFrame* childFrame, - nsIPresContext* aPresContext, - nsHTMLReflowMetrics& desiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsCalculatedBoxInfo& aInfo, - nscoord aX, - nscoord aY, - PRBool aMoveFrame, - nsIFrame*& aIncrementalChild, - PRBool& aRedraw, - const nsString& aReason) -{ - // if (mOuter->mState & NS_STATE_CURRENTLY_IN_DEBUG) - // printf("in debug\n"); - - aStatus = NS_FRAME_COMPLETE; - PRBool needsReflow = PR_FALSE; - nsReflowReason reason = aReflowState.reason; - - nsFrameState childState; - aInfo.frame->GetFrameState(&childState); - - if (childState & NS_FRAME_FIRST_REFLOW) { - if (reason != eReflowReason_Initial) - { - // if incremental then make sure we send a initial reflow first. - if (reason == eReflowReason_Incremental) { - nsHTMLReflowState state(aReflowState); - state.reason = eReflowReason_Initial; - state.reflowCommand = nsnull; - FlowChildAt(childFrame, aPresContext, desiredSize, state, aStatus, aInfo, aX, aY, aMoveFrame, aIncrementalChild, aRedraw, aReason); - } else { - // convert to initial if not incremental. - reason = eReflowReason_Initial; - } - - } - } else if (reason == eReflowReason_Initial) { - reason = eReflowReason_Resize; - } - - switch(reason) - { - // if the child we are reflowing is the child we popped off the incremental - // reflow chain then we need to reflow it no matter what. - // if its not the child we got from the reflow chain then this child needs reflow - // because as a side effect of the incremental child changing aize andit needs to be resized. - // This will happen with a lot when a box that contains 2 children with different flexabilities - // if on child gets bigger the other is affected because it is proprotional to the first. - // so it might need to be resized. But we don't need to reflow it. If it is already the - // needed size then we will do nothing. - case eReflowReason_Incremental: { - - // if incremental see if the next child in the chain is the child. If so then - // we will just let it go down. If not then convert it to a dirty. It will get converted back when - // needed in the case just below this one. - nsIFrame* incrementalChild = nsnull; - aReflowState.reflowCommand->GetNext(incrementalChild, PR_FALSE); - if (incrementalChild == aInfo.frame) { - needsReflow = PR_TRUE; - aReflowState.reflowCommand->GetNext(incrementalChild); - } else { - // create a new state. Make sure we don't null out the - // reflow command. This is how we will tell it was a converted incremental. - // We will use this later to convert back to a incremental. - nsHTMLReflowState state(aReflowState); - state.reason = eReflowReason_Dirty; - return FlowChildAt(childFrame, aPresContext, desiredSize, state, aStatus, aInfo, aX, aY, aMoveFrame, aIncrementalChild, aRedraw, aReason); - } - } break; - - // if its dirty then see if the child we want to reflow is dirty. If it is then - // mark it as needing to be reflowed. - case eReflowReason_Dirty: { - - // sometimes incrementals are converted to dirty. This is done in the case just above this. So lets check - // to see if this was converted. If it was it will still have a reflow state. - if (aReflowState.reflowCommand) { - // it was converted so lets see if the next child is this one. If it is then convert it back and - // pass it down. - nsIFrame* incrementalChild = nsnull; - aReflowState.reflowCommand->GetNext(incrementalChild, PR_FALSE); - if (incrementalChild == aInfo.frame) { - nsHTMLReflowState state(aReflowState); - state.reason = eReflowReason_Incremental; - return FlowChildAt(childFrame, aPresContext, desiredSize, state, aStatus, aInfo, aX, aY, aMoveFrame, aIncrementalChild, aRedraw, aReason); - } - } - - // get the frame state to see if it needs reflow - needsReflow = (childState & NS_FRAME_IS_DIRTY) || (childState & NS_FRAME_HAS_DIRTY_CHILDREN); - - } break; - - // if the a resize reflow then it doesn't need to be reflowed. Only if the size is different - // from the new size would we actually do a reflow - case eReflowReason_Resize: - needsReflow = PR_FALSE; - break; - - // if its an initial reflow we must place the child. - // otherwise we might think it was already placed when it wasn't - case eReflowReason_Initial: - aMoveFrame = PR_TRUE; - needsReflow = PR_TRUE; - break; - - default: - needsReflow = PR_TRUE; - - } - - // subtract out the childs margin and border - const nsStyleSpacing* spacing; - nsresult rv = childFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - nsMargin margin(0,0,0,0); - spacing->GetMargin(margin); - - // get the current size of the child - nsRect currentRect(0,0,0,0); - childFrame->GetRect(currentRect); - - // if we don't need a reflow then - // lets see if we are already that size. Yes? then don't even reflow. We are done. - if (!needsReflow) { - - if (aInfo.calculatedSize.width != NS_INTRINSICSIZE && aInfo.calculatedSize.height != NS_INTRINSICSIZE) { - - // if the new calculated size has a 0 width or a 0 height - if ((currentRect.width == 0 || currentRect.height == 0) && (aInfo.calculatedSize.width == 0 || aInfo.calculatedSize.height == 0)) { - needsReflow = PR_FALSE; - desiredSize.width = aInfo.calculatedSize.width - (margin.left + margin.right); - desiredSize.height = aInfo.calculatedSize.height - (margin.top + margin.bottom); - childFrame->SizeTo(aPresContext, desiredSize.width, desiredSize.height); - } else { - desiredSize.width = currentRect.width; - desiredSize.height = currentRect.height; - - // remove the margin. The rect of our child does not include it but our calculated size does. - nscoord calcWidth = aInfo.calculatedSize.width - (margin.left + margin.right); - nscoord calcHeight = aInfo.calculatedSize.height - (margin.top + margin.bottom); - - // don't reflow if we are already the right size - if (currentRect.width == calcWidth && currentRect.height == calcHeight) - needsReflow = PR_FALSE; - else - needsReflow = PR_TRUE; - - } - } else { - // if the width or height are intrinsic alway reflow because - // we don't know what it should be. - needsReflow = PR_TRUE; - } - } - - // ok now reflow the child into the springs calculated space - if (needsReflow) { - - nsMargin border(0,0,0,0); - spacing->GetBorderPadding(border); - - const nsStylePosition* position; - rv = childFrame->GetStyleData(eStyleStruct_Position, - (const nsStyleStruct*&) position); - - desiredSize.width = 0; - desiredSize.height = 0; - - nsSize size(aInfo.calculatedSize.width, aInfo.calculatedSize.height); - - /* - // lets also look at our intrinsic flag. This flag is to make things like HR work. - // hr is funny if you flow it intrinsically you will get a size that is the height of - // the current font size. But if you then flow the hr with a computed height of what was returned the - // hr will be stretched out to fit. So basically the hr lays itself out differently depending - // on if you use intrinsic or or computed size. So to fix this we follow this policy. If any child - // does not Innerement nsIBox then we set this flag. Then on a flow if we decide to flow at the preferred width - // we flow it with a intrinsic width. This goes for height as well. - if (aInfo.prefWidthIntrinsic && size.width == aInfo.prefSize.width) - size.width = NS_INTRINSICSIZE; - - if (aInfo.prefHeightIntrinsic && size.height == aInfo.prefSize.height) - size.height = NS_INTRINSICSIZE; - */ - - // only subrtact margin - if (size.height != NS_INTRINSICSIZE) - size.height -= (margin.top + margin.bottom); - - if (size.width != NS_INTRINSICSIZE) - size.width -= (margin.left + margin.right); - - // create a reflow state to tell our child to flow at the given size. - - #ifdef DEBUG_REFLOW - - char* reflowReasonString; - - switch(reason) - { - case eReflowReason_Initial: - reflowReasonString = "initial"; - break; - - case eReflowReason_Resize: - reflowReasonString = "resize"; - break; - case eReflowReason_Dirty: - reflowReasonString = "dirty"; - break; - case eReflowReason_StyleChange: - reflowReasonString = "stylechange"; - break; - case eReflowReason_Incremental: - reflowReasonString = "incremental"; - break; - default: - reflowReasonString = "unknown"; - break; - } - - AddIndents(); - nsFrame::ListTag(stdout, childFrame); - char ch[100]; - aReason.ToCString(ch,100); - - printf(" reason=%s %s",reflowReasonString,ch); -#endif - - // only frames that implement nsIBox seem to be able to handle a reason of Dirty. For everyone else - // send down a resize. - if (!(aInfo.mFlags & NS_FRAME_IS_BOX) && reason == eReflowReason_Dirty) - reason = eReflowReason_Resize; - - if (!(aInfo.mFlags & NS_FRAME_IS_BOX)) { - nsHTMLReflowState reflowState(aPresContext, aReflowState, childFrame, nsSize(size.width, NS_INTRINSICSIZE)); - reflowState.reason = reason; - - if (size.height != NS_INTRINSICSIZE) - size.height -= (border.top + border.bottom); - - if (size.width != NS_INTRINSICSIZE) - size.width -= (border.left + border.right); - - reflowState.mComputedWidth = size.width; - reflowState.mComputedHeight = size.height; -#ifdef DEBUG_REFLOW - printf(" Size=(%d,%d)\n",reflowState.mComputedWidth, reflowState.mComputedHeight); -#endif - - // place the child and reflow - childFrame->WillReflow(aPresContext); - - if (aMoveFrame) { - PlaceChild(aPresContext, childFrame, aX + margin.left, aY + margin.top); - } - - childFrame->Reflow(aPresContext, desiredSize, reflowState, aStatus); - } else { - nsHTMLReflowState reflowState(aReflowState); - InitializeReflowState(aPresContext, aInfo, reflowState, aReflowState, childFrame, nsSize(size.width, NS_INTRINSICSIZE), reason); - - if (size.height != NS_INTRINSICSIZE) - size.height -= (border.top + border.bottom); - - if (size.width != NS_INTRINSICSIZE) - size.width -= (border.left + border.right); - - reflowState.mComputedWidth = size.width; - reflowState.mComputedHeight = size.height; - -#ifdef DEBUG_REFLOW - printf(" Size=(%d,%d)\n",reflowState.mComputedWidth, reflowState.mComputedHeight); -#endif - - // place the child and reflow - childFrame->WillReflow(aPresContext); - - if (aMoveFrame) { - PlaceChild(aPresContext, childFrame, aX + margin.left, aY + margin.top); - } - - childFrame->Reflow(aPresContext, desiredSize, reflowState, aStatus); - } - - NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); - - nsFrameState kidState; - childFrame->GetFrameState(&kidState); - - // printf("width: %d, height: %d\n", desiredSize.mCombinedArea.width, desiredSize.mCombinedArea.height); - - // XXX EDV hack to fix bug in block - if (reason != eReflowReason_Initial) { - if (kidState & NS_FRAME_OUTSIDE_CHILDREN) { - desiredSize.width = desiredSize.mOverflowArea.width; - desiredSize.height = desiredSize.mOverflowArea.height; - } - } -// if (maxElementSize.width > desiredSize.width) - // desiredSize.width = maxElementSize.width; - - PRBool changedSize = PR_FALSE; - - if (currentRect.width != desiredSize.width || currentRect.height != desiredSize.height) - changedSize = PR_TRUE; - - // if the child got bigger then make sure the new size in our min max range - if (changedSize) { - - // redraw if we changed size. - aRedraw = PR_TRUE; - - if (aInfo.maxSize.width != NS_INTRINSICSIZE && desiredSize.width > aInfo.maxSize.width - (margin.left + margin.right)) - desiredSize.width = aInfo.maxSize.width - (margin.left + margin.right); - - // if the child was bigger than anticipated and there was a min size set thennn - if (aInfo.calculatedSize.width != NS_INTRINSICSIZE && position->mMinWidth.GetUnit() == eStyleUnit_Coord) { - nscoord min = position->mMinWidth.GetCoordValue(); - if (min != 0) - desiredSize.width = aInfo.calculatedSize.width - (margin.left + margin.right); - } - - if (aInfo.maxSize.height != NS_INTRINSICSIZE && desiredSize.height > aInfo.maxSize.height - (margin.top + margin.bottom)) - desiredSize.height = aInfo.maxSize.height - (margin.top + margin.bottom); - - // if a min size was set we will always get the desired height - if (aInfo.calculatedSize.height != NS_INTRINSICSIZE && position->mMinHeight.GetUnit() == eStyleUnit_Coord) { - nscoord min = position->mMinHeight.GetCoordValue(); - if (min != 0) - desiredSize.height = aInfo.calculatedSize.height - (margin.top + margin.bottom); - } - } - - nsContainerFrame::FinishReflowChild(childFrame, aPresContext, desiredSize, aX + margin.left, aY + margin.top, NS_FRAME_NO_MOVE_FRAME); - - // Stub out desiredSize.maxElementSize so that when go out of - // scope, nothing bad happens! - //desiredSize.maxElementSize = nsnull; - - } else { - if (aMoveFrame) { - PlaceChild(aPresContext, childFrame, aX + margin.left, aY + margin.top); - } - } - - - // add the margin back in. The child should add its border automatically - desiredSize.height += (margin.top + margin.bottom); - desiredSize.width += (margin.left + margin.right); - -#ifdef DEBUG_REFLOW - if (aInfo.calculatedSize.height != NS_INTRINSICSIZE && desiredSize.height != aInfo.calculatedSize.height) - { - AddIndents(); - printf("**** Child "); - nsFrame::ListTag(stdout, childFrame); - printf(" got taller!******\n"); - - } - if (aInfo.calculatedSize.width != NS_INTRINSICSIZE && desiredSize.width != aInfo.calculatedSize.width) - { - AddIndents(); - printf("**** Child "); - nsFrame::ListTag(stdout, childFrame); - printf(" got wider!******\n"); - - } -#endif - - if (aInfo.calculatedSize.width == NS_INTRINSICSIZE) - aInfo.calculatedSize.width = desiredSize.width; - - if (aInfo.calculatedSize.height == NS_INTRINSICSIZE) - aInfo.calculatedSize.height = desiredSize.height; - - return NS_OK; -} - -/** - * Given a box info object and a rect. Make sure the rect is not too small to layout the box and - * not to big either. - */ -void -nsBoxFrame::BoundsCheck(const nsBoxInfo& aBoxInfo, nsRect& aRect) -{ - // if we are bieng flowed at our intrinsic width or height then set our width - // to the biggest child. - if (aRect.height == NS_INTRINSICSIZE ) - aRect.height = aBoxInfo.prefSize.height; - - if (aRect.width == NS_INTRINSICSIZE ) - aRect.width = aBoxInfo.prefSize.width; - - // make sure the available size is no bigger than the max size - if (aRect.height > aBoxInfo.maxSize.height) - aRect.height = aBoxInfo.maxSize.height; - - if (aRect.width > aBoxInfo.maxSize.width) - aRect.width = aBoxInfo.maxSize.width; - - // make sure the available size is at least as big as the min size - if (aRect.height < aBoxInfo.minSize.height) - aRect.height = aBoxInfo.minSize.height; - - if (aRect.width < aBoxInfo.minSize.width) - aRect.width = aBoxInfo.minSize.width; - -} - -/** - * Ok when calculating a boxes size such as its min size we need to look at its children to figure it out. - * But this isn't as easy as just adding up its childs min sizes. If the box is horizontal then we need to - * add up each child's min width but our min height should be the childs largest min height. This needs to - * be done for preferred size and max size as well. Of course for our max size we need to pick the smallest - * max size. So this method facilitates the calculation. Just give it 2 sizes and a flag to ask whether is is - * looking for the largest or smallest value (max needs smallest) and it will set the second value. - */ -void -nsBoxFrame::AddSize(const nsSize& a, nsSize& b, PRBool largest) -{ - - // depending on the dimension switch either the width or the height component. - const nscoord& awidth = (mState & NS_STATE_IS_HORIZONTAL) ? a.width : a.height; - const nscoord& aheight = (mState & NS_STATE_IS_HORIZONTAL) ? a.height : a.width; - nscoord& bwidth = (mState & NS_STATE_IS_HORIZONTAL) ? b.width : b.height; - nscoord& bheight = (mState & NS_STATE_IS_HORIZONTAL) ? b.height : b.width; - - // add up the widths make sure we check for intrinsic. - if (bwidth != NS_INTRINSICSIZE) // if we are already intrinsic we are done - { - // otherwise if what we are adding is intrinsic then we just become instrinsic and we are done - if (awidth == NS_INTRINSICSIZE) - bwidth = NS_INTRINSICSIZE; - else // add it on - bwidth += awidth; - } - - // store the largest or smallest height - if ((largest && aheight > bheight) || (!largest && bheight < aheight)) - bheight = aheight; -} - - -void -nsBoxFrame::GetInset(nsMargin& margin) -{ - mInner->GetDebugInset(margin); -} - - -void -nsBoxFrame::InvalidateChildren() -{ - nsCalculatedBoxInfo* info = mInner->mInfoList->GetFirst(); - while(info) { - info->mFlags &= ~NS_FRAME_BOX_SIZE_VALID; - info = info->next; - } -} - nsBoxFrame::Valignment nsBoxFrameInner::GetVAlign() { @@ -2474,254 +817,13 @@ nsBoxFrameInner::GetHAlign() return mHalign; } - -void -nsBoxFrame::LayoutChildrenInRect(nsRect& aGivenSize, nscoord& aMaxAscent) -{ - nsCalculatedBoxInfo* first = mInner->mInfoList->GetFirst(); - - if (!first) - return; - - PRInt32 sizeRemaining; - - if (mState & NS_STATE_IS_HORIZONTAL) - sizeRemaining = aGivenSize.width; - else - sizeRemaining = aGivenSize.height; - - PRInt32 springConstantsRemaining = 0; - - nsCalculatedBoxInfo* info = first; - - while(info) { - // ignore collapsed children - if (info->mFlags & NS_FRAME_BOX_IS_COLLAPSED) { - info = info->next; - continue; - } - - // figure out the direction of the box and get the correct value either the width or height - nscoord pref = GET_WIDTH(info->prefSize); - - nscoord min = GET_WIDTH(info->minSize); - - if (mState & NS_STATE_AUTO_STRETCH) - { - // stretch - nscoord h = GET_HEIGHT(aGivenSize); - nscoord max1 = GET_HEIGHT(info->maxSize); - nscoord min1 = GET_HEIGHT(info->minSize); - if (h < min1) - h = min1; - else if (h > max1) - h = max1; - - SET_HEIGHT(info->calculatedSize, h); - } else { - // go to preferred size - nscoord h = GET_HEIGHT(info->prefSize); - nscoord s = GET_HEIGHT(aGivenSize); - if (h > s) - h = s; - - nscoord max1 = GET_HEIGHT(info->maxSize); - nscoord min1 = GET_HEIGHT(info->minSize); - if (h < min1) - h = min1; - else if (h > max1) - h = max1; - - SET_HEIGHT(info->calculatedSize, h); - } - - if (pref < min) { - pref = min; - SET_WIDTH(info->prefSize, min); - } - - if (info->mFlags & NS_FRAME_BOX_SIZE_VALID) { - sizeRemaining -= GET_WIDTH(info->calculatedSize); - } else { - if (info->flex == 0) - { - info->mFlags |= NS_FRAME_BOX_SIZE_VALID; - SET_WIDTH(info->calculatedSize, pref); - } - sizeRemaining -= pref; - springConstantsRemaining += info->flex; - } - - info = info->next; - } - - nscoord& sz = GET_WIDTH(aGivenSize); - if (sz == NS_INTRINSICSIZE) { - sz = 0; - info = first; - while(info) { - - // ignore collapsed springs - if (info->mFlags & NS_FRAME_BOX_IS_COLLAPSED) { - info = info->next; - continue; - } - - nscoord pref = GET_WIDTH(info->prefSize); - - if (!(info->mFlags & NS_FRAME_BOX_SIZE_VALID)) - { - // set the calculated size to be the preferred size - SET_WIDTH(info->calculatedSize, pref); - info->mFlags |= NS_FRAME_BOX_SIZE_VALID; - } - - // changed the size returned to reflect - sz += GET_WIDTH(info->calculatedSize); - - info = info->next; - - } - return; - } - - PRBool limit = PR_TRUE; - for (int pass=1; PR_TRUE == limit; pass++) { - limit = PR_FALSE; - info = first; - while(info) { - // ignore collapsed springs - if (info->mFlags & NS_FRAME_BOX_IS_COLLAPSED) { - info = info->next; - continue; - } - - nscoord pref = GET_WIDTH(info->prefSize); - nscoord max = GET_WIDTH(info->maxSize); - nscoord min = GET_WIDTH(info->minSize); - - if (!(info->mFlags & NS_FRAME_BOX_SIZE_VALID)) { - PRInt32 newSize = pref + (sizeRemaining*info->flex/springConstantsRemaining); - if (newSize<=min) { - SET_WIDTH(info->calculatedSize, min); - springConstantsRemaining -= info->flex; - sizeRemaining += pref; - sizeRemaining -= min; - - info->mFlags |= NS_FRAME_BOX_SIZE_VALID; - limit = PR_TRUE; - } - else if (newSize>=max) { - SET_WIDTH(info->calculatedSize, max); - springConstantsRemaining -= info->flex; - sizeRemaining += pref; - sizeRemaining -= max; - info->mFlags |= NS_FRAME_BOX_SIZE_VALID; - limit = PR_TRUE; - } - } - info = info->next; - } - } - - nscoord& s = GET_WIDTH(aGivenSize); - s = 0; - aMaxAscent = 0; - - info = first; - while(info) { - - // ignore collapsed springs - if (info->mFlags & NS_FRAME_BOX_IS_COLLAPSED) { - info = info->next; - continue; - } - - nscoord pref = GET_WIDTH(info->prefSize); - - if (!(info->mFlags & NS_FRAME_BOX_SIZE_VALID)) { - if (springConstantsRemaining == 0) { - SET_WIDTH(info->calculatedSize, pref); - } - else { - SET_WIDTH(info->calculatedSize, pref + info->flex*sizeRemaining/springConstantsRemaining); - } - - info->mFlags |= NS_FRAME_BOX_SIZE_VALID; - } - - s += GET_WIDTH(info->calculatedSize); - - if (info->ascent > aMaxAscent) - aMaxAscent = info->ascent; - - info = info->next; - } -} - - -void -nsBoxFrame::GetChildBoxInfo(PRInt32 aIndex, nsBoxInfo& aSize) -{ - PRInt32 infoCount = mInner->mInfoList->GetCount(); - - NS_ASSERTION(aIndex >= 0 && aIndex < infoCount,"Index out of bounds!!"); - - nsCalculatedBoxInfo* info = mInner->mInfoList->GetFirst(); - - for (PRInt32 i=0; i< infoCount; i++) { - if (i == aIndex) - break; - info = info->next; - } - - aSize = *info; -} - -// Marks the frame as dirty and generates an incremental reflow -// command targeted at this frame -nsresult -nsBoxFrame::GenerateDirtyReflowCommand(nsIPresContext* aPresContext, - nsIPresShell& aPresShell) -{ - if (mState & NS_FRAME_IS_DIRTY) - return NS_OK; - - // ask out parent to dirty things. - mState |= NS_FRAME_IS_DIRTY; - return mParent->ReflowDirtyChild(&aPresShell, this); -} - -NS_IMETHODIMP -nsBoxFrame::RemoveFrame(nsIPresContext* aPresContext, - nsIPresShell& aPresShell, - nsIAtom* aListName, - nsIFrame* aOldFrame) -{ - mInner->SanityCheck(); - - // remove child from our info list - mInner->mInfoList->Remove(&aPresShell, aOldFrame); - - // remove the child frame - mFrames.DestroyFrame(aPresContext, aOldFrame); - - mInner->SanityCheck(); - - // mark us dirty and generate a reflow command - return GenerateDirtyReflowCommand(aPresContext, aPresShell); -} - NS_IMETHODIMP nsBoxFrame::Destroy(nsIPresContext* aPresContext) { // if we are root remove 1 from the debug count. if (mState & NS_STATE_IS_ROOT) - nsBoxDebug::GetPref(aPresContext); + mInner->GetDebugPref(aPresContext); - if (mState & NS_STATE_CURRENTLY_IN_DEBUG) - nsBoxDebug::Release(aPresContext); - // recycle the Inner via the shell's arena. nsCOMPtr shell; aPresContext->GetShell(getter_AddRefs(shell)); @@ -2731,15 +833,8 @@ nsBoxFrame::Destroy(nsIPresContext* aPresContext) return nsHTMLContainerFrame::Destroy(aPresContext); } -void -nsBoxFrameInner::RecycleFreedMemory(nsIPresShell* aShell, void* aMem) -{ - size_t* sz = (size_t*)aMem; - aShell->FreeFrame(*sz, aMem); -} - NS_IMETHODIMP -nsBoxFrame::SetDebug(nsIPresContext* aPresContext, PRBool aDebug) +nsBoxFrame::SetDebug(nsBoxLayoutState& aState, PRBool aDebug) { // see if our state matches the given debug state PRBool debugSet = mState & NS_STATE_CURRENTLY_IN_DEBUG; @@ -2750,26 +845,50 @@ nsBoxFrame::SetDebug(nsIPresContext* aPresContext, PRBool aDebug) { if (aDebug) { mState |= NS_STATE_CURRENTLY_IN_DEBUG; - nsBoxDebug::AddRef(aPresContext, this); } else { mState &= ~NS_STATE_CURRENTLY_IN_DEBUG; - nsBoxDebug::Release(aPresContext); } + + SetDebugOnChildList(aState, mFirstChild, aDebug); - return mInner->mInfoList->SetDebug(aPresContext, aDebug); + NeedsRecalc(); } return NS_OK; } -void -nsBoxDebug::GetPref(nsIPresContext* aPresContext) +NS_IMETHODIMP +nsBoxFrame::NeedsRecalc() { - gDebug = PR_FALSE; - nsCOMPtr pref(do_GetService(NS_PREF_PROGID)); - if (pref) { - pref->GetBoolPref("xul.debug.box", &gDebug); - } + SizeNeedsRecalc(mInner->mPrefSize); + SizeNeedsRecalc(mInner->mMinSize); + SizeNeedsRecalc(mInner->mMaxSize); + CoordNeedsRecalc(mInner->mFlex); + CoordNeedsRecalc(mInner->mAscent); + return NS_OK; +} + +NS_IMETHODIMP +nsBoxFrame::RemoveFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame) +{ + SanityCheck(mFrames); + + // remove child from our info list + Remove(&aPresShell, aOldFrame); + + // remove the child frame + mFrames.DestroyFrame(aPresContext, aOldFrame); + + SanityCheck(mFrames); + + // mark us dirty and generate a reflow command + nsBoxLayoutState state(aPresContext); + MarkDirtyChildren(state); + MarkDirty(state); + return NS_OK; } NS_IMETHODIMP @@ -2779,23 +898,32 @@ nsBoxFrame::InsertFrames(nsIPresContext* aPresContext, nsIFrame* aPrevFrame, nsIFrame* aFrameList) { - mInner->SanityCheck(); + SanityCheck(mFrames); + + nsIBox* prevBox = GetBox(aPrevFrame); + if (prevBox == nsnull && aPrevFrame != nsnull) { + printf("Warning prev sibling is not in our list!!!"); + aPrevFrame = nsnull; + } // insert the frames to our info list - mInner->mInfoList->Insert(&aPresShell, aPrevFrame, aFrameList); + Insert(&aPresShell, aPrevFrame, aFrameList); // insert the frames in out regular frame list mFrames.InsertFrames(this, aPrevFrame, aFrameList); + nsBoxLayoutState state(aPresContext); + // if we are in debug make sure our children are in debug as well. if (mState & NS_STATE_CURRENTLY_IN_DEBUG) - mInner->mInfoList->SetDebug(aPresContext, PR_TRUE); + SetDebugOnChildList(state, mFirstChild, PR_TRUE); - mInner->SanityCheck(); + SanityCheck(mFrames); // mark us dirty and generate a reflow command - return GenerateDirtyReflowCommand(aPresContext, aPresShell); - + MarkDirtyChildren(state); + MarkDirty(state); + return NS_OK; } @@ -2805,22 +933,25 @@ nsBoxFrame::AppendFrames(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aFrameList) { - mInner->SanityCheck(); + SanityCheck(mFrames); // append them after - mInner->mInfoList->Append(&aPresShell,aFrameList); + Append(&aPresShell,aFrameList); // append in regular frames mFrames.AppendFrames(this, aFrameList); - + + nsBoxLayoutState state(aPresContext); + // if we are in debug make sure our children are in debug as well. if (mState & NS_STATE_CURRENTLY_IN_DEBUG) - mInner->mInfoList->SetDebug(aPresContext, PR_TRUE); + SetDebugOnChildList(state, mFirstChild, PR_TRUE); - mInner->SanityCheck(); + SanityCheck(mFrames); - // mark us dirty and generate a reflow command - return GenerateDirtyReflowCommand(aPresContext, aPresShell); + MarkDirtyChildren(state); + MarkDirty(state); + return NS_OK; } @@ -2880,181 +1011,36 @@ nsBoxFrame::AttributeChanged(nsIPresContext* aPresContext, nsCOMPtr shell; aPresContext->GetShell(getter_AddRefs(shell)); - GenerateDirtyReflowCommand(aPresContext, *shell); + nsBoxLayoutState state(aPresContext); + MarkDirty(state); } return rv; } -/** - * Goes though each child asking for its size to determine our size. Returns our box size minus our border. - * This method is defined in nsIBox interface. - */ -/** - * Goes though each child asking for its size to determine our size. Returns our box size minus our border. - * This method is defined in nsIBox interface. - */ -NS_IMETHODIMP -nsBoxFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize) +NS_IMETHODIMP +nsBoxFrame::GetInset(nsMargin& margin) { - nsIFrame* incrementalChild = nsnull; + margin.SizeTo(0,0,0,0); - if (aReflowState.reason == eReflowReason_Incremental) { - // then get the child we need to flow incrementally - aReflowState.reflowCommand->GetNext(incrementalChild, PR_FALSE); - } + if (mState & NS_STATE_CURRENTLY_IN_DEBUG) { + nsMargin debugMargin(0,0,0,0); + nsMargin debugBorder(0,0,0,0); + nsMargin debugPadding(0,0,0,0); + mInner->GetDebugBorder(debugBorder); + mInner->PixelMarginToTwips(mInner->mPresContext, debugBorder); + mInner->GetDebugMargin(debugMargin); + mInner->PixelMarginToTwips(mInner->mPresContext, debugMargin); + mInner->GetDebugMargin(debugPadding); + mInner->PixelMarginToTwips(mInner->mPresContext, debugPadding); + margin += debugBorder; + margin += debugMargin; + margin += debugPadding; + } - //nsMargin debugInset(0,0,0,0); - //mInner->GetDebugInset(debugInset); - - nsresult rv; - - aSize.Clear(); - GetDefaultFlex(aSize.flex); - - // run through all the children and get there min, max, and preferred sizes - // return us the size of the box - - nsCalculatedBoxInfo* info = mInner->mInfoList->GetFirst(); - - while (info) - { - // see if the child is collapsed - const nsStyleDisplay* disp; - info->frame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)disp)); - - PRBool collapsed = (info->mFlags & NS_FRAME_BOX_IS_COLLAPSED); - PRBool visibilityCollapsed = disp->mVisible == NS_STYLE_VISIBILITY_COLLAPSE; - PRBool collapsedChanged = (!collapsed && visibilityCollapsed) || (collapsed && !visibilityCollapsed); - - // if a child needs recalculation then ask it for its size. Otherwise - // just use the size we already have. - if ((info->mFlags & NS_FRAME_BOX_NEEDS_RECALC) || info->frame == incrementalChild || collapsedChanged) - { - if (visibilityCollapsed) { - nsFrameState childState; - info->frame->GetFrameState(&childState); - childState |= NS_FRAME_IS_DIRTY; - info->frame->SetFrameState(childState); - } - - if (!visibilityCollapsed || aReflowState.reflowCommand != nsnull) { - // get the size of the child. This is the min, max, preferred, and spring constant - // it does not include its border. - rv = GetChildBoxInfo(aPresContext, aReflowState, info->frame, *info); - - NS_ASSERTION(rv == NS_OK,"failed to child box info"); - if (NS_FAILED(rv)) - return rv; - - // add in the child's margin and border/padding if there is one. - const nsStyleSpacing* spacing; - rv = info->frame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - NS_ASSERTION(rv == NS_OK,"failed to get spacing info"); - if (NS_FAILED(rv)) - return rv; - - nsMargin margin(0,0,0,0); - spacing->GetMargin(margin); - nsSize m(margin.left+margin.right,margin.top+margin.bottom); - info->minSize += m; - info->prefSize += m; - if (info->maxSize.width != NS_INTRINSICSIZE) - info->maxSize.width += m.width; - - if (info->maxSize.height != NS_INTRINSICSIZE) - info->maxSize.height += m.height; - - spacing->GetBorderPadding(margin); - nsSize b(margin.left+margin.right,margin.top+margin.bottom); - info->minSize += b; - info->prefSize += b; - if (info->maxSize.width != NS_INTRINSICSIZE) - info->maxSize.width += b.width; - - if (info->maxSize.height != NS_INTRINSICSIZE) - info->maxSize.height += b.height; - - } - - - // ok we don't need to calc this guy again - info->mFlags &= ~NS_FRAME_BOX_NEEDS_RECALC; - - if (visibilityCollapsed) { - info->mFlags |= NS_FRAME_BOX_IS_COLLAPSED; - } - } - - if (!visibilityCollapsed) - AddChildSize(aSize, *info); - - // if horizontal get the largest child's ascent - if (mState & NS_STATE_IS_HORIZONTAL) { - if (info->ascent > aSize.ascent) - aSize.ascent = info->ascent; - } else { - // if vertical then get the last child's ascent. - if (info->next) - aSize.ascent += info->prefSize.height; - else - aSize.ascent += info->ascent; - } - - info = info->next; - } - - // add the insets into our size. This is merely some extra space subclasses like toolbars - // can place around us. Toolbars use it to place extra control like grippies around things. - nsMargin inset(0,0,0,0); - GetInset(inset); - - // inset += debugInset; - - nsSize in(inset.left+inset.right,inset.top+inset.bottom); - aSize.minSize += in; - aSize.prefSize += in; - - /* - // make sure we can see the debug info - if (aSize.maxSize.width < debugInset.left + debugInset.right) - aSize.maxSize.width = debugInset.left + debugInset.right; - - if (aSize.maxSize.height < debugInset.top + debugInset.bottom) - aSize.maxSize.height = debugInset.top + debugInset.bottom; - */ - - aSize.ascent += inset.top; - //aSize.ascent += debugInset.top; - - return rv; + return NS_OK; } -void -nsBoxFrame::AddChildSize(nsBoxInfo& aInfo, nsBoxInfo& aChildInfo) -{ - // if the child is not flexible then its min, max, is the same as its pref. - if (aChildInfo.flex == 0) { - - nsSize min(aChildInfo.minSize); - nsSize max(aChildInfo.maxSize); - nsSize pref(aChildInfo.prefSize); - - SET_WIDTH(min, GET_WIDTH(pref)); - SET_WIDTH(max, GET_WIDTH(pref)); - - AddSize(min, aInfo.minSize, PR_FALSE); - AddSize(max, aInfo.maxSize, PR_TRUE); - AddSize(pref, aInfo.prefSize, PR_FALSE); - } else { - // now that we know our child's min, max, pref sizes figure OUR size from them. - AddSize(aChildInfo.minSize, aInfo.minSize, PR_FALSE); - AddSize(aChildInfo.maxSize, aInfo.maxSize, PR_TRUE); - AddSize(aChildInfo.prefSize, aInfo.prefSize, PR_FALSE); - } -} NS_IMETHODIMP nsBoxFrame :: Paint ( nsIPresContext* aPresContext, @@ -3069,32 +1055,34 @@ nsBoxFrame :: Paint ( nsIPresContext* aPresContext, if (!disp->IsVisibleOrCollapsed()) return NS_OK; + if (disp->mVisible == NS_STYLE_VISIBILITY_COLLAPSE) + return NS_OK; + // if we are visible then tell our superclass to paint nsresult r = nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + /* if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { if (mState & NS_STATE_CURRENTLY_IN_DEBUG) { - nsBoxDebug::gInstance->PaintSprings(aPresContext, this, aRenderingContext, aDirtyRect); + mInner->PaintDebug(this, aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); } } - - - /* -#ifdef DEBUG_REFLOW - if (mInner->reflowCount == gViewPortReflowCount) { - if (!mInner->mResized) - aRenderingContext.SetColor(NS_RGB(255,0,0)); - else - aRenderingContext.SetColor(NS_RGB(0,255,0)); - - aRenderingContext.DrawRect(nsRect(0,0,mRect.width, mRect.height)); - } -#endif */ + return r; } +void +nsBoxFrameInner::GetDebugPref(nsIPresContext* aPresContext) +{ + gDebug = PR_FALSE; + nsCOMPtr pref(do_GetService(NS_PREF_PROGID)); + if (pref) { + pref->GetBoolPref("xul.debug.box", &gDebug); + } +} + // Paint one child frame void nsBoxFrame::PaintChild(nsIPresContext* aPresContext, @@ -3119,6 +1107,70 @@ nsBoxFrame::PaintChildren(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + nsMargin debugBorder; + nsMargin debugMargin; + nsMargin debugPadding; + nsMargin border; + nscoord onePixel; + nsRect inner; + + if (mState & NS_STATE_CURRENTLY_IN_DEBUG) + { + PRBool isHorizontal = IsHorizontal(); + + float p2t; + aPresContext->GetScaledPixelsToTwips(&p2t); + onePixel = NSIntPixelsToTwips(1, p2t); + + mInner->GetDebugBorder(debugBorder); + mInner->PixelMarginToTwips(aPresContext, debugBorder); + + mInner->GetDebugMargin(debugMargin); + mInner->PixelMarginToTwips(aPresContext, debugMargin); + + mInner->GetDebugPadding(debugPadding); + mInner->PixelMarginToTwips(aPresContext, debugPadding); + + GetContentRect(inner); + inner.Deflate(debugMargin); + GetBorder(border); + + inner.Deflate(border); + nsRect borderRect(inner); + + nscolor color; + if (isHorizontal) { + color = NS_RGB(0,0,255); + } else { + color = NS_RGB(255,0,0); + } + + aRenderingContext.SetColor(color); + + //left + nsRect r(inner); + r.width = debugBorder.left; + aRenderingContext.FillRect(r); + + // top + r = inner; + r.height = debugBorder.top; + aRenderingContext.FillRect(r); + + //right + r = inner; + r.x = r.x + r.width - debugBorder.right; + r.width = debugBorder.right; + aRenderingContext.FillRect(r); + + //bottom + r = inner; + r.y = r.y + r.height - debugBorder.bottom; + r.height = debugBorder.bottom; + aRenderingContext.FillRect(r); + } + + const nsStyleDisplay* disp = (const nsStyleDisplay*) mStyleContext->GetStyleData(eStyleStruct_Display); @@ -3132,27 +1184,29 @@ nsBoxFrame::PaintChildren(nsIPresContext* aPresContext, // If overflow is hidden then set the clip rect so that children // don't leak out of us if (NS_STYLE_OVERFLOW_HIDDEN == disp->mOverflow) { - //nsMargin dm(0,0,0,0); - //mInner->GetDebugInset(dm); nsMargin im(0,0,0,0); + nsBoxLayoutState state(aPresContext); GetInset(im); nsMargin border(0,0,0,0); const nsStyleSpacing* spacing = (const nsStyleSpacing*) mStyleContext->GetStyleData(eStyleStruct_Spacing); spacing->GetBorderPadding(border); r.Deflate(im); - //r.Deflate(dm); r.Deflate(border); } - nsIFrame* kid = mFrames.FirstChild(); + nsIBox* kid = nsnull; + GetChildBox(&kid); while (nsnull != kid) { + nsIFrame* frame = nsnull; + kid->GetFrame(&frame); + if (!hasClipped && NS_STYLE_OVERFLOW_HIDDEN == disp->mOverflow) { // if we haven't already clipped and we should // check to see if the child is in out bounds. If not then // we begin clipping. nsRect cr(0,0,0,0); - kid->GetRect(cr); + kid->GetBounds(cr); // if our rect does not contain the childs then begin clipping if (!r.Contains(cr)) { @@ -3163,72 +1217,452 @@ nsBoxFrame::PaintChildren(nsIPresContext* aPresContext, } } - PaintChild(aPresContext, aRenderingContext, aDirtyRect, kid, aWhichLayer); - kid->GetNextSibling(&kid); + PaintChild(aPresContext, aRenderingContext, aDirtyRect, frame, aWhichLayer); + + kid->GetNextBox(&kid); } if (hasClipped) { aRenderingContext.PopState(clipState); } + + if (mState & NS_STATE_CURRENTLY_IN_DEBUG) + { + GetContentRect(r); + + if (NS_STYLE_OVERFLOW_HIDDEN == disp->mOverflow) { + mInner->GetDebugMargin(debugMargin); + mInner->PixelMarginToTwips(aPresContext, debugMargin); + r.Deflate(debugMargin); + } + + hasClipped = PR_FALSE; + + GetChildBox(&kid); + while (nsnull != kid) { + if (!hasClipped && NS_STYLE_OVERFLOW_HIDDEN == disp->mOverflow) { + // if we haven't already clipped and we should + // check to see if the child is in out bounds. If not then + // we begin clipping. + nsRect cr(0,0,0,0); + kid->GetBounds(cr); + + // if our rect does not contain the childs then begin clipping + if (!r.Contains(cr)) { + aRenderingContext.PushState(); + aRenderingContext.SetClipRect(r, + nsClipCombine_kIntersect, clipState); + hasClipped = PR_TRUE; + } + } + PRBool isHorizontal = IsHorizontal(); + + nscoord x, y, borderSize, springSize; + + nsRect cr(0,0,0,0); + kid->GetBounds(cr); + nsMargin margin; + kid->GetMargin(margin); + cr.Inflate(margin); + + if (isHorizontal) + { + cr.y = inner.y; + x = cr.x; + y = cr.y + onePixel; + springSize = debugBorder.top - onePixel*4; + } else { + cr.x = inner.x; + x = cr.y; + y = cr.x + onePixel; + springSize = debugBorder.left - onePixel*4; + } + + nsBoxLayoutState state(aPresContext); + nscoord flex = 0; + kid->GetFlex(state, flex); + + + PRBool isCollapsed = PR_FALSE; + kid->IsCollapsed(state, isCollapsed); + + if (!isCollapsed) { + aRenderingContext.SetColor(NS_RGB(255,255,255)); + + if (isHorizontal) + borderSize = cr.width; + else + borderSize = cr.height; + + mInner->DrawSpring(aPresContext, aRenderingContext, isHorizontal, flex, x, y, borderSize, springSize); + } + + kid->GetNextBox(&kid); + } + + if (hasClipped) { + aRenderingContext.PopState(clipState); + } + } +} + +NS_IMETHODIMP_(nsrefcnt) +nsBoxFrame::AddRef(void) +{ + return NS_OK; +} + +NS_IMETHODIMP_(nsrefcnt) +nsBoxFrame::Release(void) +{ + return NS_OK; +} + +NS_INTERFACE_MAP_BEGIN(nsBoxFrame) + NS_INTERFACE_MAP_ENTRY(nsIBox) +#ifdef NS_DEBUG + NS_INTERFACE_MAP_ENTRY(nsIFrameDebug) +#endif + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBox) +NS_INTERFACE_MAP_END_INHERITING(nsHTMLContainerFrame) + +NS_IMETHODIMP +nsBoxFrame::GetFrame(nsIFrame** aFrame) +{ + *aFrame = this; + return NS_OK; +} + +NS_IMETHODIMP +nsBoxFrame::GetFrameName(nsString& aResult) const +{ + nsCOMPtr content; + nsBoxFrame* box = (nsBoxFrame*)this; + box->GetContentOf(getter_AddRefs(content)); + nsAutoString id; + + if (content) + content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, id); + + aResult = "Box[id="; + aResult.Append(id); + aResult.Append("]"); + return NS_OK; +} + +NS_IMETHODIMP +nsBoxFrame::GetDebug(PRBool& aDebug) +{ + aDebug = (mState & NS_STATE_CURRENTLY_IN_DEBUG); + return NS_OK; +} + +NS_IMETHODIMP +nsBoxFrame::GetFrameForPoint(nsIPresContext* aPresContext, + const nsPoint& aPoint, + nsFramePaintLayer aWhichLayer, + nsIFrame** aFrame) +{ + if (!mRect.Contains(aPoint)) + return NS_ERROR_FAILURE; + + nsIView* view = nsnull; + GetView(aPresContext, &view); + + // get the debug frame. + if (view || (mState & NS_STATE_IS_ROOT)) + { + nsIBox* box = nsnull; + if (NS_SUCCEEDED(GetDebugBoxAt(aPoint, &box)) && box) + { + PRBool isDebug = PR_FALSE; + box->GetDebug(isDebug); + if (isDebug) { + nsIFrame* frame = nsnull; + box->GetFrame(&frame); + *aFrame = frame; + return NS_OK; + } + } + } + + + if (mMouseThrough == never) + { + *aFrame = this; + return NS_OK; + } + + // This won't work. + nsresult rv = GetFrameForPointUsing(aPresContext, aPoint, nsnull, aWhichLayer, PR_FALSE, aFrame); + + /* + nsRect r(0,0,mRect.width, mRect.height); + + // if it is not inside us fail + if (!r.Contains(aPoint)) { + return NS_ERROR_FAILURE; + } + + // is it inside our border, padding, and debugborder or insets? + nsMargin im(0,0,0,0); + nsBoxLayoutState state(aPresContext); + GetInset(im); + nsMargin border(0,0,0,0); + GetBorderAndPadding(border); + r.Deflate(im); + r.Deflate(border); + + // no? Then it must be in our border so return us. + if (!r.Contains(aPoint)) { + *aFrame = this; + return NS_OK; + } + + // ok lets look throught the children + *aFrame = nsnull; + nsIBox* child = nsnull; + GetChildBox(&child); + nsPoint tmp; + nsIFrame *frame = nsnull, *hit = nsnull; + tmp.MoveTo(aPoint.x - mRect.x, aPoint.y - mRect.y); + while(child) + { + child->GetFrame(&frame); + nsresult rv = frame->GetFrameForPoint(aPresContext, tmp, aWhichLayer, &hit); + + if (NS_SUCCEEDED(rv) && hit) { + *aFrame = hit; + } + + child->GetNextBox(&child); + } + + // found it. + if (hit) + return NS_OK; + + */ + + if (rv != NS_ERROR_FAILURE) + return rv; + + // see if it is in our border, padding, or inset + nsRect r(mRect); + nsMargin m; + GetInset(m); + r.Deflate(m); + GetBorderAndPadding(m); + r.Deflate(m); + if (!r.Contains(aPoint)) { + *aFrame = this; + return NS_OK; + } + + if (mMouseThrough == sometimes) + { + *aFrame = this; + return NS_OK; + } + + const nsStyleColor* color = (const nsStyleColor*) + mStyleContext->GetStyleData(eStyleStruct_Color); + PRBool transparentBG = NS_STYLE_BG_COLOR_TRANSPARENT == + (color->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT); + + if (!transparentBG) + { + *aFrame = this; + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + + + +NS_IMETHODIMP +nsBoxFrame::GetCursor(nsIPresContext* aPresContext, + nsPoint& aPoint, + PRInt32& aCursor) +{ + /* + #ifdef NS_DEBUG + printf("Get Cursor: "); + nsFrame::ListTag(stdout, this); + printf("\n"); + + #endif + */ + + nsPoint newPoint; + mInner->TranslateEventCoords(aPresContext, aPoint, newPoint); + + // if we are in debug and we are in the debug area + // return our own cursor and dump the debug information. + if (mState & NS_STATE_CURRENTLY_IN_DEBUG) + { + nsresult rv = mInner->DisplayDebugInfoFor(this, aPresContext, newPoint, aCursor); + if (rv == NS_OK) + return rv; + } + + nsresult rv = nsHTMLContainerFrame::GetCursor(aPresContext, aPoint, aCursor); + + return rv; +} + +//XXX the event come's in in view relative coords, but really should +//be in frame relative coords by the time it hits our frame. + +// Translate an point that is relative to our view (or a containing +// view) into a localized pixel coordinate that is relative to the +// content area of this frame (inside the border+padding). +void +nsBoxFrameInner::TranslateEventCoords(nsIPresContext* aPresContext, + const nsPoint& aPoint, + nsPoint& aResult) +{ + nscoord x = aPoint.x; + nscoord y = aPoint.y; + + // If we have a view then the event coordinates are already relative + // to this frame; otherwise we have to adjust the coordinates + // appropriately. + nsIView* view; + mOuter->GetView(aPresContext, &view); + if (nsnull == view) { + nsPoint offset; + mOuter->GetOffsetFromView(aPresContext, offset, &view); + if (nsnull != view) { + x -= offset.x; + y -= offset.y; + } + } + + aResult.x = x; + aResult.y = y; + +} + + +nsresult +nsBoxFrame::GetContentOf(nsIContent** aContent) +{ + // If we don't have a content node find a parent that does. + nsIFrame* frame; + GetFrame(&frame); + + while(frame != nsnull) { + + frame->GetContent(aContent); + if (*aContent != nsnull) + return NS_OK; + + frame->GetParent(&frame); + } + + return NS_OK; +} + + + +void* +nsBoxFrameInner::operator new(size_t sz, nsIPresShell* aPresShell) +{ + return nsBoxLayoutState::Allocate(sz,aPresShell); } void -nsBoxDebug::PaintSprings(nsIPresContext* aPresContext, nsBoxFrame* aBoxFrame, - nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect) +nsBoxFrameInner::Recycle(nsIPresShell* aPresShell) +{ + mOuter->ClearChildren(aPresShell); + + delete this; + nsBoxLayoutState::RecycleFreedMemory(aPresShell, this); +} + + +// Overridden to prevent the global delete from being called, since the memory +// came out of an nsIArena instead of the global delete operator's heap. +void +nsBoxFrameInner::operator delete(void* aPtr, size_t sz) +{ + nsBoxLayoutState::Free(aPtr, sz); +} + + + +nsresult +nsBoxFrameInner::PaintDebug(nsIBox* aBox, + nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) + { - PRBool isHorizontal = aBoxFrame->mState & NS_STATE_IS_HORIZONTAL; - - // remove our border - const nsStyleSpacing* spacing; - aBoxFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - nsMargin border(0,0,0,0); - spacing->GetBorderPadding(border); + PRBool isHorizontal = mOuter->IsHorizontal(); float p2t; aPresContext->GetScaledPixelsToTwips(&p2t); nscoord onePixel = NSIntPixelsToTwips(1, p2t); - nsIStyleContext* debugStyle; - if (aBoxFrame->mState & NS_STATE_IS_HORIZONTAL) - debugStyle = mHorizontalDebugStyle; - else - debugStyle = mVerticalDebugStyle; - - if (debugStyle == nsnull) - return; - - const nsStyleSpacing* debugSpacing = - (const nsStyleSpacing*)debugStyle->GetStyleData(eStyleStruct_Spacing); - const nsStyleColor* debugColor = - (const nsStyleColor*)debugStyle->GetStyleData(eStyleStruct_Color); - - nsMargin margin(0,0,0,0); - debugSpacing->GetMargin(margin); - - border += margin; - - nsRect inner(0,0,aBoxFrame->mRect.width, aBoxFrame->mRect.height); - inner.Deflate(border); - - // paint our debug border - nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aBoxFrame, - aDirtyRect, inner, *debugSpacing, debugStyle, 0); - - // get the debug border dimensions nsMargin debugBorder(0,0,0,0); - debugSpacing->GetBorderPadding(debugBorder); + nsMargin debugMargin(0,0,0,0); + nsMargin debugPadding(0,0,0,0); + GetDebugBorder(debugBorder); + PixelMarginToTwips(aPresContext, debugBorder); + + GetDebugMargin(debugMargin); + PixelMarginToTwips(aPresContext, debugMargin); + + GetDebugPadding(debugPadding); + PixelMarginToTwips(aPresContext, debugPadding); + + nsRect inner(0,0,0,0); + aBox->GetContentRect(inner); + + inner.Deflate(debugMargin); + + nsRect borderRect(inner); + + nscolor color; + if (isHorizontal) { + color = NS_RGB(0,0,255); + } else { + color = NS_RGB(255,0,0); + } + + //left + aRenderingContext.SetColor(color); + nsRect r(inner); + r.width = debugBorder.left; + aRenderingContext.FillRect(r); + + // top + r = inner; + r.height = debugBorder.top; + aRenderingContext.FillRect(r); + + //right + r = inner; + r.x = r.x + r.width - debugBorder.right; + r.width = debugBorder.right; + aRenderingContext.FillRect(r); + + //bottom + r = inner; + r.y = r.y + r.height - debugBorder.bottom; + r.height = debugBorder.bottom; + aRenderingContext.FillRect(r); // paint the springs. nscoord x, y, borderSize, springSize; - - aRenderingContext.SetColor(debugColor->mColor); + aRenderingContext.SetColor(NS_RGB(255,255,255)); - if (isHorizontal) { x = inner.x; @@ -3242,10 +1676,17 @@ nsBoxDebug::PaintSprings(nsIPresContext* aPresContext, nsBoxFrame* aBoxFrame, springSize = debugBorder.left - onePixel*4; } - nsCalculatedBoxInfo* info = aBoxFrame->GetInfoList()->GetFirst(); - while (info) { - nsSize& size = info->calculatedSize; - if (!(info->mFlags & NS_FRAME_BOX_IS_COLLAPSED)) { + nsIBox* box = nsnull; + aBox->GetChildBox(&box); + nsBoxLayoutState state(aPresContext); + + while (box) { + nsSize size; + GetFrameSizeWithMargin(box, size); + PRBool isCollapsed = PR_FALSE; + box->IsCollapsed(state, isCollapsed); + + if (!isCollapsed) { if (isHorizontal) borderSize = size.width; else @@ -3263,15 +1704,21 @@ nsBoxDebug::PaintSprings(nsIPresContext* aPresContext, nsBoxFrame* aBoxFrame, } */ - DrawSpring(aPresContext, aRenderingContext, isHorizontal, info->flex, x, y, borderSize, springSize); + nscoord flex = 0; + box->GetFlex(state, flex); + + DrawSpring(aPresContext, aRenderingContext, isHorizontal, flex, x, y, borderSize, springSize); x += borderSize; } - info = info->next; + box->GetNextBox(&box); } + + return NS_OK; } + void -nsBoxDebug::DrawLine(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x1, nscoord y1, nscoord x2, nscoord y2) +nsBoxFrameInner::DrawLine(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x1, nscoord y1, nscoord x2, nscoord y2) { if (aHorizontal) aRenderingContext.DrawLine(x1,y1,x2,y2); @@ -3280,7 +1727,7 @@ nsBoxDebug::DrawLine(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, } void -nsBoxDebug::FillRect(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x, nscoord y, nscoord width, nscoord height) +nsBoxFrameInner::FillRect(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x, nscoord y, nscoord width, nscoord height) { if (aHorizontal) aRenderingContext.FillRect(x,y,width,height); @@ -3289,7 +1736,7 @@ nsBoxDebug::FillRect(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, } void -nsBoxDebug::DrawSpring(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, PRBool aHorizontal, PRInt32 flex, nscoord x, nscoord y, nscoord size, nscoord springSize) +nsBoxFrameInner::DrawSpring(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, PRBool aHorizontal, PRInt32 flex, nscoord x, nscoord y, nscoord size, nscoord springSize) { float p2t; aPresContext->GetScaledPixelsToTwips(&p2t); @@ -3329,253 +1776,44 @@ nsBoxDebug::DrawSpring(nsIPresContext* aPresContext, nsIRenderingContext& aRende } void -nsBoxDebug::AddRef(nsIPresContext* aPresContext, nsBoxFrame* aBoxFrame) +nsBoxFrameInner::GetDebugBorder(nsMargin& aInset) { - if (!gInstance) { - gInstance = new nsBoxDebug(aPresContext, aBoxFrame); - } + aInset.SizeTo(2,2,2,2); - gInstance->mRefCount++; + if (mOuter->IsHorizontal()) + aInset.top = 10; + else + aInset.left = 10; } void -nsBoxDebug::Release(nsIPresContext* aPresContext) +nsBoxFrameInner::GetDebugMargin(nsMargin& aInset) { - NS_ASSERTION(gInstance && gInstance->mRefCount > 0, "nsBoxDebug Realsed too may times!!"); - - gInstance->mRefCount--; - if (gInstance->mRefCount == 0) { - delete gInstance; - gInstance = nsnull; - } -} - -nsBoxDebug::nsBoxDebug(nsIPresContext* aPresContext, nsBoxFrame* aBoxFrame) -{ - nsCOMPtr content; - aBoxFrame->mInner->GetContentOf(aBoxFrame, getter_AddRefs(content)); - - nsCOMPtr atom ( getter_AddRefs(NS_NewAtom(":-moz-horizontal-box-debug")) ); - aPresContext->ProbePseudoStyleContextFor(content, atom, aBoxFrame->mStyleContext, - PR_FALSE, - getter_AddRefs(mHorizontalDebugStyle)); - - atom = getter_AddRefs(NS_NewAtom(":-moz-vertical-box-debug")); - aPresContext->ProbePseudoStyleContextFor(content, atom, aBoxFrame->mStyleContext, - PR_FALSE, - getter_AddRefs(mVerticalDebugStyle)); - - mDebugChild = nsnull; - mRefCount = 0; + aInset.SizeTo(2,2,2,2); } void -nsBoxFrameInner::GetDebugInset(nsMargin& inset) +nsBoxFrameInner::GetDebugPadding(nsMargin& aPadding) { - inset.SizeTo(0,0,0,0); - - if (mOuter->mState & NS_STATE_CURRENTLY_IN_DEBUG) - { - nsIStyleContext* style; - if (mOuter->mState & NS_STATE_IS_HORIZONTAL) - style = nsBoxDebug::gInstance->mHorizontalDebugStyle; - else - style = nsBoxDebug::gInstance->mVerticalDebugStyle; - - if (style == nsnull) - return; - - const nsStyleSpacing* debugSpacing = - (const nsStyleSpacing*)style->GetStyleData(eStyleStruct_Spacing); - - debugSpacing->GetBorderPadding(inset); - nsMargin margin(0,0,0,0); - debugSpacing->GetMargin(margin); - inset += margin; - } + aPadding.SizeTo(2,2,2,2); } -NS_IMETHODIMP_(nsrefcnt) -nsBoxFrame::AddRef(void) -{ - return NS_OK; -} - -NS_IMETHODIMP_(nsrefcnt) -nsBoxFrame::Release(void) -{ - return NS_OK; -} - -NS_INTERFACE_MAP_BEGIN(nsBoxFrame) - NS_INTERFACE_MAP_ENTRY(nsIBox) -#ifdef NS_DEBUG - NS_INTERFACE_MAP_ENTRY(nsIFrameDebug) -#endif - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBox) -NS_INTERFACE_MAP_END_INHERITING(nsHTMLContainerFrame) - - -NS_IMETHODIMP -nsBoxFrame::GetFrameName(nsString& aResult) const -{ - nsCOMPtr content; - nsIFrame* frame = (nsIFrame*)this; - mInner->GetContentOf(frame, getter_AddRefs(content)); - - nsAutoString id; - content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, id); - - aResult = "Box[id="; - aResult.Append(id); - aResult.Append("]"); - return NS_OK; -} - -void* -nsCalculatedBoxInfoImpl::operator new(size_t sz, nsIPresShell* aPresShell) -{ - return nsBoxFrameInner::Allocate(sz,aPresShell); -} void -nsCalculatedBoxInfo::Recycle(nsIPresShell* aShell) +nsBoxFrameInner::PixelMarginToTwips(nsIPresContext* aPresContext, nsMargin& aMarginPixels) { -} - -void -nsCalculatedBoxInfoImpl::Recycle(nsIPresShell* aShell) -{ - delete this; - nsBoxFrameInner::RecycleFreedMemory(aShell, this); -} - -// Overridden to prevent the global delete from being called, since the memory -// came out of an nsIArena instead of the global delete operator's heap. -void -nsCalculatedBoxInfoImpl::operator delete(void* aPtr, size_t sz) -{ - nsBoxFrameInner::Free(aPtr, sz); -} - -//static PRInt32 gBoxInfoCount = 0; - -nsCalculatedBoxInfoImpl::nsCalculatedBoxInfoImpl(nsIFrame* aFrame) -{ - //gBoxInfoCount++; - // printf("created Info=%d\n",gBoxInfoCount); - - mFlags = NS_FRAME_BOX_NEEDS_RECALC; - - next = nsnull; - calculatedSize.width = 0; - calculatedSize.height = 0; - frame = aFrame; - prefSize.width = 0; - prefSize.height = 0; - minSize.width = 0; - minSize.height = 0; - ascent = 0; - flex = 0; - maxSize.width = NS_INTRINSICSIZE; - maxSize.height = NS_INTRINSICSIZE; -} - -nsCalculatedBoxInfoImpl::~nsCalculatedBoxInfoImpl() -{ - // gBoxInfoCount--; - // printf("deleted Info=%d\n",gBoxInfoCount); -} - -void -nsCalculatedBoxInfoImpl::Clear() -{ - nsBoxInfo::Clear(); - - mFlags = NS_FRAME_BOX_NEEDS_RECALC; - - calculatedSize.width = 0; - calculatedSize.height = 0; - - //prefWidthIntrinsic = PR_TRUE; - //prefHeightIntrinsic = PR_TRUE; - -} - -NS_IMETHODIMP -nsBoxFrame::GetFrameForPoint(nsIPresContext* aPresContext, - const nsPoint& aPoint, - nsFramePaintLayer aWhichLayer, - nsIFrame** aFrame) -{ - // this should act like a block, so we need to override - return GetFrameForPointUsing(aPresContext, aPoint, nsnull, aWhichLayer, (aWhichLayer == NS_FRAME_PAINT_LAYER_BACKGROUND), aFrame); - - /* - nsRect r(0,0,mRect.width, mRect.height); - - // if it is not inside us fail - if (!r.Contains(aPoint)) { - return NS_ERROR_FAILURE; - } - - // is it inside our border, padding, and debugborder or insets? - //nsMargin dm(0,0,0,0); - //mInner->GetDebugInset(dm); - nsMargin im(0,0,0,0); - GetInset(im); - nsMargin border(0,0,0,0); - const nsStyleSpacing* spacing = (const nsStyleSpacing*) - mStyleContext->GetStyleData(eStyleStruct_Spacing); - spacing->GetBorderPadding(border); - r.Deflate(im); - //r.Deflate(dm); - r.Deflate(border); - - // no? Then it must be in our border so return us. - if (!r.Contains(aPoint)) { - *aFrame = this; - return NS_OK; - } - - // ok lets look throught the children - nsCalculatedBoxInfo* info = mInner->mInfoList->GetFirst(); - nsRect kidRect; - while(info) - { - info->frame->GetRect(kidRect); - - // Do a quick check and see if the child frame contains the point - if (kidRect.Contains(aPoint)) { - nsPoint tmp; - tmp.MoveTo(aPoint.x - kidRect.x, aPoint.y - kidRect.y); - return info->frame->GetFrameForPoint(aPresContext, tmp, aFrame); - } - - info = info->next; - } - - const nsStyleColor* color = - (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color); - - PRBool transparentBG = NS_STYLE_BG_COLOR_TRANSPARENT == - (color->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT); - - PRBool backgroundImage = (color->mBackgroundImage.Length() > 0); - - if (!transparentBG || backgroundImage) - { - *aFrame = this; - return NS_OK; - } - - return NS_ERROR_FAILURE; - */ + float p2t; + aPresContext->GetScaledPixelsToTwips(&p2t); + nscoord onePixel = NSIntPixelsToTwips(1, p2t); + aMarginPixels.left *= onePixel; + aMarginPixels.right *= onePixel; + aMarginPixels.top *= onePixel; + aMarginPixels.bottom *= onePixel; } void -nsBoxDebug::GetValue(nsIPresContext* aPresContext, const nsSize& a, const nsSize& b, char* ch) +nsBoxFrameInner::GetValue(nsIPresContext* aPresContext, const nsSize& a, const nsSize& b, char* ch) { float p2t; aPresContext->GetScaledPixelsToTwips(&p2t); @@ -3594,105 +1832,119 @@ nsBoxDebug::GetValue(nsIPresContext* aPresContext, const nsSize& a, const nsSize sprintf(height,"%d", nscoord(a.height/*/p2t*/)); - sprintf(ch, "(%s%s, %s%s)", width, (b.width != NS_INTRINSICSIZE ? "[CSS]" : ""), - height, (b.height != NS_INTRINSICSIZE ? "[CSS]" : "")); + sprintf(ch, "(%s%s, %s%s)", width, (b.width != NS_INTRINSICSIZE ? "[SET]" : ""), + height, (b.height != NS_INTRINSICSIZE ? "[SET]" : "")); } void -nsBoxDebug::GetValue(nsIPresContext* aPresContext, PRInt32 a, PRInt32 b, char* ch) +nsBoxFrameInner::GetValue(nsIPresContext* aPresContext, PRInt32 a, PRInt32 b, char* ch) { - sprintf(ch, "(%d)", a); + if (a == NS_INTRINSICSIZE) + sprintf(ch, "%d[SET]", b); + else + sprintf(ch, "%d", a); } -PRBool -nsBoxDebug::DisplayDebugInfoFor(nsIPresContext* aPresContext, - nsBoxFrame* aBoxFrame, +nsresult +nsBoxFrameInner::DisplayDebugInfoFor(nsIBox* aBox, + nsIPresContext* aPresContext, nsPoint& aPoint, PRInt32& aCursor) { + nsBoxLayoutState state(aPresContext); + nscoord x = aPoint.x; nscoord y = aPoint.y; - // get the area inside our border. - nsRect insideBorder(0,0,aBoxFrame->mRect.width, aBoxFrame->mRect.height); - - const nsStyleSpacing* spacing; - nsresult rv = aBoxFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - NS_ASSERTION(rv == NS_OK,"failed to get spacing"); - if (NS_FAILED(rv)) - return rv; - - nsMargin border; - spacing->GetBorderPadding(border); + nsIFrame* ourFrame = nsnull; + aBox->GetFrame(&ourFrame); + // get the area inside our border but not our debug margins. + nsRect insideBorder; + aBox->GetContentRect(insideBorder); + nsMargin border(0,0,0,0); + aBox->GetBorderAndPadding(border); insideBorder.Deflate(border); - PRBool isHorizontal = aBoxFrame->mState & NS_STATE_IS_HORIZONTAL; + PRBool isHorizontal = mOuter->IsHorizontal(); if (!insideBorder.Contains(nsPoint(x,y))) - return NS_OK; + return NS_ERROR_FAILURE; //printf("%%%%%% inside box %%%%%%%\n"); int count = 0; - nsCalculatedBoxInfo* info = aBoxFrame->GetInfoList()->GetFirst(); + nsIBox* child = nsnull; + aBox->GetChildBox(&child); nsMargin m; - aBoxFrame->mInner->GetDebugInset(m); + nsMargin m2; + GetDebugBorder(m); + PixelMarginToTwips(aPresContext, m); + + GetDebugMargin(m2); + PixelMarginToTwips(aPresContext, m2); + + m += m2; if ((isHorizontal && y < insideBorder.y + m.top) || (!isHorizontal && x < insideBorder.x + m.left)) { //printf("**** inside debug border *******\n"); - while (info) + while (child) { - nsIFrame* childFrame = info->frame; - nsRect r; - childFrame->GetRect(r); + nsRect r; + child->GetBounds(r); + nsIFrame* childFrame = nsnull; + child->GetFrame(&childFrame); // if we are not in the child. But in the spring above the child. if ((isHorizontal && x >= r.x && x < r.x + r.width) || (!isHorizontal && y >= r.y && y < r.y + r.height)) { aCursor = NS_STYLE_CURSOR_POINTER; // found it but we already showed it. - if (mDebugChild == childFrame) - return PR_TRUE; + if (mDebugChild == child) + return NS_OK; nsCOMPtr content; - aBoxFrame->mInner->GetContentOf(aBoxFrame, getter_AddRefs(content)); + ourFrame->GetContent(getter_AddRefs(content)); nsAutoString id; - content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, id); - char idValue[100]; - id.ToCString(idValue,100); - nsAutoString kClass; - content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, kClass); - char kClassValue[100]; - kClass.ToCString(kClassValue,100); - nsCOMPtr tag; - content->GetTag(*getter_AddRefs(tag)); nsAutoString tagString; - tag->ToString(tagString); char tagValue[100]; - tagString.ToCString(tagValue,100); + char kClassValue[100]; + char idValue[100]; - printf("----- "); + if (content) { + content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, id); + id.ToCString(idValue,100); + + content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, kClass); + kClass.ToCString(kClassValue,100); + + content->GetTag(*getter_AddRefs(tag)); + tag->ToString(tagString); + tagString.ToCString(tagValue,100); + + printf("----- "); - #ifdef NS_DEBUG - nsFrame::ListTag(stdout, aBoxFrame); - #endif + #ifdef NS_DEBUG + nsFrame::ListTag(stdout, ourFrame); + #endif - printf(" Tag='%s', id='%s' class='%s'---------------\n", tagValue, idValue, kClassValue); + printf(" Tag='%s', id='%s' class='%s'---------------\n", tagValue, idValue, kClassValue); + } childFrame->GetContent(getter_AddRefs(content)); if (content) { + id = ""; + kClass = ""; + tagString = ""; content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, id); id.ToCString(idValue,100); @@ -3712,119 +1964,44 @@ nsBoxDebug::DisplayDebugInfoFor(nsIPresContext* aPresContext, } - mDebugChild = childFrame; - nsCalculatedBoxInfoImpl aSize(childFrame); - aSize.prefSize.width = NS_INTRINSICSIZE; - aSize.prefSize.height = NS_INTRINSICSIZE; + mDebugChild = child; - aSize.minSize.width = NS_INTRINSICSIZE; - aSize.minSize.height = NS_INTRINSICSIZE; + nsSize prefSizeCSS(NS_INTRINSICSIZE, NS_INTRINSICSIZE); + nsSize minSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE); + nsSize maxSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE); + nscoord flexCSS = NS_INTRINSICSIZE; - aSize.maxSize.width = NS_INTRINSICSIZE; - aSize.maxSize.height = NS_INTRINSICSIZE; + nsSize prefSize(0, 0); + nsSize minSize (0, 0); + nsSize maxSize (NS_INTRINSICSIZE, NS_INTRINSICSIZE); + nscoord flexSize = 0; - aSize.calculatedSize.width = NS_INTRINSICSIZE; - aSize.calculatedSize.height = NS_INTRINSICSIZE; - aSize.flex = -1; + nsIBox::AddCSSPrefSize(state, child, prefSizeCSS); + nsIBox::AddCSSMinSize (state, child, minSizeCSS); + nsIBox::AddCSSMaxSize (state, child, maxSizeCSS); + nsIBox::AddCSSFlex (state, child, flexCSS); - // add in the css min, max, pref - const nsStylePosition* position; - rv = childFrame->GetStyleData(eStyleStruct_Position, - (const nsStyleStruct*&) position); - - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get position"); - if (NS_FAILED(rv)) - return PR_TRUE; - - // see if the width or height was specifically set - if (position->mWidth.GetUnit() == eStyleUnit_Coord) { - aSize.prefSize.width = position->mWidth.GetCoordValue(); - } - - if (position->mHeight.GetUnit() == eStyleUnit_Coord) { - aSize.prefSize.height = position->mHeight.GetCoordValue(); - } - - // same for min size. Unfortunately min size is always set to 0. So for now - // we will assume 0 means not set. - if (position->mMinWidth.GetUnit() == eStyleUnit_Coord) { - nscoord min = position->mMinWidth.GetCoordValue(); - if (min != 0) - aSize.minSize.width = min; - } - - if (position->mMinHeight.GetUnit() == eStyleUnit_Coord) { - nscoord min = position->mMinHeight.GetCoordValue(); - if (min != 0) - aSize.minSize.height = min; - } - - // and max - if (position->mMaxWidth.GetUnit() == eStyleUnit_Coord) { - nscoord max = position->mMaxWidth.GetCoordValue(); - aSize.maxSize.width = max; - } - - if (position->mMaxHeight.GetUnit() == eStyleUnit_Coord) { - nscoord max = position->mMaxHeight.GetCoordValue(); - aSize.maxSize.height = max; - } - - if (content) { - nsAutoString value; - PRInt32 error; - - if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::flex, value)) - { - value.Trim("%"); - aSize.flex = value.ToInteger(&error); - } - - - if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, value)) - { - float p2t; - aPresContext->GetScaledPixelsToTwips(&p2t); - - value.Trim("%"); - - aSize.prefSize.width = NSIntPixelsToTwips(value.ToInteger(&error), p2t); - } - - if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::height, value)) - { - float p2t; - aPresContext->GetScaledPixelsToTwips(&p2t); - - value.Trim("%"); - - aSize.prefSize.height = NSIntPixelsToTwips(value.ToInteger(&error), p2t); - } - - } + child->GetPrefSize(state, prefSize); + child->GetMinSize(state, minSize); + child->GetMaxSize(state, maxSize); + child->GetFlex(state, flexSize); char min[100]; char pref[100]; char max[100]; char calc[100]; char flex[100]; + + nsSize actualSize; + GetFrameSizeWithMargin(child, actualSize); + nsSize actualSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE); - /* - nsSize c(info->calculatedSize); - if (c.width != NS_INTRINSICSIZE) - c.width -= inset.left + inset.right; - - if (c.height != NS_INTRINSICSIZE) - c.height -= inset.left + inset.right; - - */ - - GetValue(aPresContext, info->minSize, aSize.minSize, min); - GetValue(aPresContext, info->prefSize, aSize.prefSize, pref); - GetValue(aPresContext, info->maxSize, aSize.maxSize, max); - GetValue(aPresContext, info->calculatedSize, aSize.calculatedSize, calc); - GetValue(aPresContext, info->flex, aSize.flex, flex); + GetValue(aPresContext, minSize, minSizeCSS, min); + GetValue(aPresContext, prefSize, prefSizeCSS, pref); + GetValue(aPresContext, maxSize, maxSizeCSS, max); + GetValue(aPresContext, actualSize, actualSizeCSS, calc); + GetValue(aPresContext, flexSize, flexCSS, flex); printf("min%s, pref%s, max%s, actual%s, flex=%s\n\n", @@ -3835,427 +2012,29 @@ nsBoxDebug::DisplayDebugInfoFor(nsIPresContext* aPresContext, flex ); - return PR_TRUE; + return NS_OK; } - info = info->next; + child->GetNextBox(&child); count++; } } else { - mDebugChild = nsnull; } - return PR_FALSE; -} + mDebugChild = nsnull; -NS_IMETHODIMP -nsBoxFrame::GetCursor(nsIPresContext* aPresContext, - nsPoint& aPoint, - PRInt32& aCursor) -{ - nsPoint newPoint; - mInner->TranslateEventCoords(aPresContext, aPoint, newPoint); - - /* - nsCOMPtr content; - mInner->GetContentOf(this, getter_AddRefs(content)); - - nsAutoString id; - content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, id); - char idValue[100]; - id.ToCString(idValue,100); -*/ - - /// printf("----------Box id = %s-----------\n", idValue); - // printf("x=%d, r.x=%d r.x + r.width=%d\n",newPoint.x, or.x, or.x + or.width); - // printf("y=%d, r.y=%d r.y + r.height=%d\n",newPoint.y, or.y, or.y + or.height); - - //aCursor = NS_STYLE_CURSOR_POINTER; - - - // if we are in debug and we are in the debug area - // return our own cursor and dump the debug information. - if (mState & NS_STATE_CURRENTLY_IN_DEBUG) - { - if (nsBoxDebug::gInstance->DisplayDebugInfoFor(aPresContext, this, newPoint, aCursor)) - return NS_OK; - } - - return nsHTMLContainerFrame::GetCursor(aPresContext, aPoint, aCursor); -} - -//XXX the event come's in in view relative coords, but really should -//be in frame relative coords by the time it hits our frame. - -// Translate an point that is relative to our view (or a containing -// view) into a localized pixel coordinate that is relative to the -// content area of this frame (inside the border+padding). -void -nsBoxFrameInner::TranslateEventCoords(nsIPresContext* aPresContext, - const nsPoint& aPoint, - nsPoint& aResult) -{ - nscoord x = aPoint.x; - nscoord y = aPoint.y; - - // If we have a view then the event coordinates are already relative - // to this frame; otherwise we have to adjust the coordinates - // appropriately. - nsIView* view; - mOuter->GetView(aPresContext, &view); - if (nsnull == view) { - nsPoint offset; - mOuter->GetOffsetFromView(aPresContext, offset, &view); - if (nsnull != view) { - x -= offset.x; - y -= offset.y; - } - } - - /* - const nsStyleSpacing* spacing; - nsresult rv = mOuter->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - nsMargin m(0,0,0,0); - spacing->GetBorderPadding(m); - - // Subtract out border and padding here so that the coordinates are - // now relative to the content area of this frame. - x -= m.left + m.right; - y -= m.top + m.bottom; -*/ - - aResult.x = x; - aResult.y = y; - -} - - -nsresult -nsBoxFrameInner::GetContentOf(nsIFrame* aFrame, nsIContent** aContent) -{ - // If we don't have a content node find a parent that does. - while(aFrame != nsnull) { - aFrame->GetContent(aContent); - if (*aContent != nsnull) - return NS_OK; - - aFrame->GetParent(&aFrame); - } - - NS_ERROR("Can't find a parent with a content node"); - return NS_OK; -} - -void -nsBoxFrameInner::SanityCheck() -{ -#ifdef TEST_SANITY - mInfoList->SanityCheck(mOuter->mFrames); -#endif -} - -void* -nsInfoListImpl::operator new(size_t sz, nsIPresShell* aPresShell) -{ - return nsBoxFrameInner::Allocate(sz,aPresShell); -} - -void -nsInfoListImpl::Recycle(nsIPresShell* aShell) -{ - // recycle all out box infos - Clear(aShell); - - delete this; - nsBoxFrameInner::RecycleFreedMemory(aShell, this); -} - -// Overridden to prevent the global delete from being called, since the memory -// came out of an nsIArena instead of the global delete operator's heap. -void -nsInfoListImpl::operator delete(void* aPtr, size_t sz) -{ - nsBoxFrameInner::Free(aPtr, sz); -} - -nsInfoListImpl::nsInfoListImpl():mFirst(nsnull),mLast(nsnull),mCount(0) -{ - -} - -nsInfoListImpl::~nsInfoListImpl() -{ + return NS_OK; } nsresult -nsInfoListImpl::SetDebug(nsIPresContext* aPresContext, PRBool aDebug) +nsBoxFrameInner::GetFrameSizeWithMargin(nsIBox* aBox, nsSize& aSize) { - nsCalculatedBoxInfo* info = GetFirst(); - while (info) - { - nsIBox* ibox = nsnull; - if (NS_SUCCEEDED(info->frame->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) { - ibox->SetDebug(aPresContext, aDebug); - } - - // make sure we recalculate our children's sizes - info->mFlags |= NS_FRAME_BOX_NEEDS_RECALC; - - info = info->next; - } - - - return NS_OK; -} - - -nsCalculatedBoxInfo* -nsInfoListImpl::GetFirst() -{ - return mFirst; -} - -nsCalculatedBoxInfo* -nsInfoListImpl::GetLast() -{ - return mLast; -} - -void -nsInfoListImpl::Clear(nsIPresShell* aShell) -{ - nsCalculatedBoxInfo* info = mFirst; - while(info) { - nsCalculatedBoxInfo* it = info; - info = info->next; - it->Recycle(aShell); - } - mFirst = nsnull; - mLast = nsnull; - mCount = 0; -} - -PRInt32 -nsInfoListImpl::GetCount() -{ - return mCount; -} - -PRInt32 -nsInfoListImpl::CreateInfosFor(nsIPresShell* aPresShell, nsIFrame* aList, nsCalculatedBoxInfo*& first, nsCalculatedBoxInfo*& last) -{ - PRInt32 count = 0; - if (aList) { - first = new (aPresShell) nsCalculatedBoxInfoImpl(aList); - count++; - last = first; - aList->GetNextSibling(&aList); - while(aList) { - last->next = new (aPresShell) nsCalculatedBoxInfoImpl(aList); - count++; - aList->GetNextSibling(&aList); - last = last->next; - } - } - - return count; -} - -nsCalculatedBoxInfo* -nsInfoListImpl::GetPrevious(nsIFrame* aFrame) -{ - if (aFrame == nsnull) - return nsnull; - - // find the frame to remove - nsCalculatedBoxInfo* info = mFirst; - nsCalculatedBoxInfo* prev = nsnull; - while (info) - { - if (info->frame == aFrame) { - return prev; - } - - prev = info; - info = info->next; - } - - return nsnull; -} - -nsCalculatedBoxInfo* -nsInfoListImpl::GetInfo(nsIFrame* aFrame) -{ - if (aFrame == nsnull) - return nsnull; - - // find the frame to remove - nsCalculatedBoxInfo* info = mFirst; - while (info) - { - if (info->frame == aFrame) { - return info; - } - - info = info->next; - } - - return nsnull; -} - -void -nsInfoListImpl::Remove(nsIPresShell* aShell, nsIFrame* aFrame) -{ - // get the info before the frame - nsCalculatedBoxInfo* prevInfo = GetPrevious(aFrame); - RemoveAfter(aShell, prevInfo); -} - -void -nsInfoListImpl::Insert(nsIPresShell* aShell, nsIFrame* aPrevFrame, nsIFrame* aFrameList) -{ - nsCalculatedBoxInfo* prevInfo = GetInfo(aPrevFrame); - - // find the frame before this one - // if no previous frame then we are inserting in front - if (prevInfo == nsnull) { - // prepend them - Prepend(aShell, aFrameList); - } else { - // insert insert after previous info - InsertAfter(aShell, prevInfo, aFrameList); - } -} - -void -nsInfoListImpl::RemoveAfter(nsIPresShell* aPresShell, nsCalculatedBoxInfo* aPrevious) -{ - nsCalculatedBoxInfo* toDelete = nsnull; - - if (aPrevious == nsnull) - { - NS_ASSERTION(mFirst,"Can't find first child"); - toDelete = mFirst; - if (mLast == mFirst) - mLast = mFirst->next; - mFirst = mFirst->next; - } else { - toDelete = aPrevious->next; - NS_ASSERTION(toDelete,"Can't find child to delete"); - aPrevious->next = toDelete->next; - if (mLast == toDelete) - mLast = aPrevious; - } - - toDelete->Recycle(aPresShell); - mCount--; -} - -void -nsInfoListImpl::Prepend(nsIPresShell* aPresShell, nsIFrame* aList) -{ - nsCalculatedBoxInfo* first; - nsCalculatedBoxInfo* last; - mCount += CreateInfosFor(aPresShell, aList, first, last); - if (!mFirst) - mFirst = mLast = first; - else { - last->next = mFirst; - mFirst = first; - } -} - -void -nsInfoListImpl::Append(nsIPresShell* aPresShell, nsIFrame* aList) -{ - nsCalculatedBoxInfo* first; - nsCalculatedBoxInfo* last; - mCount += CreateInfosFor(aPresShell, aList, first, last); - if (!mFirst) - mFirst = first; - else - mLast->next = first; - - mLast = last; -} - -void -nsInfoListImpl::InsertAfter(nsIPresShell* aPresShell, nsCalculatedBoxInfo* aPrev, nsIFrame* aList) -{ - nsCalculatedBoxInfo* first; - nsCalculatedBoxInfo* last; - mCount += CreateInfosFor(aPresShell, aList, first, last); - last->next = aPrev->next; - aPrev->next = first; - if (aPrev == mLast) - mLast = last; -} - -void -nsInfoListImpl::Init(nsIPresShell* aPresShell, nsIFrame* aList) -{ - Clear(aPresShell); - mCount += CreateInfosFor(aPresShell, aList, mFirst, mLast); -} - -void -nsInfoListImpl::SanityCheck(nsFrameList& aFrameList) -{ - // make sure the length match - PRInt32 length = aFrameList.GetLength(); - NS_ASSERTION(length == mCount,"nsBox::ERROR!! Box info list count does not match frame count!!"); - - // make sure last makes sense - NS_ASSERTION(mLast == nsnull || mLast->next == nsnull,"nsBox::ERROR!! The last child is not really the last!!!"); - nsIFrame* child = aFrameList.FirstChild(); - nsCalculatedBoxInfo* info = mFirst; - PRInt32 count = 0; - while(child) - { - NS_ASSERTION(count <= mCount,"too many children!!!"); - NS_ASSERTION(info->frame == child,"nsBox::ERROR!! box info list and child info lists don't match!!!"); - info = info->next; - child->GetNextSibling(&child); - count++; - } -} - - -// ---- box info ------ - -nsBoxInfo::nsBoxInfo():prefSize(0,0), minSize(0,0), maxSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE), flex(0) -{ -} - -void -nsBoxInfo::Clear() -{ - prefSize.width = 0; - prefSize.height = 0; - - minSize.width = 0; - minSize.height = 0; - - ascent = 0; - - flex = 0; - - maxSize.width = NS_INTRINSICSIZE; - maxSize.height = NS_INTRINSICSIZE; -} - -nsBoxInfo::~nsBoxInfo() -{ -} - - - - - - - - - - + nsRect rect(0,0,0,0); + aBox->GetBounds(rect); + nsMargin margin(0,0,0,0); + aBox->GetMargin(margin); + rect.Inflate(margin); + aSize.width = rect.width; + aSize.height = rect.height; + return NS_OK; +} \ No newline at end of file diff --git a/mozilla/layout/xul/base/src/nsBoxFrame.h b/mozilla/layout/xul/base/src/nsBoxFrame.h index c9a0a74b57b..2ac5a599c03 100644 --- a/mozilla/layout/xul/base/src/nsBoxFrame.h +++ b/mozilla/layout/xul/base/src/nsBoxFrame.h @@ -33,8 +33,8 @@ #include "nsCOMPtr.h" #include "nsHTMLContainerFrame.h" -#include "nsIBox.h" -#include "nsISpaceManager.h" +#include "nsContainerBox.h" +class nsBoxLayoutState; class nsBoxFrameInner; class nsBoxDebugInner; @@ -47,23 +47,6 @@ class nsHTMLInfo; #define NS_FRAME_BOX_NEEDS_RECALC 0x0004 #define NS_FRAME_IS_BOX 0x0008 -class nsCalculatedBoxInfo : public nsBoxInfo { -public: - nsSize calculatedSize; - PRInt16 mFlags; - nsCalculatedBoxInfo* next; - nsIFrame* frame; - - virtual void Recycle(nsIPresShell* aShell); -}; - -class nsInfoList -{ -public: - virtual nsCalculatedBoxInfo* GetFirst()=0; - virtual nsCalculatedBoxInfo* GetLast()=0; - virtual PRInt32 GetCount()=0; -}; // flags from box #define NS_STATE_IS_HORIZONTAL 0x00400000 @@ -72,8 +55,9 @@ public: #define NS_STATE_CURRENTLY_IN_DEBUG 0x02000000 #define NS_STATE_SET_TO_DEBUG 0x04000000 #define NS_STATE_DEBUG_WAS_SET 0x08000000 +#define NS_STATE_IS_COLLAPSED 0x10000000 -class nsBoxFrame : public nsHTMLContainerFrame, public nsIBox +class nsBoxFrame : public nsHTMLContainerFrame, public nsContainerBox { public: @@ -81,21 +65,40 @@ public: // gets the rect inside our border and debug border. If you wish to paint inside a box // call this method to get the rect so you don't draw on the debug border or outer border. - virtual void GetInnerRect(nsRect& aInner); + // ------ nsISupports -------- + NS_DECL_ISUPPORTS + + // ------ nsIBox ------------- + + NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetFlex(nsBoxLayoutState& aBoxLayoutState, nscoord& aFlex); + NS_IMETHOD GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent); + NS_IMETHOD SetDebug(nsBoxLayoutState& aBoxLayoutState, PRBool aDebug); + NS_IMETHOD GetFrame(nsIFrame** aFrame); + NS_IMETHOD GetVAlign(Valignment& aAlign); + NS_IMETHOD GetHAlign(Halignment& aAlign); + NS_IMETHOD NeedsRecalc(); + NS_IMETHOD GetInset(nsMargin& aInset); + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); + NS_IMETHOD GetDebug(PRBool& aDebug); + + // ----- child and sibling operations --- + + // ----- public methods ------- + NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, - const nsPoint& aPoint, - nsFramePaintLayer aWhichLayer, - nsIFrame** aFrame); + const nsPoint& aPoint, + nsFramePaintLayer aWhichLayer, + nsIFrame** aFrame); NS_IMETHOD GetCursor(nsIPresContext* aPresContext, nsPoint& aPoint, PRInt32& aCursor); - NS_IMETHOD DidReflow(nsIPresContext* aPresContext, - nsDidReflowStatus aStatus); - NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild); NS_IMETHOD Init(nsIPresContext* aPresContext, @@ -146,37 +149,22 @@ public: NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD DidReflow(nsIPresContext* aPresContext, + nsDidReflowStatus aStatus); + virtual PRBool IsHorizontal() const; - NS_IMETHOD_(nsrefcnt) AddRef(void); - NS_IMETHOD_(nsrefcnt) Release(void); - virtual ~nsBoxFrame(); - virtual void GetChildBoxInfo(PRInt32 aIndex, nsBoxInfo& aSize); + virtual nsresult GetContentOf(nsIContent** aContent); - // nsIBox methods - NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); - NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); - NS_IMETHOD InvalidateCache(nsIFrame* aChild); - NS_IMETHOD SetDebug(nsIPresContext* aPresContext, PRBool aDebug); - - enum Halignment { - hAlign_Left, - hAlign_Right, - hAlign_Center - }; - - enum Valignment { - vAlign_Top, - vAlign_Middle, - vAlign_BaseLine, - vAlign_Bottom - }; protected: nsBoxFrame(nsIPresShell* aPresShell, PRBool aIsRoot = PR_FALSE); + virtual void PropagateDebug(nsBoxLayoutState& aState); + + // Paint one child frame virtual void PaintChild(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -189,36 +177,14 @@ protected: const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer); - - virtual void GetRedefinedMinPrefMax(nsIPresContext* aPresContext, nsIFrame* aFrame, nsCalculatedBoxInfo& aSize); - virtual nsresult GetChildBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame* aFrame, nsCalculatedBoxInfo& aSize); - virtual void ComputeChildsNextPosition( nsCalculatedBoxInfo* aInfo, nscoord& aCurX, nscoord& aCurY, nscoord& aNextX, nscoord& aNextY, const nsSize& aCurrentChildSize, const nsRect& aBoxRect, nscoord aMaxAscent); - virtual nsresult PlaceChildren(nsIPresContext* aPresContext, nsRect& boxRect); - virtual void ChildResized(nsIFrame* aFrame, nsHTMLReflowMetrics& aDesiredSize, nsRect& aRect, nscoord& aMaxAscent, nsCalculatedBoxInfo& aInfo, PRBool*& aResized, PRInt32 aInfoCount, nscoord& aChangedIndex, PRBool& aFinished, nscoord aIndex, nsString& aReason); - - virtual void LayoutChildrenInRect(nsRect& aSize, nscoord& aMaxAscent); - virtual void AddChildSize(nsBoxInfo& aInfo, nsBoxInfo& aChildInfo); - virtual void BoundsCheck(const nsBoxInfo& aBoxInfo, nsRect& aRect); - virtual void InvalidateChildren(); - virtual void AddSize(const nsSize& a, nsSize& b, PRBool largest); - virtual PRIntn GetSkipSides() const { return 0; } - virtual void GetInset(nsMargin& margin); - virtual void CollapseChild(nsIPresContext* aPresContext, nsIFrame* frame, PRBool hide); - - nsresult GenerateDirtyReflowCommand(nsIPresContext* aPresContext, - nsIPresShell& aPresShell); - - virtual PRBool GetInitialOrientation(PRBool& aIsHorizontal); virtual PRBool GetInitialHAlignment(Halignment& aHalign); virtual PRBool GetInitialVAlignment(Valignment& aValign); virtual PRBool GetInitialAutoStretch(PRBool& aStretch); - virtual PRBool GetDefaultFlex(PRInt32& aFlex); - - virtual nsInfoList* GetInfoList(); + NS_IMETHOD Destroy(nsIPresContext* aPresContext); private: diff --git a/mozilla/layout/xul/base/src/nsBoxLayoutState.cpp b/mozilla/layout/xul/base/src/nsBoxLayoutState.cpp new file mode 100644 index 00000000000..adf7704e58b --- /dev/null +++ b/mozilla/layout/xul/base/src/nsBoxLayoutState.cpp @@ -0,0 +1,381 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +// +// Eric Vaughan +// Netscape Communications +// +// See documentation in associated header file +// + +#include "nsBoxLayoutState.h" +#include "nsIReflowCommand.h" +#include "nsBoxFrame.h" +#include "nsIStyleContext.h" +#include "nsHTMLAtoms.h" +#include "nsXULAtoms.h" +#include "nsIContent.h" +#include "nsINameSpaceManager.h" +#include "nsIPresContext.h" + +nsBoxLayoutState::nsBoxLayoutState(nsIPresContext* aPresContext):mPresContext(aPresContext), mReflowState(nsnull) +{ +} + +nsBoxLayoutState::nsBoxLayoutState(const nsBoxLayoutState& aState) +{ + mPresContext = aState.mPresContext; + mType = aState.mType; + mReflowState = aState.mReflowState; +} + +nsBoxLayoutState::nsBoxLayoutState(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState):mReflowState(&aReflowState),mPresContext(aPresContext),mType(Dirty) +{ +} + +PRBool +nsBoxLayoutState::HandleReflow(nsIBox* aRootBox, PRBool aCoelesce) +{ + switch(mReflowState->reason) + { + case eReflowReason_Incremental: + { + nsIReflowCommand::ReflowType type; + mReflowState->reflowCommand->GetType(type); + + // atempt to coelesce style changes and reflows + // see if the target is a box + /* + PRBool isAdaptor = PR_FALSE; + nsIBox* box = GetTargetBox(mReflowState->reflowCommand, isAdaptor); + // if it is mark it dirty. Generating a dirty reflow targeted at us unless on is already + // done. + if (box && box != aRootBox) { + if (type == nsIReflowCommand::StyleChanged) { + // could be a visiblity change need to dirty + // parent so it gets redrawn. + nsIBox* parent; + box->GetParentBox(&parent); + parent->MarkDirty(*this); + DirtyAllChildren(*this, box); + } else + box->MarkDirty(*this); + return PR_TRUE; + } + */ + + // ok if the target was not a box. Then unwind it down + if (UnWind(mReflowState->reflowCommand, aRootBox, aCoelesce)) { + mType = Dirty; + return PR_TRUE; + } + + } // fall into dirty + + case eReflowReason_Dirty: + mType = Dirty; + break; + + // if the a resize reflow then it doesn't need to be reflowed. Only if the size is different + // from the new size would we actually do a reflow + case eReflowReason_Resize: + mType = Resize; + break; + + // if its an initial reflow we must place the child. + // otherwise we might think it was already placed when it wasn't + case eReflowReason_Initial: + mType = Initial; + break; + + default: + mType = Dirty; + } + + return PR_FALSE; +} + + +PRBool +nsBoxLayoutState::UnWind(nsIReflowCommand* aCommand, nsIBox* aBox, PRBool aCoelesce) +{ + // if incremental unwindow the chain + nsIFrame* incrementalChild = nsnull; + nsIBox* lastBox = nsnull; + nsIFrame* target = nsnull; + aCommand->GetTarget(target); + nsIReflowCommand::ReflowType type; + mReflowState->reflowCommand->GetType(type); + + while(1) + { + aCommand->GetNext(incrementalChild, PR_FALSE); + if (incrementalChild == nsnull) + return PR_FALSE; + + // get the box for the given incrementalChild. If adaptor is true then + // it is some wrapped HTML frame. + PRBool isAdaptor = PR_FALSE; + nsIBox* ibox = GetBoxForFrame(incrementalChild, isAdaptor); + if (ibox) { + nsFrameState state; + incrementalChild->GetFrameState(&state); + state &= ~NS_FRAME_HAS_DIRTY_CHILDREN; + incrementalChild->SetFrameState(state); + + // ok we got a box is it the target? + if (incrementalChild == target) { + + if (!aCoelesce) { + nsFrameState state; + nsIFrame* frame; + aBox->GetFrame(&frame); + frame->GetFrameState(&state); + state |= NS_FRAME_HAS_DIRTY_CHILDREN; + frame->SetFrameState(state); + } + // the target is a box? + // mark it dirty generating a new reflow command targeted + // at us and coelesce out this one. + ibox->MarkDirty(*this); + + if (type == nsIReflowCommand::StyleChanged) { + // could be a visiblity change need to dirty + // parent so it gets redrawn. + nsIBox* parent; + ibox->GetParentBox(&parent); + parent->MarkDirty(*this); + //DirtyAllChildren(*this, box); + } + + // yes we coelesed + return aCoelesce ? PR_TRUE : PR_FALSE; + } + + // was the child html? + if (isAdaptor) { + // the target is deep inside html we will have to honor this one. + // mark us as dirty so we don't post + // a dirty reflow + nsFrameState state; + nsIFrame* frame; + aBox->GetFrame(&frame); + frame->GetFrameState(&state); + state |= NS_FRAME_HAS_DIRTY_CHILDREN; + frame->SetFrameState(state); + + incrementalChild->GetFrameState(&state); + state &= ~NS_FRAME_IS_DIRTY; + incrementalChild->SetFrameState(state); + + // mark the adaptor dirty + ibox->MarkDirty(*this); + + // we are done and we did not coelesce + return PR_FALSE; + } + + } else { + NS_ERROR("This should not happen! We should always get a box"); + break; + } + + aCommand->GetNext(incrementalChild); + } + + return PR_FALSE; +} + +/* +void +nsBoxLayoutState::UnWind(nsIReflowCommand* aCommand, nsIBox* aBox) +{ + + nsFrameState state; + nsIFrame* frame; + aBox->GetFrame(&frame); + frame->GetFrameState(&state); + state |= NS_FRAME_HAS_DIRTY_CHILDREN; + frame->SetFrameState(state); + + // if incremental unwindow the chain + nsIFrame* incrementalChild = nsnull; + + while(1) + { + aCommand->GetNext(incrementalChild, PR_FALSE); + if (incrementalChild == nsnull) + break; + + nsIFrame* target = nsnull; + aCommand->GetTarget(target); + + PRBool isAdaptor = PR_FALSE; + nsIBox* ibox = GetBoxForFrame(incrementalChild, isAdaptor); + if (ibox) { + if (incrementalChild == target || isAdaptor) { + ibox->MarkDirty(*this); + if (isAdaptor) + break; + } else + ibox->MarkDirtyChildren(*this); + + } else { + break; + } + + aCommand->GetNext(incrementalChild); + } + +} +*/ + +nsIBox* +nsBoxLayoutState::GetTargetBox(nsIReflowCommand* mCommand, PRBool& aIsAdaptor) +{ + nsIFrame* target = nsnull; + mReflowState->reflowCommand->GetTarget(target); + return GetBoxForFrame(target, aIsAdaptor); +} + +nsIBox* +nsBoxLayoutState::GetBoxForFrame(nsIFrame* aFrame, PRBool& aIsAdaptor) +{ + if (aFrame == nsnull) + return nsnull; + + nsIBox* ibox = nsnull; + if (NS_FAILED(aFrame->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox))) { + aIsAdaptor = PR_TRUE; + + // if we hit a non box. Find the box in out last container + // and clear its cache. + nsIFrame* parent = nsnull; + aFrame->GetParent(&parent); + nsIBox* parentBox = nsnull; + if (NS_FAILED(parent->QueryInterface(NS_GET_IID(nsIBox), (void**)&parentBox))) + return nsnull; + + if (parentBox) { + nsIBox* start = nsnull; + parentBox->GetChildBox(&start); + while (start) { + nsIFrame* frame = nsnull; + start->GetFrame(&frame); + if (frame == aFrame) { + ibox = start; + break; + } + + start->GetNextBox(&start); + } + } + } + + return ibox; +} + +void +nsBoxLayoutState::DirtyAllChildren(nsBoxLayoutState& aState, nsIBox* aBox) +{ + aBox->MarkDirty(aState); + + nsIBox* first = nsnull; + aBox->GetChildBox(&first); + if (first) + aBox->MarkDirtyChildren(aState); + + while(first) + { + DirtyAllChildren(aState, first); + first->GetNextBox(&first); + } +} + +void* +nsBoxLayoutState::Allocate(size_t sz, nsIPresShell* aPresShell) +{ + // Check the recycle list first. + void* result = nsnull; + aPresShell->AllocateFrame(sz, &result); + + if (result) { + nsCRT::zero(result, sz); + } + + return result; +} + +// Overridden to prevent the global delete from being called, since the memory +// came out of an nsIArena instead of the global delete operator's heap. +void +nsBoxLayoutState::Free(void* aPtr, size_t sz) +{ + // Don't let the memory be freed, since it will be recycled + // instead. Don't call the global operator delete. + + // Stash the size of the object in the first four bytes of the + // freed up memory. The Destroy method can then use this information + // to recycle the object. + size_t* szPtr = (size_t*)aPtr; + *szPtr = sz; +} + +void +nsBoxLayoutState::RecycleFreedMemory(nsIPresShell* aShell, void* aMem) +{ + size_t* sz = (size_t*)aMem; + aShell->FreeFrame(*sz, aMem); +} + +nsresult +nsBoxLayoutState::GetPresShell(nsIPresShell** aShell) +{ + return mPresContext->GetShell(aShell); +} + +nsresult +nsBoxLayoutState::PushStackMemory() +{ + nsCOMPtr shell; + mPresContext->GetShell(getter_AddRefs(shell)); + return shell->PushStackMemory(); +} + +nsresult +nsBoxLayoutState::PopStackMemory() +{ + nsCOMPtr shell; + mPresContext->GetShell(getter_AddRefs(shell)); + + return shell->PopStackMemory(); +} + +nsresult +nsBoxLayoutState::AllocateStackMemory(size_t aSize, void** aResult) +{ + nsCOMPtr shell; + mPresContext->GetShell(getter_AddRefs(shell)); + + return shell->AllocateStackMemory(aSize, aResult); +} + \ No newline at end of file diff --git a/mozilla/layout/xul/base/src/nsBoxLayoutState.h b/mozilla/layout/xul/base/src/nsBoxLayoutState.h new file mode 100644 index 00000000000..8a0c5844223 --- /dev/null +++ b/mozilla/layout/xul/base/src/nsBoxLayoutState.h @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +/** + + Author: + Eric D Vaughan + +**/ + +#ifndef nsBoxLayoutState_h___ +#define nsBoxLayoutState_h___ + +#include "nsIFrame.h" +#include "nsCOMPtr.h" +#include "nsIPresContext.h" +#include "nsIPresShell.h" + +class nsReflowState; +class nsCalculatedBoxInfo; +struct nsHTMLReflowMetrics; +class nsString; +class nsIBox; +class nsIReflowCommand; + +class nsBoxLayoutState +{ +public: + enum eBoxLayoutReason { + Dirty, + Resize, + Initial + }; + + nsBoxLayoutState(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState); + nsBoxLayoutState(nsIPresContext* aPresContext); + nsBoxLayoutState(const nsBoxLayoutState& aState); + + virtual PRBool HandleReflow(nsIBox* aRootBox, PRBool aCoalesce); + + virtual nsIPresContext* GetPresContext() { return mPresContext; } + virtual nsresult GetPresShell(nsIPresShell** aShell); + + virtual eBoxLayoutReason GetLayoutReason() { return mType; } + virtual void SetLayoutReason(eBoxLayoutReason aReason) { mType = aReason; } + virtual const nsHTMLReflowState* GetReflowState() { return mReflowState; } + + static void* Allocate(size_t sz, nsIPresShell* aPresShell); + static void Free(void* aPtr, size_t sz); + static void RecycleFreedMemory(nsIPresShell* aPresShell, void* mem); + + nsresult PushStackMemory(); + nsresult PopStackMemory(); + nsresult AllocateStackMemory(size_t aSize, void** aResult); + +private: + void DirtyAllChildren(nsBoxLayoutState& aState, nsIBox* aBox); + PRBool UnWind(nsIReflowCommand* aCommand, nsIBox* aRootBox, PRBool aCoalesce); + nsIBox* GetTargetBox(nsIReflowCommand* mCommand, PRBool& aIsAdaptor); + nsIBox* GetBoxForFrame(nsIFrame* aFrame, PRBool& aIsAdaptor); + + nsIPresContext* mPresContext; + const nsHTMLReflowState* mReflowState; + eBoxLayoutReason mType; +}; + +#endif + diff --git a/mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.cpp b/mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.cpp new file mode 100644 index 00000000000..d4526fb8749 --- /dev/null +++ b/mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.cpp @@ -0,0 +1,806 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +// +// Eric Vaughan +// Netscape Communications +// +// See documentation in associated header file +// + +#include "nsBoxLayoutState.h" +#include "nsBoxFrame.h" +#include "nsIStyleContext.h" +#include "nsIPresContext.h" +#include "nsCOMPtr.h" +#include "nsHTMLIIDs.h" +#include "nsUnitConversion.h" +#include "nsINameSpaceManager.h" +#include "nsHTMLAtoms.h" +#include "nsXULAtoms.h" +#include "nsIReflowCommand.h" +#include "nsIContent.h" +#include "nsSpaceManager.h" +#include "nsHTMLParts.h" +#include "nsIViewManager.h" +#include "nsIView.h" +#include "nsIPresShell.h" +#include "nsGenericHTMLElement.h" +#include "nsFrameNavigator.h" +#include "nsCSSRendering.h" +#include "nsISelfScrollingFrame.h" +#include "nsIPref.h" +#include "nsIServiceManager.h" +#include "nsBoxToBlockAdaptor.h" +#include "nsILineIterator.h" +#include "nsIFontMetrics.h" + +nsBoxToBlockAdaptor::nsBoxToBlockAdaptor(nsIPresShell* aPresShell, nsIFrame* aFrame):nsBox(aPresShell) +{ + NS_INIT_ISUPPORTS(); + + mFrame = aFrame; + mSpaceManager = nsnull; + mWasCollapsed = PR_FALSE; + NeedsRecalc(); +} + +void* +nsBoxToBlockAdaptor::operator new(size_t sz, nsIPresShell* aPresShell) +{ + return nsBoxLayoutState::Allocate(sz,aPresShell); +} + +NS_IMETHODIMP +nsBoxToBlockAdaptor::Recycle(nsIPresShell* aPresShell) +{ + delete this; + nsBoxLayoutState::RecycleFreedMemory(aPresShell, this); + return NS_OK; +} + +NS_IMETHODIMP +nsBoxToBlockAdaptor::GetFrame(nsIFrame** aFrame) +{ + *aFrame = mFrame; + return NS_OK; +} + +// Overridden to prevent the global delete from being called, since the memory +// came out of an nsIArena instead of the global delete operator's heap. +void +nsBoxToBlockAdaptor::operator delete(void* aPtr, size_t sz) +{ + nsBoxLayoutState::Free(aPtr, sz); +} + +nsBoxToBlockAdaptor::~nsBoxToBlockAdaptor() +{ + if (mSpaceManager) + NS_RELEASE(mSpaceManager); +} + + +NS_IMETHODIMP +nsBoxToBlockAdaptor::NeedsRecalc() +{ + nsIBox* parent; + GetParentBox(&parent); + nsIFrame* frame; + if (parent) { + parent->GetFrame(&frame); + nsFrameState frameState = 0; + frame->GetFrameState(&frameState); + } + + mMinWidth = -1; + mPrefNeedsRecalc = PR_TRUE; + SizeNeedsRecalc(mMinSize); + SizeNeedsRecalc(mMaxSize); + CoordNeedsRecalc(mFlex); + CoordNeedsRecalc(mAscent); + return NS_OK; +} + +NS_IMETHODIMP +nsBoxToBlockAdaptor::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + + if (!mPrefNeedsRecalc) { + aSize = mPrefSize; + return NS_OK; + } + + nsresult rv = NS_OK; + + // see if anything is defined in css. If pref size is competely + // defined in css we are golden. We do nothing. But is its not + // in css we will have to reflow the child. + nsSize pref(0,0); + + PRBool completelyRedefined = nsIBox::AddCSSPrefSize(aBoxLayoutState, this, mPrefSize); + + if (!completelyRedefined) { + const nsHTMLReflowState* reflowState = aBoxLayoutState.GetReflowState(); + if (reflowState) { + nsIPresContext* presContext = aBoxLayoutState.GetPresContext(); + nsReflowStatus status = NS_FRAME_COMPLETE; + nsHTMLReflowMetrics desiredSize(nsnull); + + PRBool isDirty = PR_FALSE; + IsDirty(isDirty); + + //nsRect oldRect; + // mFrame->GetRect(oldRect); + + rv = Reflow(presContext, + desiredSize, + *reflowState, + status, + 0, + 0, + NS_INTRINSICSIZE, + NS_INTRINSICSIZE, + PR_FALSE); + + nsFrameState frameState = 0; + mFrame->GetFrameState(&frameState); + frameState |= NS_FRAME_IS_DIRTY; + mFrame->SetFrameState(frameState); + //mFrame->SetRect(presContext, oldRect); + + mPrefSize.width = desiredSize.width; + mPrefSize.height = desiredSize.height; + mAscent = desiredSize.ascent; + + nsMargin m(0,0,0,0); + GetInset(m); + mAscent += m.top; + + // ok the sizes might be bigger than our css preferred size. + // check it. + AddInset(mPrefSize); + + nsIBox::AddCSSPrefSize(aBoxLayoutState, this, mPrefSize); + mPrefNeedsRecalc = PR_FALSE; + } + } + + aSize = mPrefSize; + + return rv; +} + +NS_IMETHODIMP +nsBoxToBlockAdaptor::GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + if (!DoesNeedRecalc(mMinSize)) { + aSize = mMinSize; + return NS_OK; + } + + mMinSize.width = 0; + mMinSize.height = 0; + + AddBorderAndPadding(mMinSize); + AddInset(mMinSize); + + if (mMinWidth != -1) + mMinSize.width = mMinWidth; + + nsIBox::AddCSSMinSize(aBoxLayoutState, this, mMinSize); + + aSize = mMinSize; + + return NS_OK; +} + +NS_IMETHODIMP +nsBoxToBlockAdaptor::GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + if (!DoesNeedRecalc(mMaxSize)) { + aSize = mMaxSize; + return NS_OK; + } + + nsresult rv = nsBox::GetMaxSize(aBoxLayoutState, mMaxSize); + aSize = mMaxSize; + + return rv; +} + +NS_IMETHODIMP +nsBoxToBlockAdaptor::GetFlex(nsBoxLayoutState& aBoxLayoutState, nscoord& aFlex) +{ + if (!DoesNeedRecalc(mFlex)) { + aFlex = mFlex; + return NS_OK; + } + + mFlex = 0; + nsBox::GetFlex(aBoxLayoutState, mFlex); + + aFlex = mFlex; + + return NS_OK; +} + +NS_IMETHODIMP +nsBoxToBlockAdaptor::GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent) +{ + if (!DoesNeedRecalc(mAscent)) { + aAscent = mAscent; + return NS_OK; + } + + nsSize size; + GetPrefSize(aBoxLayoutState, size); + + aAscent = mAscent; + + return NS_OK; +} + +NS_IMETHODIMP +nsBoxToBlockAdaptor::IsCollapsed(nsBoxLayoutState& aBoxLayoutState, PRBool& aCollapsed) +{ + return nsBox::IsCollapsed(aBoxLayoutState, aCollapsed); +} + +nsresult +nsBoxToBlockAdaptor::Layout(nsBoxLayoutState& aBoxLayoutState) +{ + nsRect ourRect(0,0,0,0); + GetBounds(ourRect); + + const nsHTMLReflowState* reflowState = aBoxLayoutState.GetReflowState(); + nsIPresContext* presContext = aBoxLayoutState.GetPresContext(); + nsReflowStatus status = NS_FRAME_COMPLETE; + nsHTMLReflowMetrics desiredSize(nsnull); + nsresult rv; + + if (reflowState) { + + // nsRect oldRect; + // mFrame->GetRect(oldRect); + + rv = Reflow(presContext, + desiredSize, + *reflowState, + status, + ourRect.x, + ourRect.y, + ourRect.width, + ourRect.height); + + mAscent = desiredSize.ascent; + + PRBool isCollapsed = PR_FALSE; + IsCollapsed(aBoxLayoutState, isCollapsed); + // if (!isCollapsed) { + mFrame->SizeTo(presContext, desiredSize.width, desiredSize.height); + // } else { + // mFrame->SetRect(presContext, oldRect); + // } + } + + SyncLayout(aBoxLayoutState); + + return rv; +} + +nsresult +nsBoxToBlockAdaptor::Reflow(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus, + nscoord aX, + nscoord aY, + nscoord aWidth, + nscoord aHeight, + PRBool aMoveFrame) +{ + + //printf("width=%d, height=%d\n", aWidth, aHeight); + + nsIBox* parent; + GetParentBox(&parent); + nsIFrame* frame; + parent->GetFrame(&frame); + nsFrameState frameState = 0; + frame->GetFrameState(&frameState); + + // if (frameState & NS_STATE_CURRENTLY_IN_DEBUG) + // printf("In debug\n"); + + if (mSpaceManager == nsnull) { + mSpaceManager = new nsSpaceManager(mFrame); + NS_ADDREF(mSpaceManager); + } + + // Modify the reflow state and set the space manager + nsHTMLReflowState& nonConstState = (nsHTMLReflowState&)aReflowState; + nonConstState.mSpaceManager = mSpaceManager; + + // Clear the spacemanager's regions. + mSpaceManager->ClearRegions(); + + + aStatus = NS_FRAME_COMPLETE; + PRBool needsReflow = PR_FALSE; + + // get our frame its size and the reflow state + + nsReflowReason reason = aReflowState.reason; + + nsFrameState childState; + mFrame->GetFrameState(&childState); + // childState |= NS_BLOCK_SPACE_MGR; + // mFrame->SetFrameState(childState); + + + if (childState & NS_FRAME_FIRST_REFLOW) { + if (reason != eReflowReason_Initial) + { + // if incremental then make sure we send a initial reflow first. + if (reason == eReflowReason_Incremental) { + nsHTMLReflowState state(aReflowState); + state.reason = eReflowReason_Initial; + state.reflowCommand = nsnull; + Reflow(aPresContext, aDesiredSize, state, aStatus, aX, aY, aWidth, aHeight, aMoveFrame); + } else { + // convert to initial if not incremental. + reason = eReflowReason_Initial; + } + + } + } else if (reason == eReflowReason_Initial) { + reason = eReflowReason_Resize; + } + + // handle or different types of reflow + switch(reason) + { + // if the child we are reflowing is the child we popped off the incremental + // reflow chain then we need to reflow it no matter what. + // if its not the child we got from the reflow chain then this child needs reflow + // because as a side effect of the incremental child changing aize andit needs to be resized. + // This will happen with a lot when a box that contains 2 children with different flexabilities + // if on child gets bigger the other is affected because it is proprotional to the first. + // so it might need to be resized. But we don't need to reflow it. If it is already the + // needed size then we will do nothing. + case eReflowReason_Incremental: { + + // if incremental see if the next child in the chain is the child. If so then + // we will just let it go down. If not then convert it to a dirty. It will get converted back when + // needed in the case just below this one. + nsIFrame* incrementalChild = nsnull; + aReflowState.reflowCommand->GetNext(incrementalChild, PR_FALSE); + if (incrementalChild == nsnull) + aReflowState.reflowCommand->GetTarget(incrementalChild); + + if (incrementalChild == mFrame) { + needsReflow = PR_TRUE; + aReflowState.reflowCommand->GetNext(incrementalChild); + break; + } + + // fall into dirty + } + + // if its dirty then see if the child we want to reflow is dirty. If it is then + // mark it as needing to be reflowed. + case eReflowReason_Dirty: { + // only frames that implement nsIBox seem to be able to handle a reason of Dirty. For everyone else + // send down a resize. + reason = eReflowReason_Resize; + + // get the frame state to see if it needs reflow + needsReflow = (childState & NS_FRAME_IS_DIRTY) || (childState & NS_FRAME_HAS_DIRTY_CHILDREN); + + } break; + + // if the a resize reflow then it doesn't need to be reflowed. Only if the size is different + // from the new size would we actually do a reflow + case eReflowReason_Resize: + needsReflow = PR_FALSE; + break; + + // if its an initial reflow we must place the child. + // otherwise we might think it was already placed when it wasn't + case eReflowReason_Initial: + aMoveFrame = PR_TRUE; + needsReflow = PR_TRUE; + break; + + default: + needsReflow = PR_TRUE; + + } + + //nsMargin margin(0,0,0,0); + // GetMargin(margin); + + // if we don't need a reflow then + // lets see if we are already that size. Yes? then don't even reflow. We are done. + if (!needsReflow) { + + if (aWidth != NS_INTRINSICSIZE && aHeight != NS_INTRINSICSIZE) { + + // if the new calculated size has a 0 width or a 0 height + if ((mLastSize.width == 0 || mLastSize.height == 0) && (aWidth == 0 || aHeight == 0)) { + needsReflow = PR_FALSE; + aDesiredSize.width = aWidth; + aDesiredSize.height = aHeight; + mFrame->SizeTo(aPresContext, aDesiredSize.width, aDesiredSize.height); + } else { + aDesiredSize.width = mLastSize.width; + aDesiredSize.height = mLastSize.height; + + // remove the margin. The rect of our child does not include it but our calculated size does. + nscoord calcWidth = aWidth; + nscoord calcHeight = aHeight; + // don't reflow if we are already the right size + if (mLastSize.width == calcWidth && mLastSize.height == calcHeight) + needsReflow = PR_FALSE; + else + needsReflow = PR_TRUE; + + } + } else { + // if the width or height are intrinsic alway reflow because + // we don't know what it should be. + needsReflow = PR_TRUE; + } + } + + // ok now reflow the child into the springs calculated space + if (needsReflow) { + + nsMargin border(0,0,0,0); + GetBorderAndPadding(border); + + + aDesiredSize.width = 0; + aDesiredSize.height = 0; + + nsSize size(aWidth, aHeight); + + // create a reflow state to tell our child to flow at the given size. + +#ifdef DEBUG_REFLOW + + char* reflowReasonString; + + switch(reason) + { + case eReflowReason_Initial: + reflowReasonString = "initial"; + break; + + case eReflowReason_Resize: + reflowReasonString = "resize"; + break; + case eReflowReason_Dirty: + reflowReasonString = "dirty"; + break; + case eReflowReason_StyleChange: + reflowReasonString = "stylechange"; + break; + case eReflowReason_Incremental: + reflowReasonString = "incremental"; + break; + default: + reflowReasonString = "unknown"; + break; + } + + AddIndents(); + nsFrame::ListTag(stdout, childFrame); + char ch[100]; + aReason.ToCString(ch,100); + + printf(" reason=%s %s",reflowReasonString,ch); +#endif + + + nsHTMLReflowState reflowState(aPresContext, aReflowState, mFrame, nsSize(size.width, NS_INTRINSICSIZE)); + reflowState.reason = reason; + + if (size.height != NS_INTRINSICSIZE) { + size.height -= (border.top + border.bottom); + NS_ASSERTION(size.height >= 0,"Error top bottom border too large"); + } + + if (size.width != NS_INTRINSICSIZE) { + size.width -= (border.left + border.right); + NS_ASSERTION(size.height >= 0,"Error left right border too large"); + } + + reflowState.mComputedWidth = size.width; + reflowState.mComputedHeight = size.height; +#ifdef DEBUG_REFLOW + printf(" Size=(%d,%d)\n",reflowState.mComputedWidth, reflowState.mComputedHeight); +#endif + + // place the child and reflow + mFrame->WillReflow(aPresContext); + + // if (aMoveFrame) { + // PlaceChild(aPresContext, mFrame, aX + margin.left, aY + margin.top); + // } + + mFrame->Reflow(aPresContext, aDesiredSize, reflowState, aStatus); + + NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); + + nsFrameState kidState; + mFrame->GetFrameState(&kidState); + + // printf("width: %d, height: %d\n", aDesiredSize.mCombinedArea.width, aDesiredSize.mCombinedArea.height); + + // XXX EDV hack to fix bug in block + //if (reflowState.reason != eReflowReason_Initial) { + + + /* + if (kidState & NS_FRAME_OUTSIDE_CHILDREN) { + printf("OutsideChildren width=%d, height=%d\n", aDesiredSize.mOverflowArea.width, aDesiredSize.mOverflowArea.height); + + if (aDesiredSize.mOverflowArea.width > aWidth) + { + reflowState.mComputedWidth = aDesiredSize.mOverflowArea.width - (border.left + border.right); + reflowState.availableWidth = reflowState.mComputedWidth; + //Reflow(aPresContext, aDesiredSize, aReflowState, aStatus, aX, aY, aDesiredSize.mOverflowArea.width, aHeight, aMoveFrame); + mFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + mFrame->WillReflow(aPresContext); + mFrame->Reflow(aPresContext, aDesiredSize, reflowState, aStatus); + mFrame->GetFrameState(&kidState); + if (kidState & NS_FRAME_OUTSIDE_CHILDREN) + aDesiredSize.height = aDesiredSize.mOverflowArea.height; + } else { + aDesiredSize.height = aDesiredSize.mOverflowArea.height; + } + } +*/ + + if (kidState & NS_FRAME_OUTSIDE_CHILDREN) { + //printf("OutsideChildren width=%d, height=%d\n", aDesiredSize.mOverflowArea.width, aDesiredSize.mOverflowArea.height); + aDesiredSize.width = aDesiredSize.mOverflowArea.width; + if (aDesiredSize.width <= aWidth) + aDesiredSize.height = aDesiredSize.mOverflowArea.height; + else { + if (aDesiredSize.width > aWidth) + { + reflowState.mComputedWidth = aDesiredSize.width - (border.left + border.right); + reflowState.availableWidth = reflowState.mComputedWidth; + reflowState.reason = eReflowReason_Resize; + reflowState.reflowCommand = nsnull; + mFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + mFrame->WillReflow(aPresContext); + mFrame->Reflow(aPresContext, aDesiredSize, reflowState, aStatus); + mFrame->GetFrameState(&kidState); + if (kidState & NS_FRAME_OUTSIDE_CHILDREN) + aDesiredSize.height = aDesiredSize.mOverflowArea.height; + } + } + } + + + // ok we need the max ascent of the items on the line. So to do this + // ask the block for its line iterator. Get the max ascent. + nsILineIterator* lines = nsnull; + if (NS_SUCCEEDED(mFrame->QueryInterface(NS_GET_IID(nsILineIterator), (void**)&lines)) && lines) + { + nsIFrame* firstFrame = nsnull; + PRInt32 framesOnLine; + nsRect lineBounds; + PRUint32 lineFlags; + lines->GetLine(0, &firstFrame, &framesOnLine, lineBounds, &lineFlags); + + if (firstFrame) { + nsRect rect(0,0,0,0); + firstFrame->GetRect(rect); + + const nsStyleFont* font; + firstFrame->GetStyleData(eStyleStruct_Font, + (const nsStyleStruct*&) font); + nsIRenderingContext& rc = *aReflowState.rendContext; + rc.SetFont(font->mFont); + nsIFontMetrics* fm; + nsresult rv = rc.GetFontMetrics(fm); + if (NS_SUCCEEDED(rv) && (nsnull != fm)) { + fm->GetMaxAscent(aDesiredSize.ascent); + NS_RELEASE(fm); + } + rv = NS_OK; + aDesiredSize.ascent += rect.y; + + /* + nsHTMLReflowMetrics d(nsnull); + nsHTMLReflowState lineReflowState(aPresContext, reflowState, firstFrame, nsSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE)); + lineReflowState.mComputedWidth = rect.width - (lineReflowState.mComputedBorderPadding.left + lineReflowState.mComputedBorderPadding.right); + lineReflowState.mComputedHeight = NS_INTRINSICSIZE; + reason = eReflowReason_Resize; + firstFrame->WillReflow(aPresContext); + firstFrame->Reflow(aPresContext, d, lineReflowState, aStatus); + aDesiredSize.ascent = d.ascent + rect.y + border.top; + */ + } + } + + // look at the first child + /* + const nsStyleFont* font; + firstFrame->GetStyleData(eStyleStruct_Font, + (const nsStyleStruct*&) font); + nsIRenderingContext& rc = *aReflowState.mReflowState.rendContext; + rc.SetFont(font->mFont); + nsIFontMetrics* fm; + rv = rc.GetFontMetrics(fm); + if (NS_SUCCEEDED(rv) && (nsnull != fm)) { + fm->GetMaxAscent(aDesiredSize.ascent); + NS_RELEASE(fm); + } + rv = NS_OK; + + + // add top border and padding to the ascent + nsRect rect(0,0,0,0); + firstFrame->GetRect(&rect); + + // now our max ascent is acent + the y offset of the the first child + aDesiredSize.ascent += rect.y; + } + */ + + PRBool changedSize = PR_FALSE; + + if (mLastSize.width != aDesiredSize.width || mLastSize.height != aDesiredSize.height) + changedSize = PR_TRUE; + + // if the child got bigger then make sure the new size in our min max range + if (changedSize) { + + // redraw if we changed size. + //aRedraw = PR_TRUE; + } + + nsContainerFrame::FinishReflowChild(mFrame, aPresContext, aDesiredSize, aX, aY, NS_FRAME_NO_MOVE_FRAME); + + + } else { + /* + if (aMoveFrame) { + PlaceChild(aPresContext, mFrame, aX + margin.left, aY + margin.top); + } + */ + } + + // add the margin back in. The child should add its border automatically + //aDesiredSize.height += (margin.top + margin.bottom); + //aDesiredSize.width += (margin.left + margin.right); + +#ifdef DEBUG_REFLOW + if (aHeight != NS_INTRINSICSIZE && aDesiredSize.height != aHeight) + { + AddIndents(); + printf("**** Child "); + nsFrame::ListTag(stdout, childFrame); + printf(" got taller!******\n"); + + } + if (aWidth != NS_INTRINSICSIZE && aDesiredSize.width != aWidth) + { + AddIndents(); + printf("**** Child "); + nsFrame::ListTag(stdout, childFrame); + printf(" got wider!******\n"); + + } +#endif + + if (aWidth == NS_INTRINSICSIZE) + aWidth = aDesiredSize.width; + + if (aHeight == NS_INTRINSICSIZE) + aHeight = aDesiredSize.height; + + mLastSize.width = aDesiredSize.width; + mLastSize.height = aDesiredSize.height; + + if (aDesiredSize.width > aWidth && mMinWidth != aDesiredSize.width) { + mMinWidth = aDesiredSize.width; + SizeNeedsRecalc(mMinSize); + } + + return NS_OK; +} + + +void +nsBoxToBlockAdaptor::PlaceChild(nsIPresContext* aPresContext, nsIFrame* aFrame, nscoord aX, nscoord aY) +{ + nsPoint curOrigin; + aFrame->GetOrigin(curOrigin); + + // only if the origin changed + if ((curOrigin.x != aX) || (curOrigin.y != aY)) { + aFrame->MoveTo(aPresContext, aX, aY); + + nsIView* view; + aFrame->GetView(aPresContext, &view); + if (view) { + nsContainerFrame::PositionFrameView(aPresContext, aFrame, view); + } else + nsContainerFrame::PositionChildViews(aPresContext, aFrame); + } +} + +/* +void +nsBoxToBlockAdaptor::BuildReflowChain(nsIFrame* aFrame, nsIFrame* aTargetParent, const nsHTMLReflowState& aRoot, nsHTMLReflowState& aState) +{ + nsIFrame* parent; + aFrame->GetParent(parent); + + if (aFrame != aTargetParent) + { + BuildReflowChain(parent, aTargetFrame, aRoot, aState); + nsHTMLReflowState state(aPresContext, aRoot, aFrame, nsSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE)); + aRoot = state; + } +} +*/ + + +PRBool +nsBoxToBlockAdaptor::GetWasCollapsed(nsBoxLayoutState& aBoxLayoutState) +{ + return mWasCollapsed; +} + +void +nsBoxToBlockAdaptor::SetWasCollapsed(nsBoxLayoutState& aBoxLayoutState, PRBool aCollapsed) +{ + mWasCollapsed = aCollapsed; +} + +NS_IMETHODIMP_(nsrefcnt) +nsBoxToBlockAdaptor::AddRef(void) +{ + return NS_OK; +} + +NS_IMETHODIMP_(nsrefcnt) +nsBoxToBlockAdaptor::Release(void) +{ + return NS_OK; +} + +// +// QueryInterface +// +NS_INTERFACE_MAP_BEGIN(nsBoxToBlockAdaptor) + NS_INTERFACE_MAP_ENTRY(nsIBoxToBlockAdaptor) +NS_INTERFACE_MAP_END_INHERITING(nsBox) + diff --git a/mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.h b/mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.h new file mode 100644 index 00000000000..4e1a8fe533b --- /dev/null +++ b/mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.h @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Author: + * Eric D Vaughan + * + * Contributor(s): + */ + +#ifndef nsBoxToBlockAdaptor_h___ +#define nsBoxToBlockAdaptor_h___ + +#include "nsIBoxToBlockAdaptor.h" +#include "nsBox.h" +class nsSpaceManager; + +class nsBoxToBlockAdaptor : public nsBox, nsIBoxToBlockAdaptor { + +public: + + NS_DECL_ISUPPORTS + + NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetFlex(nsBoxLayoutState& aBoxLayoutState, nscoord& aFlex); + NS_IMETHOD GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent); + NS_IMETHOD IsCollapsed(nsBoxLayoutState& aBoxLayoutState, PRBool& aCollapsed); + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); + NS_IMETHOD GetFrame(nsIFrame** aFrame); + NS_IMETHOD NeedsRecalc(); + + NS_IMETHOD Recycle(nsIPresShell* aPresShell); + + void* operator new(size_t sz, nsIPresShell* aPresShell); + void operator delete(void* aPtr, size_t sz); + + + nsBoxToBlockAdaptor(nsIPresShell* aShell, nsIFrame* aFrame); + ~nsBoxToBlockAdaptor(); + +protected: + virtual PRBool GetWasCollapsed(nsBoxLayoutState& aState); + virtual void SetWasCollapsed(nsBoxLayoutState& aState, PRBool aWas); + + virtual nsresult Reflow(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus, + nscoord aX, + nscoord aY, + nscoord aWidth, + nscoord aHeight, + PRBool aMoveFrame = PR_TRUE); + + virtual void PlaceChild(nsIPresContext* aPresContext, nsIFrame* aFrame, nscoord aX, nscoord aY); + + nsIFrame* mFrame; + nsSize mPrefSize; + nsSize mMinSize; + nsSize mMaxSize; + nscoord mFlex; + nscoord mAscent; + PRBool mPrefNeedsRecalc; + nsSpaceManager* mSpaceManager; + nsSize mLastSize; + nscoord mMinWidth; + PRBool mWasCollapsed; + +}; + +#endif + diff --git a/mozilla/layout/xul/base/src/nsXULButtonFrame.cpp b/mozilla/layout/xul/base/src/nsButtonBoxFrame.cpp similarity index 87% rename from mozilla/layout/xul/base/src/nsXULButtonFrame.cpp rename to mozilla/layout/xul/base/src/nsButtonBoxFrame.cpp index c4be4c2ea4d..0a25864398b 100644 --- a/mozilla/layout/xul/base/src/nsXULButtonFrame.cpp +++ b/mozilla/layout/xul/base/src/nsButtonBoxFrame.cpp @@ -22,7 +22,7 @@ * Contributor(s): */ #include "nsCOMPtr.h" -#include "nsXULButtonFrame.h" +#include "nsButtonBoxFrame.h" #include "nsIContent.h" #include "nsIDocument.h" #include "nsIDOMXULDocument.h" @@ -36,13 +36,13 @@ // Creates a new Button frame and returns it in |aNewFrame| // nsresult -NS_NewXULButtonFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) +NS_NewButtonBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) { NS_PRECONDITION(aNewFrame, "null OUT ptr"); if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } - nsXULButtonFrame* it = new (aPresShell) nsXULButtonFrame(aPresShell); + nsButtonBoxFrame* it = new (aPresShell) nsButtonBoxFrame(aPresShell); if (nsnull == it) return NS_ERROR_OUT_OF_MEMORY; @@ -52,11 +52,11 @@ NS_NewXULButtonFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) } // NS_NewXULButtonFrame -nsXULButtonFrame::nsXULButtonFrame(nsIPresShell* aPresShell) +nsButtonBoxFrame::nsButtonBoxFrame(nsIPresShell* aPresShell) :nsBoxFrame(aPresShell, PR_FALSE) {} -NS_IMETHODIMP nsXULButtonFrame::GetFrameForPoint(nsIPresContext* aPresContext, +NS_IMETHODIMP nsButtonBoxFrame::GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, nsFramePaintLayer aWhichLayer, nsIFrame** aFrame) @@ -66,7 +66,7 @@ NS_IMETHODIMP nsXULButtonFrame::GetFrameForPoint(nsIPresContext* aPresContext, } NS_IMETHODIMP -nsXULButtonFrame::HandleEvent(nsIPresContext* aPresContext, +nsButtonBoxFrame::HandleEvent(nsIPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus) { @@ -89,7 +89,7 @@ nsXULButtonFrame::HandleEvent(nsIPresContext* aPresContext, } void -nsXULButtonFrame::MouseClicked (nsIPresContext* aPresContext) +nsButtonBoxFrame::MouseClicked (nsIPresContext* aPresContext) { // Execute the oncommand event handler. nsEventStatus status = nsEventStatus_eIgnore; diff --git a/mozilla/layout/xul/base/src/nsXULButtonFrame.h b/mozilla/layout/xul/base/src/nsButtonBoxFrame.h similarity index 84% rename from mozilla/layout/xul/base/src/nsXULButtonFrame.h rename to mozilla/layout/xul/base/src/nsButtonBoxFrame.h index ddf003c871a..eded57dcf3e 100644 --- a/mozilla/layout/xul/base/src/nsXULButtonFrame.h +++ b/mozilla/layout/xul/base/src/nsButtonBoxFrame.h @@ -21,17 +21,17 @@ * * Contributor(s): */ -#ifndef nsXULButtonFrame_h___ -#define nsXULButtonFrame_h___ +#ifndef nsButtonBoxFrame_h___ +#define nsButtonBoxFrame_h___ #include "nsBoxFrame.h" -class nsXULButtonFrame : public nsBoxFrame +class nsButtonBoxFrame : public nsBoxFrame { public: - friend nsresult NS_NewXULButtonFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); + friend nsresult NS_NewButtonBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); - nsXULButtonFrame(nsIPresShell* aPresShell); + nsButtonBoxFrame(nsIPresShell* aPresShell); NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, @@ -45,6 +45,6 @@ public: virtual void MouseClicked (nsIPresContext* aPresContext); -}; // class nsXULButtonFrame +}; // class nsButtonBoxFrame -#endif /* nsXULButtonFrame_h___ */ +#endif /* nsButtonBoxFrame_h___ */ diff --git a/mozilla/layout/xul/base/src/nsXULCheckboxFrame.cpp b/mozilla/layout/xul/base/src/nsCheckBoxFrame.cpp similarity index 77% rename from mozilla/layout/xul/base/src/nsXULCheckboxFrame.cpp rename to mozilla/layout/xul/base/src/nsCheckBoxFrame.cpp index 3d6a9310dc3..85443144ef1 100644 --- a/mozilla/layout/xul/base/src/nsXULCheckboxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsCheckBoxFrame.cpp @@ -17,12 +17,10 @@ * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * - * Original Author: David W. Hyatt (hyatt@netscape.com) - * * Contributor(s): */ #include "nsCOMPtr.h" -#include "nsXULCheckboxFrame.h" +#include "nsCheckBoxFrame.h" #include "nsIDOMXULCheckboxElement.h" #include "nsIContent.h" #include "nsIDOMXULRadioElement.h" @@ -34,27 +32,31 @@ // -// NS_NewXULCheckboxFrame +// NS_NewCheckBoxFrame // // Creates a new checkbox frame and returns it in |aNewFrame| // nsresult -NS_NewXULCheckboxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) +NS_NewCheckBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) { NS_PRECONDITION(aNewFrame, "null OUT ptr"); if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } - nsXULCheckboxFrame* it = new (aPresShell) nsXULCheckboxFrame(aPresShell); + nsCheckBoxFrame* it = new (aPresShell) nsCheckBoxFrame (aPresShell); if (nsnull == it) return NS_ERROR_OUT_OF_MEMORY; - // it->SetFlags(aFlags); *aNewFrame = it; return NS_OK; -} // NS_NewXULCheckboxFrame +} // NS_NewCheckBoxFrame -nsXULCheckboxFrame::nsXULCheckboxFrame(nsIPresShell* aPresShell) -:nsXULButtonFrame(aPresShell) -{} +PRIntn nsCheckBoxFrame::GetDefaultAlignment() +{ + return NS_SIDE_LEFT; +} + +nsCheckBoxFrame::nsCheckBoxFrame(nsIPresShell* aPresShell):nsButtonBoxFrame(aPresShell) +{ +} \ No newline at end of file diff --git a/mozilla/layout/xul/base/src/nsXULCheckboxFrame.h b/mozilla/layout/xul/base/src/nsCheckBoxFrame.h similarity index 68% rename from mozilla/layout/xul/base/src/nsXULCheckboxFrame.h rename to mozilla/layout/xul/base/src/nsCheckBoxFrame.h index f07ff431ec9..341afea811f 100644 --- a/mozilla/layout/xul/base/src/nsXULCheckboxFrame.h +++ b/mozilla/layout/xul/base/src/nsCheckBoxFrame.h @@ -17,22 +17,23 @@ * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * - * Original Author: David W. Hyatt (hyatt@netscape.com) - * * Contributor(s): */ -#ifndef nsXULCheckboxFrame_h___ -#define nsXULCheckboxFrame_h___ +#ifndef nsCheckBoxFrame_h___ +#define nsCheckBoxFrame_h___ -#include "nsXULButtonFrame.h" +#include "nsButtonBoxFrame.h" -class nsXULCheckboxFrame : public nsXULButtonFrame +class nsCheckBoxFrame : public nsButtonBoxFrame { public: - nsXULCheckboxFrame(nsIPresShell* aPresShell); - friend nsresult NS_NewXULCheckboxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); + friend nsresult NS_NewCheckBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); -}; // class nsXULCheckboxFrame + PRIntn GetDefaultAlignment(); -#endif /* nsXULCheckboxFrame_h___ */ + nsCheckBoxFrame(nsIPresShell* aPresShell); + +}; // class nsCheckBoxFrame + +#endif /* nsCheckBoxFrame_h___ */ diff --git a/mozilla/layout/xul/base/src/nsColorPickerFrame.cpp b/mozilla/layout/xul/base/src/nsColorPickerFrame.cpp index 8086c1384fe..2952278aeb5 100644 --- a/mozilla/layout/xul/base/src/nsColorPickerFrame.cpp +++ b/mozilla/layout/xul/base/src/nsColorPickerFrame.cpp @@ -36,6 +36,7 @@ #include "nsIServiceManager.h" #include "nsStdColorPicker.h" #include "nsColorPickerCID.h" +#include "nsBoxLayoutState.h" // // NS_NewColorPickerFrame // @@ -48,7 +49,7 @@ NS_NewColorPickerFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } - nsColorPickerFrame* it = new (aPresShell) nsColorPickerFrame; + nsColorPickerFrame* it = new (aPresShell) nsColorPickerFrame (aPresShell); if ( !it ) return NS_ERROR_OUT_OF_MEMORY; *aNewFrame = it; @@ -60,10 +61,6 @@ NS_NewColorPickerFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) // // nsColorPickerFrame cntr // -nsColorPickerFrame::nsColorPickerFrame() -{ - -} nsColorPickerFrame::~nsColorPickerFrame() { @@ -192,6 +189,28 @@ nsColorPickerFrame::Paint(nsIPresContext* aPresContext, } +NS_IMETHODIMP +nsColorPickerFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + float p2t; + + nsIPresContext* presContext = aBoxLayoutState.GetPresContext(); + + presContext->GetScaledPixelsToTwips(&p2t); + + nsSize pixelSize(0,0); + mColorPicker->GetSize(&pixelSize.width, &pixelSize.height); + + aSize.width = nscoord(pixelSize.width * p2t); + aSize.height = nscoord(pixelSize.height * p2t); + + AddBorderAndPadding(aSize); + AddInset(aSize); + + return NS_OK; +} + +/* // // GetDesiredSize // @@ -202,34 +221,6 @@ nsColorPickerFrame::GetDesiredSize(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredSize) { - float p2t; - - aPresContext->GetScaledPixelsToTwips(&p2t); - - - // if the width is set use it - if (NS_INTRINSICSIZE != aReflowState.mComputedWidth) - aDesiredSize.width = aReflowState.mComputedWidth; - else - aDesiredSize.width = -1; - - // if the height is set use it - if (NS_INTRINSICSIZE != aReflowState.mComputedHeight) - aDesiredSize.height = aReflowState.mComputedHeight; - else - aDesiredSize.height = -1; - - mColorPicker->SetSize((aDesiredSize.width == -1) ? -1 : PRInt32(aDesiredSize.width/p2t), - (aDesiredSize.height == -1) ? -1 : PRInt32(aDesiredSize.height/p2t)); - - - int width, height; - - mColorPicker->GetSize(&width, &height); - - aDesiredSize.width = nscoord(width * p2t); - aDesiredSize.height = nscoord(height * p2t); - aDesiredSize.ascent = nscoord(height * p2t); - aDesiredSize.descent = 0; } // GetDesiredSize +*/ \ No newline at end of file diff --git a/mozilla/layout/xul/base/src/nsColorPickerFrame.h b/mozilla/layout/xul/base/src/nsColorPickerFrame.h index 1698e7cc990..6b696bd0241 100644 --- a/mozilla/layout/xul/base/src/nsColorPickerFrame.h +++ b/mozilla/layout/xul/base/src/nsColorPickerFrame.h @@ -28,7 +28,7 @@ #define nsColorPickerFrame_h__ -#include "nsLeafFrame.h" +#include "nsLeafBoxFrame.h" #include "prtypes.h" #include "nsIAtom.h" #include "nsCOMPtr.h" @@ -40,12 +40,15 @@ class nsString; nsresult NS_NewColorPickerFrame(nsIPresShell* aPresShell, nsIFrame** aResult) ; -class nsColorPickerFrame : public nsLeafFrame +class nsColorPickerFrame : public nsLeafBoxFrame { public: - nsColorPickerFrame(); + nsColorPickerFrame(nsIPresShell* aShell):nsLeafBoxFrame(aShell) {} virtual ~nsColorPickerFrame(); + NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + + NS_IMETHOD Init(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParent, @@ -72,10 +75,6 @@ public: nsFramePaintLayer aWhichLayer); protected: - virtual void GetDesiredSize(nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - nsHTMLReflowMetrics& aDesiredSize) ; - private: nsIColorPicker *mColorPicker; diff --git a/mozilla/layout/xul/base/src/nsContainerBox.cpp b/mozilla/layout/xul/base/src/nsContainerBox.cpp new file mode 100644 index 00000000000..0ecacaa8026 --- /dev/null +++ b/mozilla/layout/xul/base/src/nsContainerBox.cpp @@ -0,0 +1,536 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Pierre Phaneuf + */ + +// +// Eric Vaughan +// Netscape Communications +// +// See documentation in associated header file +// + + +#include "nsBoxLayoutState.h" +#include "nsBox.h" +#include "nsIStyleContext.h" +#include "nsIPresContext.h" +#include "nsCOMPtr.h" +#include "nsIContent.h" +#include "nsIViewManager.h" +#include "nsIView.h" +#include "nsIPresShell.h" +#include "nsHTMLContainerFrame.h" +#include "nsBoxToBlockAdaptor.h" + +#include "nsBoxLayoutState.h" +#include "nsBoxFrame.h" +#include "nsIStyleContext.h" +#include "nsIPresContext.h" +#include "nsCOMPtr.h" +#include "nsHTMLIIDs.h" +#include "nsUnitConversion.h" +#include "nsINameSpaceManager.h" +#include "nsHTMLAtoms.h" +#include "nsXULAtoms.h" +#include "nsIReflowCommand.h" +#include "nsIContent.h" +#include "nsSpaceManager.h" +#include "nsHTMLParts.h" +#include "nsIViewManager.h" +#include "nsIView.h" +#include "nsIPresShell.h" +#include "nsGenericHTMLElement.h" +#include "nsFrameNavigator.h" +#include "nsCSSRendering.h" +#include "nsISelfScrollingFrame.h" +#include "nsIPref.h" +#include "nsIServiceManager.h" + +#include "nsContainerBox.h" + +nsContainerBox::nsContainerBox(nsIPresShell* aShell):nsBox(aShell) +{ + mFirstChild = nsnull; + mLastChild = nsnull; + mChildCount = 0; +} + +NS_IMETHODIMP +nsContainerBox::GetChildBox(nsIBox** aBox) +{ + *aBox = mFirstChild; + return NS_OK; +} + +PRInt32 +nsContainerBox::GetChildCount() +{ + return mChildCount; +} + +PRInt32 +nsContainerBox::CreateBoxList(nsIPresShell* aPresShell, nsIFrame* aFrameList, nsIBox*& aFirst, nsIBox*& aLast) +{ + PRInt32 count = 0; + if (aFrameList) { + nsIBox* ibox = nsnull; + if (NS_SUCCEEDED(aFrameList->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) + aFirst = ibox; + else + aFirst = new (aPresShell) nsBoxToBlockAdaptor(aPresShell, aFrameList); + + aFirst->SetParentBox(this); + + count++; + aLast = aFirst; + aFrameList->GetNextSibling(&aFrameList); + nsIBox* last = aLast; + + while(aFrameList) { + + if (NS_SUCCEEDED(aFrameList->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) + aLast = ibox; + else + aLast = new (aPresShell) nsBoxToBlockAdaptor(aPresShell, aFrameList); + + aLast->SetParentBox(this); + + last->SetNextBox(aLast); + last = aLast; + aFrameList->GetNextSibling(&aFrameList); + count++; + } + } + + return count; +} + +nsIBox* +nsContainerBox::GetPrevious(nsIFrame* aFrame) +{ + if (aFrame == nsnull) + return nsnull; + + // find the frame to remove + nsIBox* box = mFirstChild; + nsIBox* prev = nsnull; + while (box) + { + nsIFrame* frame = nsnull; + box->GetFrame(&frame); + if (frame == aFrame) { + return prev; + } + + prev = box; + box->GetNextBox(&box); + } + + return nsnull; +} + +nsIBox* +nsContainerBox::GetBox(nsIFrame* aFrame) +{ + if (aFrame == nsnull) + return nsnull; + + // recycle adaptors + // nsIBox* ibox = nsnull; + + // if (NS_SUCCEEDED(aFrame->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) + // return ibox; + + // find the frame to remove + nsIBox* box = mFirstChild; + while (box) + { + nsIFrame* frame = nsnull; + box->GetFrame(&frame); + + if (frame == aFrame) { + return box; + } + + box->GetNextBox(&box); + } + + return nsnull; +} + +nsIBox* +nsContainerBox::GetBoxAt(PRInt32 aIndex) +{ + // find the frame to remove + nsIBox* child = mFirstChild; + PRInt32 count = 0; + while (child) + { + if (count == aIndex) { + return child; + } + + child->GetNextBox(&child); + count++; + } + + return nsnull; +} + +PRInt32 +nsContainerBox::GetIndexOf(nsIBox* aBox) +{ + // find the frame to remove + nsIBox* child = mFirstChild; + PRInt32 count = 0; + while (child) + { + if (aBox == child) { + return count; + } + + child->GetNextBox(&child); + count++; + } + + return -1; +} + +void +nsContainerBox::Remove(nsIPresShell* aShell, nsIFrame* aFrame) +{ + // get the info before the frame + nsIBox* prevBox = GetPrevious(aFrame); + RemoveAfter(aShell, prevBox); +} + +void +nsContainerBox::Insert(nsIPresShell* aShell, nsIFrame* aPrevFrame, nsIFrame* aFrameList) +{ + nsIBox* prevBox = GetBox(aPrevFrame); + //NS_ASSERTION(aPrevFrame == nsnull || prevBox,"Error! The previous frame given is not in our list!"); + + // find the frame before this one + // if no previous frame then we are inserting in front + if (prevBox == nsnull) { + // prepend them + Prepend(aShell, aFrameList); + } else { + // insert insert after previous info + InsertAfter(aShell, prevBox, aFrameList); + } +} + +void +nsContainerBox::RemoveAfter(nsIPresShell* aPresShell, nsIBox* aPrevious) +{ + nsIBox* toDelete = nsnull; + + if (aPrevious == nsnull) + { + NS_ASSERTION(mFirstChild,"Can't find first child"); + toDelete = mFirstChild; + if (mLastChild == mFirstChild) { + nsIBox* next = nsnull; + mFirstChild->GetNextBox(&next); + mLastChild = next; + } + mFirstChild->GetNextBox(&mFirstChild); + } else { + aPrevious->GetNextBox(&toDelete); + NS_ASSERTION(toDelete,"Can't find child to delete"); + + nsIBox* next = nsnull; + toDelete->GetNextBox(&next); + aPrevious->SetNextBox(next); + + if (mLastChild == toDelete) + mLastChild = aPrevious; + } + + // recycle adaptors + nsIBoxToBlockAdaptor* adaptor = nsnull; + + if (NS_SUCCEEDED(toDelete->QueryInterface(NS_GET_IID(nsIBoxToBlockAdaptor), (void**)&adaptor)) && adaptor) + adaptor->Recycle(aPresShell); + + mChildCount--; +} + +void +nsContainerBox::ClearChildren(nsIPresShell* aShell) +{ + nsIBox* box = mFirstChild; + while(box) { + nsIBox* it = box; + box->GetNextBox(&box); + // recycle adaptors + nsIBoxToBlockAdaptor* adaptor = nsnull; + + if (NS_SUCCEEDED(it->QueryInterface(NS_GET_IID(nsIBoxToBlockAdaptor), (void**)&adaptor)) && adaptor) + adaptor->Recycle(aShell); + } + + mFirstChild= nsnull; + mLastChild= nsnull; + mChildCount = 0; +} + +void +nsContainerBox::Prepend(nsIPresShell* aPresShell, nsIFrame* aList) +{ + nsIBox* first; + nsIBox* last; + mChildCount += CreateBoxList(aPresShell, aList, first, last); + if (!mFirstChild) + mFirstChild= mLastChild= first; + else { + last->SetNextBox(mFirstChild); + mFirstChild= first; + } +} + +void +nsContainerBox::Append(nsIPresShell* aPresShell, nsIFrame* aList) +{ + nsIBox* first; + nsIBox* last; + mChildCount += CreateBoxList(aPresShell, aList, first, last); + if (!mFirstChild) + mFirstChild= first; + else + mLastChild->SetNextBox(first); + + mLastChild= last; +} + +void +nsContainerBox::InsertAfter(nsIPresShell* aPresShell, nsIBox* aPrev, nsIFrame* aList) +{ + nsIBox* first = nsnull; + nsIBox* last = nsnull; + mChildCount += CreateBoxList(aPresShell, aList, first, last); + nsIBox* next = nsnull; + aPrev->GetNextBox(&next); + last->SetNextBox(next); + aPrev->SetNextBox(first); + if (aPrev == mLastChild) + mLastChild = last; +} + +void +nsContainerBox::InitChildren(nsIPresShell* aPresShell, nsIFrame* aList) +{ + ClearChildren(aPresShell); + mChildCount += CreateBoxList(aPresShell, aList, mFirstChild, mLastChild); +} + +void +nsContainerBox::SetDebugOnChildList(nsBoxLayoutState& aState, nsIBox* aChild, PRBool aDebug) +{ + nsIBox* child = nsnull; + GetChildBox(&child); + while (child) + { + child->SetDebug(aState, aDebug); + child->GetNextBox(&child); + } +} + +void +nsContainerBox::SanityCheck(nsFrameList& aFrameList) +{ + // make sure the length match + PRInt32 length = aFrameList.GetLength(); + NS_ASSERTION(length == mChildCount,"nsBox::ERROR!! Box info list count does not match frame count!!"); + + // make sure last makes sense + nsIBox* next = nsnull; + NS_ASSERTION(mLastChild == nsnull || (NS_SUCCEEDED(mLastChild->GetNextBox(&next)) && next == nsnull),"nsBox::ERROR!! The last child is not really the last!!!"); + nsIFrame* child = aFrameList.FirstChild(); + nsIBox* box = mFirstChild; + PRInt32 count = 0; + while(box) + { + NS_ASSERTION(count <= mChildCount,"too many children!!!"); + nsIFrame* frame = nsnull; + nsIBox* parent = nsnull; + NS_ASSERTION(NS_SUCCEEDED(box->GetFrame(&frame)) && frame == child,"nsBox::ERROR!! box info list and child info lists don't match!!!"); + NS_ASSERTION(NS_SUCCEEDED(box->GetParentBox(&parent)) && parent == this,"nsBox::ERROR!! parent's don't match!!!"); + box->GetNextBox(&box); + child->GetNextSibling(&child); + count++; + } +} + + +NS_IMETHODIMP +nsContainerBox::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + nsresult rv = NS_OK; + + aSize.width = 0; + aSize.height = 0; + + // if the size was not completely redefined in CSS then ask our children + if (!nsIBox::AddCSSPrefSize(aBoxLayoutState, this, aSize)) + { + aSize.width = 0; + aSize.height = 0; + + if (mLayoutManager) { + rv = mLayoutManager->GetPrefSize(this, aBoxLayoutState, aSize); + nsIBox::AddCSSPrefSize(aBoxLayoutState, this, aSize); + } else + rv = nsBox::GetPrefSize(aBoxLayoutState, aSize); + } + + nsSize minSize(0,0); + nsSize maxSize(0,0); + GetMinSize(aBoxLayoutState, minSize); + GetMaxSize(aBoxLayoutState, maxSize); + + BoundsCheck(minSize, aSize, maxSize); + + return rv; +} + +NS_IMETHODIMP +nsContainerBox::GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + nsresult rv = NS_OK; + + aSize.width = 0; + aSize.height = 0; + + // if the size was not completely redefined in CSS then ask our children + if (!nsIBox::AddCSSMinSize(aBoxLayoutState, this, aSize)) + { + aSize.width = 0; + aSize.height = 0; + + if (mLayoutManager) { + rv = mLayoutManager->GetMinSize(this, aBoxLayoutState, aSize); + nsIBox::AddCSSMinSize(aBoxLayoutState, this, aSize); + } else { + rv = nsBox::GetMinSize(aBoxLayoutState, aSize); + } + } + + return rv; +} + +NS_IMETHODIMP +nsContainerBox::GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + nsresult rv = NS_OK; + + aSize.width = NS_INTRINSICSIZE; + aSize.height = NS_INTRINSICSIZE; + + // if the size was not completely redefined in CSS then ask our children + if (!nsIBox::AddCSSMaxSize(aBoxLayoutState, this, aSize)) + { + aSize.width = NS_INTRINSICSIZE; + aSize.height = NS_INTRINSICSIZE; + + if (mLayoutManager) { + rv = mLayoutManager->GetMaxSize(this, aBoxLayoutState, aSize); + nsIBox::AddCSSMaxSize(aBoxLayoutState, this, aSize); + } else { + rv = nsBox::GetMaxSize(aBoxLayoutState, aSize); + } + } + + return rv; +} + + +NS_IMETHODIMP +nsContainerBox::GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent) +{ + nsresult rv = NS_OK; + + aAscent = 0; + if (mLayoutManager) + rv = mLayoutManager->GetAscent(this, aBoxLayoutState, aAscent); + else + rv = nsBox::GetAscent(aBoxLayoutState, aAscent); + + return rv; +} + +NS_IMETHODIMP +nsContainerBox::Layout(nsBoxLayoutState& aBoxLayoutState) +{ + nsresult rv = NS_OK; + + if (mLayoutManager) + rv = mLayoutManager->Layout(this, aBoxLayoutState); + + nsBox::Layout(aBoxLayoutState); + + return rv; +} + +NS_IMETHODIMP +nsContainerBox::SetLayoutManager(nsIBoxLayout* aLayout) +{ + mLayoutManager = aLayout; + return NS_OK; +} + +NS_IMETHODIMP +nsContainerBox::GetLayoutManager(nsIBoxLayout** aLayout) +{ + *aLayout = mLayoutManager; + return NS_OK; +} + +nsresult +nsContainerBox::LayoutChildAt(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect) +{ + // get the current rect + nsRect oldRect(0,0,0,0); + aBox->GetBounds(oldRect); + aBox->SetBounds(aState, aRect); + + PRBool dirty = PR_FALSE; + PRBool dirtyChildren = PR_FALSE; + aBox->IsDirty(dirty); + aBox->HasDirtyChildren(dirtyChildren); + + PRBool layout = PR_TRUE; + if (!(dirty || dirtyChildren) && aState.GetLayoutReason() != nsBoxLayoutState::Initial) + layout = PR_FALSE; + + if (layout || (oldRect.width != aRect.width || oldRect.height != aRect.height)) { + return aBox->Layout(aState); + } + + return NS_OK; +} + + + + + diff --git a/mozilla/layout/xul/base/src/nsContainerBox.h b/mozilla/layout/xul/base/src/nsContainerBox.h new file mode 100644 index 00000000000..4dcf463fa40 --- /dev/null +++ b/mozilla/layout/xul/base/src/nsContainerBox.h @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Author: + * Eric D Vaughan + * + * Contributor(s): + */ + +#ifndef nsContainerBox_h___ +#define nsContainerBox_h___ + +#include "nsBox.h" +#include "nsCOMPtr.h" +#include "nsIBoxLayout.h" + +class nsContainerBox : public nsBox { + +public: + + NS_IMETHOD GetChildBox(nsIBox** aBox); + + nsContainerBox(nsIPresShell* aShell); + + NS_IMETHOD SetLayoutManager(nsIBoxLayout* aLayout); + NS_IMETHOD GetLayoutManager(nsIBoxLayout** aLayout); + NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent); + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); + + virtual nsIBox* GetBoxAt(PRInt32 aIndex); + virtual nsIBox* GetBox(nsIFrame* aFrame); + virtual PRInt32 GetIndexOf(nsIBox* aBox); + virtual PRInt32 GetChildCount(); + virtual void ClearChildren(nsIPresShell* aShell); + virtual PRInt32 CreateBoxList(nsIPresShell* aShell, nsIFrame* aList, nsIBox*& first, nsIBox*& last); + virtual void RemoveAfter(nsIPresShell* aShell, nsIBox* aPrev); + virtual void Remove(nsIPresShell* aShell, nsIFrame* aChild); + virtual void Prepend(nsIPresShell* aShell, nsIFrame* aList); + virtual void Append(nsIPresShell* aShell, nsIFrame* aList); + virtual void Insert(nsIPresShell* aShell, nsIFrame* aPrevFrame, nsIFrame* aList); + virtual void InsertAfter(nsIPresShell* aShell, nsIBox* aPrev, nsIFrame* aList); + virtual void InitChildren(nsIPresShell* aShell, nsIFrame* aList); + virtual nsIBox* GetPrevious(nsIFrame* aChild); + virtual void SanityCheck(nsFrameList& aFrameList); + virtual void SetDebugOnChildList(nsBoxLayoutState& aState, nsIBox* aChild, PRBool aDebug); + +protected: + + virtual nsresult LayoutChildAt(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect); + + nsIBox* mFirstChild; + nsIBox* mLastChild; + PRInt32 mChildCount; + nsCOMPtr mLayoutManager; +}; + +#endif + diff --git a/mozilla/layout/xul/base/src/nsDeckFrame.cpp b/mozilla/layout/xul/base/src/nsDeckFrame.cpp index ddbc064a4c4..0c43967348d 100644 --- a/mozilla/layout/xul/base/src/nsDeckFrame.cpp +++ b/mozilla/layout/xul/base/src/nsDeckFrame.cpp @@ -43,7 +43,8 @@ #include "nsStyleChangeList.h" #include "nsCSSRendering.h" #include "nsIViewManager.h" - +#include "nsBoxLayoutState.h" +#include "nsStackLayout.h" nsresult NS_NewDeckFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) @@ -56,14 +57,21 @@ NS_NewDeckFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) if (nsnull == it) return NS_ERROR_OUT_OF_MEMORY; + *aNewFrame = it; return NS_OK; } // NS_NewDeckFrame -nsDeckFrame::nsDeckFrame(nsIPresShell* aPresShell):nsStackFrame(aPresShell) +nsCOMPtr nsDeckFrame::gLayout = nsnull; + +nsDeckFrame::nsDeckFrame(nsIPresShell* aPresShell):nsBoxFrame(aPresShell) { + if (!gLayout) + gLayout = new nsStackLayout(aPresShell); + + SetLayoutManager(gLayout); } NS_IMETHODIMP @@ -73,49 +81,14 @@ nsDeckFrame::AttributeChanged(nsIPresContext* aPresContext, nsIAtom* aAttribute, PRInt32 aHint) { - nsresult rv = nsStackFrame::AttributeChanged(aPresContext, aChild, + nsresult rv = nsBoxFrame::AttributeChanged(aPresContext, aChild, aNameSpaceID, aAttribute, aHint); // if the index changed hide the old element and make the now element visible if (aAttribute == nsHTMLAtoms::index) { - - Invalidate(aPresContext, nsRect(0,0,mRect.width,mRect.height), PR_FALSE); - - int index = 0; - - // get the index attribute - nsAutoString value; - if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::index, value)) - { - PRInt32 error; - - // convert it to an integer - index = value.ToInteger(&error); - } - - nsIFrame* childFrame = mFrames.FirstChild(); - nscoord count = 0; - while (nsnull != childFrame) - { - // make collapsed children not show up - if (index != count) - CollapseChild(aPresContext, childFrame, PR_TRUE); - else - CollapseChild(aPresContext, childFrame, PR_FALSE); - - rv = childFrame->GetNextSibling(&childFrame); - NS_ASSERTION(rv == NS_OK,"failed to get next child"); - count++; - } - - } - - - - - if (NS_OK != rv) { - return rv; + nsBoxLayoutState state(aPresContext); + MarkDirty(state); } return NS_OK; @@ -154,11 +127,11 @@ nsDeckFrame::Paint(nsIPresContext* aPresContext, // if a tab is hidden all its children are too. const nsStyleDisplay* disp = (const nsStyleDisplay*) mStyleContext->GetStyleData(eStyleStruct_Display); - if (!disp->IsVisibleOrCollapsed()) + if (!disp->mVisible) return NS_OK; if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { - if (disp->IsVisibleOrCollapsed() && mRect.width && mRect.height) { + if (disp->IsVisible() && mRect.width && mRect.height) { // Paint our background and border PRIntn skipSides = GetSkipSides(); const nsStyleColor* color = (const nsStyleColor*) @@ -186,44 +159,33 @@ nsDeckFrame::Paint(nsIPresContext* aPresContext, NS_IMETHODIMP nsDeckFrame::GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, - nsFramePaintLayer aWhichLayer, + nsFramePaintLayer aWhichLayer, nsIFrame** aFrame) { - - // If it's not in this frame, then it's not going to be in any - // children (since there cannot be overflowing children). + // if it is not inside us fail if (!mRect.Contains(aPoint)) { - return NS_ERROR_FAILURE; + return NS_ERROR_FAILURE; } + // if its not in our child just return us. + *aFrame = this; + // get the selected frame and see if the point is in it. nsIFrame* selectedFrame = GetSelectedFrame(); + nsPoint tmp; + tmp.MoveTo(aPoint.x - mRect.x, aPoint.y - mRect.y); if (nsnull != selectedFrame) { - // adjust the point - nsPoint p = aPoint; - p.x -= mRect.x; - p.y -= mRect.y; - return selectedFrame->GetFrameForPoint(aPresContext, p, aWhichLayer, aFrame); - } - - if (aWhichLayer == NS_FRAME_PAINT_LAYER_BACKGROUND) { - // if its not in our child just return us. - const nsStyleDisplay* disp = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - if (disp->IsVisible()) { - *aFrame = this; - return NS_OK; - } + return selectedFrame->GetFrameForPoint(aPresContext, tmp, aWhichLayer, aFrame); } - return NS_ERROR_FAILURE; + return NS_OK; } + NS_IMETHODIMP -nsDeckFrame::DidReflow(nsIPresContext* aPresContext, - nsDidReflowStatus aStatus) +nsDeckFrame::Layout(nsBoxLayoutState& aState) { int index = 0; @@ -237,21 +199,34 @@ nsDeckFrame::DidReflow(nsIPresContext* aPresContext, index = value.ToInteger(&error); } - nsresult rv = nsBoxFrame::DidReflow(aPresContext, aStatus); - NS_ASSERTION(rv == NS_OK,"DidReflow failed"); + nsIBox* box = nsnull; + GetChildBox(&box); - nsIFrame* childFrame = mFrames.FirstChild(); nscoord count = 0; - while (nsnull != childFrame) + while (nsnull != box) + { + // make collapsed children not show up + if (index == count) + box->UnCollapse(aState); + + nsresult rv2 = box->GetNextBox(&box); + NS_ASSERTION(rv2 == NS_OK,"failed to get next child"); + count++; + } + + nsresult rv = nsBoxFrame::Layout(aState); + + GetChildBox(&box); + + count = 0; + while (nsnull != box) { // make collapsed children not show up if (index != count) - CollapseChild(aPresContext, childFrame, PR_TRUE); - else - CollapseChild(aPresContext, childFrame, PR_FALSE); + box->Collapse(aState); - rv = childFrame->GetNextSibling(&childFrame); - NS_ASSERTION(rv == NS_OK,"failed to get next child"); + nsresult rv2 = box->GetNextBox(&box); + NS_ASSERTION(rv2 == NS_OK,"failed to get next child"); count++; } diff --git a/mozilla/layout/xul/base/src/nsDeckFrame.h b/mozilla/layout/xul/base/src/nsDeckFrame.h index f5b4bdd6806..57bad08848b 100644 --- a/mozilla/layout/xul/base/src/nsDeckFrame.h +++ b/mozilla/layout/xul/base/src/nsDeckFrame.h @@ -31,9 +31,9 @@ #ifndef nsDeckFrame_h___ #define nsDeckFrame_h___ -#include "nsStackFrame.h" +#include "nsBoxFrame.h" -class nsDeckFrame : public nsStackFrame +class nsDeckFrame : public nsBoxFrame { public: @@ -47,8 +47,7 @@ public: nsIAtom* aAttribute, PRInt32 aHint); - NS_IMETHOD DidReflow(nsIPresContext* aPresContext, - nsDidReflowStatus aStatus); + NS_IMETHOD Layout(nsBoxLayoutState& aState); NS_IMETHOD Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -56,10 +55,10 @@ public: nsFramePaintLayer aWhichLayer); - NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, - const nsPoint& aPoint, - nsFramePaintLayer aWhichLayer, - nsIFrame** aFrame); + NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, + const nsPoint& aPoint, + nsFramePaintLayer aWhichLayer, + nsIFrame** aFrame); NS_IMETHOD GetFrameName(nsString& aResult) const { @@ -75,6 +74,7 @@ protected: private: + static nsCOMPtr gLayout; nsIFrame* mSelected; }; // class nsDeckFrame diff --git a/mozilla/layout/xul/base/src/nsFrameNavigator.cpp b/mozilla/layout/xul/base/src/nsFrameNavigator.cpp index 3ec48e74196..6acd6ec16e1 100644 --- a/mozilla/layout/xul/base/src/nsFrameNavigator.cpp +++ b/mozilla/layout/xul/base/src/nsFrameNavigator.cpp @@ -30,10 +30,14 @@ #include "nsFrameNavigator.h" #include "nsCOMPtr.h" #include "nsIContent.h" +#include "nsIBox.h" nsIAtom* -nsFrameNavigator::GetTag(nsIFrame* frame) +nsFrameNavigator::GetTag(nsIBox* aBox) { + nsIFrame* frame = nsnull; + aBox->GetFrame(&frame); + nsCOMPtr content; frame->GetContent(getter_AddRefs(content)); if (content) { @@ -45,11 +49,11 @@ nsFrameNavigator::GetTag(nsIFrame* frame) return nsnull; } -nsIFrame* -nsFrameNavigator::GetChildBeforeAfter(nsIPresContext* aPresContext, nsIFrame* start, PRBool before) +nsIBox* +nsFrameNavigator::GetChildBeforeAfter(nsIPresContext* aPresContext, nsIBox* start, PRBool before) { - nsIFrame* parent = nsnull; - start->GetParent(&parent); + nsIBox* parent = nsnull; + start->GetParentBox(&parent); PRInt32 index = IndexOf(aPresContext, parent,start); PRInt32 count = CountFrames(aPresContext, parent); @@ -72,18 +76,18 @@ nsFrameNavigator::GetChildBeforeAfter(nsIPresContext* aPresContext, nsIFrame* st } PRInt32 -nsFrameNavigator::IndexOf(nsIPresContext* aPresContext, nsIFrame* parent, nsIFrame* child) +nsFrameNavigator::IndexOf(nsIPresContext* aPresContext, nsIBox* parent, nsIBox* child) { PRInt32 count = 0; - nsIFrame* childFrame; - parent->FirstChild(aPresContext, nsnull, &childFrame); - while (nsnull != childFrame) + nsIBox* box = nsnull; + parent->GetChildBox(&box); + while (nsnull != box) { - if (childFrame == child) + if (box == child) return count; - nsresult rv = childFrame->GetNextSibling(&childFrame); + nsresult rv = box->GetNextBox(&box); NS_ASSERTION(rv == NS_OK,"failed to get next child"); count++; } @@ -92,15 +96,15 @@ nsFrameNavigator::IndexOf(nsIPresContext* aPresContext, nsIFrame* parent, nsIFra } PRInt32 -nsFrameNavigator::CountFrames(nsIPresContext* aPresContext, nsIFrame* aFrame) +nsFrameNavigator::CountFrames(nsIPresContext* aPresContext, nsIBox* aBox) { PRInt32 count = 0; - nsIFrame* childFrame; - aFrame->FirstChild(aPresContext, nsnull, &childFrame); - while (nsnull != childFrame) + nsIBox* box; + aBox->GetChildBox(&box); + while (nsnull != box) { - nsresult rv = childFrame->GetNextSibling(&childFrame); + nsresult rv = box->GetNextBox(&box); NS_ASSERTION(rv == NS_OK,"failed to get next child"); count++; } @@ -108,19 +112,19 @@ nsFrameNavigator::CountFrames(nsIPresContext* aPresContext, nsIFrame* aFrame) return count; } -nsIFrame* -nsFrameNavigator::GetChildAt(nsIPresContext* aPresContext, nsIFrame* parent, PRInt32 index) +nsIBox* +nsFrameNavigator::GetChildAt(nsIPresContext* aPresContext, nsIBox* parent, PRInt32 index) { PRInt32 count = 0; - nsIFrame* childFrame; - parent->FirstChild(aPresContext, nsnull, &childFrame); - while (nsnull != childFrame) + nsIBox* box; + parent->GetChildBox(&box); + while (nsnull != box) { if (count == index) - return childFrame; + return box; - nsresult rv = childFrame->GetNextSibling(&childFrame); + nsresult rv = box->GetNextBox(&box); NS_ASSERTION(rv == NS_OK,"failed to get next child"); count++; } diff --git a/mozilla/layout/xul/base/src/nsFrameNavigator.h b/mozilla/layout/xul/base/src/nsFrameNavigator.h index 1a2cfcfed89..c2dd79d8112 100644 --- a/mozilla/layout/xul/base/src/nsFrameNavigator.h +++ b/mozilla/layout/xul/base/src/nsFrameNavigator.h @@ -31,16 +31,17 @@ #define nsGrippyFrame_h___ #include "nsIFrame.h" +class nsIBox; class nsFrameNavigator { public: - static nsIFrame* GetChildBeforeAfter(nsIPresContext* aPresContext, nsIFrame* start, PRBool before); - static nsIFrame* GetChildAt(nsIPresContext* aPresContext, nsIFrame* parent, PRInt32 index); - static PRInt32 IndexOf(nsIPresContext* aPresContext, nsIFrame* parent, nsIFrame* child); - static PRInt32 CountFrames(nsIPresContext* aPresContext, nsIFrame* aFrame); - static nsIAtom* GetTag(nsIFrame* frame); + static nsIBox* GetChildBeforeAfter(nsIPresContext* aPresContext, nsIBox* start, PRBool before); + static nsIBox* GetChildAt(nsIPresContext* aPresContext, nsIBox* parent, PRInt32 index); + static PRInt32 IndexOf(nsIPresContext* aPresContext, nsIBox* parent, nsIBox* child); + static PRInt32 CountFrames(nsIPresContext* aPresContext, nsIBox* aFrame); + static nsIAtom* GetTag(nsIBox* frame); }; diff --git a/mozilla/layout/xul/base/src/nsGrippyFrame.cpp b/mozilla/layout/xul/base/src/nsGrippyFrame.cpp index 011d0a5eaf0..7b3823e0b5e 100644 --- a/mozilla/layout/xul/base/src/nsGrippyFrame.cpp +++ b/mozilla/layout/xul/base/src/nsGrippyFrame.cpp @@ -62,7 +62,7 @@ NS_NewGrippyFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } - nsGrippyFrame* it = new (aPresShell) nsGrippyFrame; + nsGrippyFrame* it = new (aPresShell) nsGrippyFrame (aPresShell); if (nsnull == it) return NS_ERROR_OUT_OF_MEMORY; @@ -71,7 +71,7 @@ NS_NewGrippyFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) } // NS_NewGrippyFrame -nsGrippyFrame::nsGrippyFrame():mCollapsed(PR_FALSE) +nsGrippyFrame::nsGrippyFrame(nsIPresShell* aShell):nsTitledButtonFrame(aShell),mCollapsed(PR_FALSE) { } diff --git a/mozilla/layout/xul/base/src/nsGrippyFrame.h b/mozilla/layout/xul/base/src/nsGrippyFrame.h index e2b3690f99d..44ba84184c7 100644 --- a/mozilla/layout/xul/base/src/nsGrippyFrame.h +++ b/mozilla/layout/xul/base/src/nsGrippyFrame.h @@ -47,7 +47,7 @@ public: static nsIFrame* GetChildAt(nsIPresContext* aPresContext, nsIFrame* parent, PRInt32 index); static PRInt32 IndexOf(nsIPresContext* aPresContext, nsIFrame* parent, nsIFrame* child); static PRInt32 CountFrames(nsIPresContext* aPresContext, nsIFrame* aFrame); - nsGrippyFrame(); + nsGrippyFrame(nsIPresShell* aShell); protected: virtual void MouseClicked(nsIPresContext* aPresContext); diff --git a/mozilla/layout/xul/base/src/nsGroupBoxFrame.cpp b/mozilla/layout/xul/base/src/nsGroupBoxFrame.cpp index 73556e852ea..d98ace98fb4 100644 --- a/mozilla/layout/xul/base/src/nsGroupBoxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsGroupBoxFrame.cpp @@ -58,6 +58,9 @@ public: NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList); + + NS_IMETHOD GetBorderAndPadding(nsMargin& aBorderAndPadding); + NS_METHOD Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -81,12 +84,7 @@ public: } #endif - NS_IMETHOD Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); - - virtual PRBool GetInitialOrientation(PRBool& aHorizontal) { aHorizontal = PR_FALSE; return PR_TRUE; } + virtual PRBool GetInitialOrientation(PRBool& aHorizontal) { aHorizontal = PR_FALSE; return PR_TRUE; } nsIFrame* GetTitleFrame(nsIPresContext* aPresContext, nsRect& aRect); nsIFrame* GetContentFrame(nsIPresContext* aPresContext); @@ -321,28 +319,11 @@ nsTitledBoxFrame::GetContentFrame(nsIPresContext* aPresContext) return next; } -NS_IMETHODIMP -nsTitledBoxFrame::Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) +NS_IMETHODIMP +nsTitledBoxFrame::GetBorderAndPadding(nsMargin& aBorderAndPadding) { - if (aReflowState.mComputedBorderPadding.top != 0) - { - nsHTMLReflowState newState(aReflowState); - - if (newState.mComputedHeight != NS_INTRINSICSIZE) - newState.mComputedHeight += aReflowState.mComputedBorderPadding.top; - - // remove the border from border padding - ((nsMargin&)newState.mComputedBorderPadding).top = 0; - ((nsMargin&)newState.mComputedPadding).top = 0; - - // reflow us again with the correct values. - return Reflow(aPresContext, aDesiredSize, newState, aStatus); - } - - return nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + aBorderAndPadding.SizeTo(0,0,0,0); + return NS_OK; } NS_IMETHODIMP diff --git a/mozilla/layout/xul/base/src/nsIBox.h b/mozilla/layout/xul/base/src/nsIBox.h index d4fcf017178..9bf54a08415 100644 --- a/mozilla/layout/xul/base/src/nsIBox.h +++ b/mozilla/layout/xul/base/src/nsIBox.h @@ -31,27 +31,15 @@ #ifndef nsIBox_h___ #define nsIBox_h___ -class nsIPresContext; -class nsIFrame; -struct nsHTMLReflowState; -class nsBoxInfo; +#include "nsISupports.h" +#include "nsIBoxLayout.h" -// {02A560C0-01BF-11d3-B35C-00A0CC3C1CDE} -#define NS_IBOX_IID { 0x2a560c0, 0x1bf, 0x11d3, { 0xb3, 0x5c, 0x0, 0xa0, 0xcc, 0x3c, 0x1c, 0xde } } +class nsBoxLayoutState; +struct nsRect; +struct nsSize; -class nsBoxInfo { -public: - nsSize prefSize; - nsSize minSize; - nsSize maxSize; - PRInt32 flex; - nscoord ascent; - - nsBoxInfo(); - virtual void Clear(); - virtual ~nsBoxInfo(); - -}; +// {162F6B5A-F926-11d3-BA06-001083023C1E} +#define NS_IBOX_IID { 0x162f6b5a, 0xf926, 0x11d3, { 0xba, 0x6, 0x0, 0x10, 0x83, 0x2, 0x3c, 0x1e } } class nsIBox : public nsISupports { @@ -59,19 +47,63 @@ public: static const nsIID& GetIID() { static nsIID iid = NS_IBOX_IID; return iid; } - /** Get the layout information object for this box. It will contains things like flexiblity, - * preferred, min, max sizes. - */ - NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize)=0; + enum Halignment { + hAlign_Left, + hAlign_Right, + hAlign_Center + }; - /** clear any cached layout info about our children. If the child is specifically specified - * then only clear cached layout information for that specific child. If the child is not - * then clear all childrens cached information. - */ - NS_IMETHOD InvalidateCache(nsIFrame* aChild)=0; + enum Valignment { + vAlign_Top, + vAlign_Middle, + vAlign_BaseLine, + vAlign_Bottom + }; + NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)=0; + NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)=0; + NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)=0; + NS_IMETHOD GetFlex(nsBoxLayoutState& aBoxLayoutState, nscoord& aFlex)=0; + NS_IMETHOD GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent)=0; + NS_IMETHOD IsCollapsed(nsBoxLayoutState& aBoxLayoutState, PRBool& aCollapsed)=0; + NS_IMETHOD Collapse(nsBoxLayoutState& aBoxLayoutState)=0; + NS_IMETHOD UnCollapse(nsBoxLayoutState& aBoxLayoutState)=0; + NS_IMETHOD SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect)=0; + NS_IMETHOD GetBounds(nsRect& aRect)=0; + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState)=0; + NS_IMETHOD IsDirty(PRBool& aIsDirty)=0; + NS_IMETHOD HasDirtyChildren(PRBool& aIsDirty)=0; + NS_IMETHOD MarkDirty(nsBoxLayoutState& aState)=0; + NS_IMETHOD MarkDirtyChildren(nsBoxLayoutState& aState)=0; + NS_IMETHOD SetDebug(nsBoxLayoutState& aState, PRBool aDebug)=0; + NS_IMETHOD GetDebug(PRBool& aDebug)=0; + NS_IMETHOD GetChildBox(nsIBox** aBox)=0; + NS_IMETHOD GetNextBox(nsIBox** aBox)=0; + NS_IMETHOD SetNextBox(nsIBox* aBox)=0; + NS_IMETHOD GetParentBox(nsIBox** aParent)=0; + NS_IMETHOD SetParentBox(nsIBox* aParent)=0; + NS_IMETHOD GetFrame(nsIFrame** aFrame)=0; + NS_IMETHOD GetBorderAndPadding(nsMargin& aBorderAndPadding)=0; + NS_IMETHOD GetBorder(nsMargin& aBorderAndPadding)=0; + NS_IMETHOD GetPadding(nsMargin& aBorderAndPadding)=0; + NS_IMETHOD GetInset(nsMargin& aInset)=0; + NS_IMETHOD GetMargin(nsMargin& aMargin)=0; + NS_IMETHOD SetLayoutManager(nsIBoxLayout* aLayout)=0; + NS_IMETHOD GetLayoutManager(nsIBoxLayout** aLayout)=0; + NS_IMETHOD GetContentRect(nsRect& aContentRect) = 0; + NS_IMETHOD GetClientRect(nsRect& aContentRect) = 0; + NS_IMETHOD GetVAlign(Valignment& aAlign) = 0; + NS_IMETHOD GetHAlign(Halignment& aAlign) = 0; + NS_IMETHOD GetOrientation(PRBool& aIsHorizontal)=0; + NS_IMETHOD Redraw(nsBoxLayoutState& aState, const nsRect* aRect = nsnull, PRBool aImmediate = PR_FALSE)=0; + NS_IMETHOD NeedsRecalc()=0; + NS_IMETHOD GetDebugBoxAt(const nsPoint& aPoint, nsIBox** aBox)=0; - NS_IMETHOD SetDebug(nsIPresContext* aPresContext, PRBool aDebug)=0; + static PRBool AddCSSPrefSize(nsBoxLayoutState& aState, nsIBox* aBox, nsSize& aSize); + static PRBool AddCSSMinSize(nsBoxLayoutState& aState, nsIBox* aBox, nsSize& aSize); + static PRBool AddCSSMaxSize(nsBoxLayoutState& aState, nsIBox* aBox, nsSize& aSize); + static PRBool AddCSSFlex(nsBoxLayoutState& aState, nsIBox* aBox, nscoord& aFlex); + static PRBool AddCSSCollapsed(nsBoxLayoutState& aState, nsIBox* aBox, PRBool& aCollapsed); }; diff --git a/mozilla/layout/xul/base/src/nsImageBoxFrame.cpp b/mozilla/layout/xul/base/src/nsImageBoxFrame.cpp new file mode 100644 index 00000000000..bace61922ee --- /dev/null +++ b/mozilla/layout/xul/base/src/nsImageBoxFrame.cpp @@ -0,0 +1,447 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +// +// Eric Vaughan +// Netscape Communications +// +// See documentation in associated header file +// + +#include "nsImageBoxFrame.h" +#include "nsIDeviceContext.h" +#include "nsIFontMetrics.h" +#include "nsHTMLAtoms.h" +#include "nsXULAtoms.h" +#include "nsIStyleContext.h" +#include "nsStyleConsts.h" +#include "nsCOMPtr.h" +#include "nsIPresContext.h" +#include "nsButtonFrameRenderer.h" +#include "nsBoxLayoutState.h" + +#include "nsHTMLParts.h" +#include "nsString.h" +#include "nsLeafFrame.h" +#include "nsIPresContext.h" +#include "nsIRenderingContext.h" +#include "nsIPresShell.h" +#include "nsHTMLIIDs.h" +#include "nsIImage.h" +#include "nsIWidget.h" +#include "nsHTMLAtoms.h" +#include "nsIHTMLAttributes.h" +#include "nsIDocument.h" +#include "nsIHTMLDocument.h" +#include "nsIStyleContext.h" +#include "nsStyleConsts.h" +#include "nsImageMap.h" +#include "nsILinkHandler.h" +#include "nsIURL.h" +#include "nsIView.h" +#include "nsIViewManager.h" +#include "nsHTMLContainerFrame.h" +#include "prprf.h" +#include "nsISizeOfHandler.h" +#include "nsIFontMetrics.h" +#include "nsCSSRendering.h" +#include "nsIDOMHTMLImageElement.h" +#include "nsIDeviceContext.h" +#include "nsINameSpaceManager.h" +#include "nsTextFragment.h" +#include "nsIDOMHTMLMapElement.h" +#include "nsIStyleSet.h" +#include "nsIStyleContext.h" +#include "nsBoxLayoutState.h" + +#include "nsFormControlHelper.h" + +#define ONLOAD_CALLED_TOO_EARLY 1 + +nsresult +nsImageBoxFrame::UpdateImageFrame(nsIPresContext* aPresContext, + nsHTMLImageLoader* aLoader, + nsIFrame* aFrame, + void* aClosure, + PRUint32 aStatus) +{ + if (NS_IMAGE_LOAD_STATUS_SIZE_AVAILABLE & aStatus) { + nsImageBoxFrame* us = (nsImageBoxFrame*)aFrame; + nsBoxLayoutState state(aPresContext); + us->MarkDirty(state); + } + return NS_OK; +} + +// +// NS_NewToolbarFrame +// +// Creates a new Toolbar frame and returns it in |aNewFrame| +// +nsresult +NS_NewImageBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) +{ + NS_PRECONDITION(aNewFrame, "null OUT ptr"); + if (nsnull == aNewFrame) { + return NS_ERROR_NULL_POINTER; + } + nsImageBoxFrame* it = new (aPresShell) nsImageBoxFrame (aPresShell); + if (nsnull == it) + return NS_ERROR_OUT_OF_MEMORY; + + *aNewFrame = it; + return NS_OK; + +} // NS_NewTitledButtonFrame + +NS_IMETHODIMP +nsImageBoxFrame::AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aHint) +{ + PRBool aResize; + PRBool aRedraw; + UpdateAttributes(aPresContext, aAttribute, aResize, aRedraw); + + nsBoxLayoutState state(aPresContext); + + if (aResize) { + MarkDirty(state); + } else if (aRedraw) { + Redraw(state); + } + + return NS_OK; +} + +nsImageBoxFrame::nsImageBoxFrame(nsIPresShell* aShell):nsLeafBoxFrame(aShell) +{ + mSizeFrozen = PR_FALSE; + mHasImage = PR_FALSE; + NeedsRecalc(); +} + +nsImageBoxFrame::~nsImageBoxFrame() +{ +} + + +NS_IMETHODIMP +nsImageBoxFrame::NeedsRecalc() +{ + SizeNeedsRecalc(mImageSize); + return NS_OK; +} + +NS_METHOD +nsImageBoxFrame::Destroy(nsIPresContext* aPresContext) +{ + // Release image loader first so that it's refcnt can go to zero + mImageLoader.StopAllLoadImages(aPresContext); + + return nsLeafBoxFrame::Destroy(aPresContext); +} + + +NS_IMETHODIMP +nsImageBoxFrame::Init(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) +{ + nsresult rv = nsLeafBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); + + mHasImage = PR_FALSE; + + // Always set the image loader's base URL, because someone may + // decide to change a button _without_ an image to have an image + // later. + nsIURI* baseURL = nsnull; + nsIHTMLContent* htmlContent; + if (NS_SUCCEEDED(mContent->QueryInterface(kIHTMLContentIID, (void**)&htmlContent))) { + htmlContent->GetBaseURL(baseURL); + NS_RELEASE(htmlContent); + } + else { + nsIDocument* doc; + if (NS_SUCCEEDED(mContent->GetDocument(doc))) { + doc->GetBaseURL(baseURL); + NS_RELEASE(doc); + } + } + + // Initialize the image loader. Make sure the source is correct so + // that UpdateAttributes doesn't double start an image load. + nsAutoString src; + GetImageSource(src); + if (!src.Equals("")) { + mHasImage = PR_TRUE; + } + mImageLoader.Init(this, UpdateImageFrame, nsnull, baseURL, src); + NS_IF_RELEASE(baseURL); + + PRBool a,b; + UpdateAttributes(aPresContext, nsnull, a, b); + + return rv; +} + +void +nsImageBoxFrame::GetImageSource(nsString& aResult) +{ + // get the new image src + mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::src, aResult); + + // if the new image is empty + if (aResult.Equals("")) { + // get the list-style-image + const nsStyleList* myList = + (const nsStyleList*)mStyleContext->GetStyleData(eStyleStruct_List); + + if (myList->mListStyleImage.Length() > 0) { + aResult = myList->mListStyleImage; + } + } +} + +void +nsImageBoxFrame::UpdateAttributes(nsIPresContext* aPresContext, nsIAtom* aAttribute, PRBool& aResize, PRBool& aRedraw) +{ + aResize = PR_FALSE; + aRedraw = PR_FALSE; + + if (aAttribute == nsnull || aAttribute == nsHTMLAtoms::src) { + UpdateImage(aPresContext, aResize); + } +} + +void +nsImageBoxFrame::UpdateImage(nsIPresContext* aPresContext, PRBool& aResize) +{ + aResize = PR_FALSE; + + // see if the source changed + // get the old image src + nsAutoString oldSrc =""; + mImageLoader.GetURLSpec(oldSrc); + + // get the new image src + nsAutoString src; + GetImageSource(src); + + // see if the images are different + if (!oldSrc.Equals(src)) { + + if (!src.Equals("")) { + mSizeFrozen = PR_FALSE; + mHasImage = PR_TRUE; + } else { + mSizeFrozen = PR_TRUE; + mHasImage = PR_FALSE; + } + + mImageLoader.UpdateURLSpec(aPresContext, src); + + aResize = PR_TRUE; + } +} + +NS_IMETHODIMP +nsImageBoxFrame::Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + const nsStyleDisplay* disp = (const nsStyleDisplay*) + mStyleContext->GetStyleData(eStyleStruct_Display); + if (!disp->IsVisible()) + return NS_OK; + + nsresult rv = nsLeafBoxFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + + nsRect rect (0,0, mRect.width, mRect.height); + PaintImage(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + + return rv; +} + + +NS_IMETHODIMP +nsImageBoxFrame::PaintImage(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + if ((0 == mRect.width) || (0 == mRect.height)) { + // Do not render when given a zero area. This avoids some useless + // scaling work while we wait for our image dimensions to arrive + // asynchronously. + return NS_OK; + } + + nsRect rect; + GetClientRect(rect); + + // don't draw if the image is not dirty + if (!mHasImage || !aDirtyRect.Intersects(rect)) + return NS_OK; + + if (NS_FRAME_PAINT_LAYER_FOREGROUND != aWhichLayer) + return NS_OK; + + nsCOMPtr image ( dont_AddRef(mImageLoader.GetImage()) ); + if ( !image ) { + } + else { + // Now render the image into our content area (the area inside the + // borders and padding) + aRenderingContext.DrawImage(image, rect); + } + + return NS_OK; +} + + +// +// DidSetStyleContext +// +// When the style context changes, make sure that all of our image is up to date. +// +NS_IMETHODIMP +nsImageBoxFrame :: DidSetStyleContext( nsIPresContext* aPresContext ) +{ + // if list-style-image change we want to change the image + PRBool aResize; + UpdateImage(aPresContext, aResize); + + return NS_OK; + +} // DidSetStyleContext + +void +nsImageBoxFrame::GetImageSize(nsIPresContext* aPresContext) +{ + nsSize s(0,0); + nsHTMLReflowMetrics desiredSize(&s); + const PRInt32 kDefaultSize = 0; + float p2t; + aPresContext->GetScaledPixelsToTwips(&p2t); + const PRInt32 kDefaultSizeInTwips = NSIntPixelsToTwips(kDefaultSize, p2t); + +// not calculated? Get the intrinsic size + if (mHasImage) { + // get the size of the image and set the desired size + if (mSizeFrozen) { + mImageSize.width = kDefaultSizeInTwips; + mImageSize.height = kDefaultSizeInTwips; + return; + } else { + // Ask the image loader for the *intrinsic* image size + mImageLoader.GetDesiredSize(aPresContext, nsnull, desiredSize); + + if (desiredSize.width == 1 || desiredSize.height == 1) + { + mImageSize.width = kDefaultSizeInTwips; + mImageSize.height = kDefaultSizeInTwips; + return; + } + } + } + + mImageSize.width = desiredSize.width; + mImageSize.height = desiredSize.height; +} + + +/** + * Ok return our dimensions + */ +NS_IMETHODIMP +nsImageBoxFrame::Layout(nsBoxLayoutState& aState) +{ + return nsLeafBoxFrame::Layout(aState); +} + +/** + * Ok return our dimensions + */ +NS_IMETHODIMP +nsImageBoxFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) +{ + if (DoesNeedRecalc(mImageSize)) { + CacheImageSize(aState); + } + + aSize = mImageSize; + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSPrefSize(aState, this, aSize); + + return NS_OK; +} + +/** + * Ok return our dimensions + */ +NS_IMETHODIMP +nsImageBoxFrame::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize) +{ + if (DoesNeedRecalc(mImageSize)) { + CacheImageSize(aState); + } + + aSize = mImageSize; + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSMinSize(aState, this, aSize); + + return NS_OK; +} + +NS_IMETHODIMP +nsImageBoxFrame::GetAscent(nsBoxLayoutState& aState, nscoord& aCoord) +{ + nsSize size(0,0); + GetPrefSize(aState, size); + aCoord = size.height; + return NS_OK; +} + +/** + * Ok return our dimensions + */ +void +nsImageBoxFrame::CacheImageSize(nsBoxLayoutState& aState) +{ + nsIPresContext* presContext = aState.GetPresContext(); + GetImageSize(presContext); +} + +NS_IMETHODIMP +nsImageBoxFrame::GetFrameName(nsString& aResult) const +{ + aResult = "ImageBox"; + return NS_OK; +} diff --git a/mozilla/layout/xul/base/src/nsImageBoxFrame.h b/mozilla/layout/xul/base/src/nsImageBoxFrame.h new file mode 100644 index 00000000000..d99bc3843aa --- /dev/null +++ b/mozilla/layout/xul/base/src/nsImageBoxFrame.h @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ +#ifndef nsImageBoxFrame_h___ +#define nsImageBoxFrame_h___ + +#include "nsHTMLImageLoader.h" +#include "nsLeafBoxFrame.h" + +class nsImageBoxFrame : public nsLeafBoxFrame +{ +public: + + // nsIBox + NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent); + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); + NS_IMETHOD NeedsRecalc(); + + friend nsresult NS_NewImageBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); + + // nsIBox frame interface + + NS_IMETHOD Init(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* asPrevInFlow); + + NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aHint); + + NS_IMETHOD DidSetStyleContext (nsIPresContext* aPresContext); + + NS_IMETHOD Destroy(nsIPresContext* aPresContext); + + NS_IMETHOD GetFrameName(nsString& aResult) const; + + virtual void UpdateAttributes(nsIPresContext* aPresContext, nsIAtom* aAttribute, PRBool& aResize, PRBool& aRedraw); + virtual void UpdateImage(nsIPresContext* aPresContext, PRBool& aResize); + + + NS_IMETHOD Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + + ~nsImageBoxFrame(); +protected: + + void CacheImageSize(nsBoxLayoutState& aBoxLayoutState); + + + NS_IMETHOD PaintImage(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + + nsImageBoxFrame(nsIPresShell* aShell); + + static nsresult UpdateImageFrame(nsIPresContext* aPresContext, + nsHTMLImageLoader* aLoader, + nsIFrame* aFrame, + void* aClosure, + PRUint32 aStatus); + + void GetImageSource(nsString& aResult); + + virtual void GetImageSize(nsIPresContext* aPresContext); + +private: + + nsHTMLImageLoader mImageLoader; + PRBool mSizeFrozen; + nsSize mImageSize; + PRBool mHasImage; + +}; // class nsImageBoxFrame + +#endif /* nsImageBoxFrame_h___ */ diff --git a/mozilla/layout/xul/base/src/nsLeafBoxFrame.cpp b/mozilla/layout/xul/base/src/nsLeafBoxFrame.cpp new file mode 100644 index 00000000000..5c8cf3ddeae --- /dev/null +++ b/mozilla/layout/xul/base/src/nsLeafBoxFrame.cpp @@ -0,0 +1,246 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +// +// Eric Vaughan +// Netscape Communications +// +// See documentation in associated header file +// + +#include "nsLeafBoxFrame.h" +#include "nsBoxFrame.h" +#include "nsCOMPtr.h" +#include "nsIDeviceContext.h" +#include "nsIFontMetrics.h" +#include "nsHTMLAtoms.h" +#include "nsXULAtoms.h" +#include "nsIPresContext.h" +#include "nsIRenderingContext.h" +#include "nsIStyleContext.h" +#include "nsIContent.h" +#include "nsINameSpaceManager.h" +#include "nsBoxLayoutState.h" + +// +// NS_NewToolbarFrame +// +// Creates a new Toolbar frame and returns it in |aNewFrame| +// +nsresult +NS_NewLeafBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) +{ + NS_PRECONDITION(aNewFrame, "null OUT ptr"); + if (nsnull == aNewFrame) { + return NS_ERROR_NULL_POINTER; + } + nsLeafBoxFrame* it = new (aPresShell) nsLeafBoxFrame(aPresShell); + if (nsnull == it) + return NS_ERROR_OUT_OF_MEMORY; + + // it->SetFlags(aFlags); + *aNewFrame = it; + return NS_OK; + +} // NS_NewTextFrame + +nsLeafBoxFrame::nsLeafBoxFrame(nsIPresShell* aShell):nsBox(aShell) +{ +} + +/** + * Initialize us. This is a good time to get the alignment of the box + */ +NS_IMETHODIMP +nsLeafBoxFrame::Init(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) +{ + nsresult rv = nsLeafFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); + + mMouseThrough = sometimes; + + if (mContent) { + nsAutoString value; + if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::mousethrough, value)) { + if (value.EqualsIgnoreCase("never")) + mMouseThrough = never; + else if (value.EqualsIgnoreCase("always")) + mMouseThrough = always; + + } + } + + return rv; +} + +NS_IMETHODIMP +nsLeafBoxFrame::GetFrameForPoint(nsIPresContext* aPresContext, + const nsPoint& aPoint, + nsFramePaintLayer aWhichLayer, + nsIFrame** aFrame) +{ + if (!mRect.Contains(aPoint)) + return NS_ERROR_FAILURE; + + if (mMouseThrough != never) + { + *aFrame = this; + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsLeafBoxFrame::GetFrame(nsIFrame** aFrame) +{ + *aFrame = this; + return NS_OK; +} + +NS_IMETHODIMP +nsLeafBoxFrame::DidReflow(nsIPresContext* aPresContext, + nsDidReflowStatus aStatus) +{ + PRBool isDirty = mState & NS_FRAME_IS_DIRTY; + PRBool hasDirtyChildren = mState & NS_FRAME_HAS_DIRTY_CHILDREN; + nsresult rv = nsFrame::DidReflow(aPresContext, aStatus); + if (isDirty) + mState |= NS_FRAME_IS_DIRTY; + + if (hasDirtyChildren) + mState |= NS_FRAME_HAS_DIRTY_CHILDREN; + + return rv; + +} + + +NS_IMETHODIMP +nsLeafBoxFrame::Reflow(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + NS_ASSERTION(aReflowState.mComputedWidth >=0 && aReflowState.mComputedHeight >= 0, "Computed Size < 0"); + + aStatus = NS_FRAME_COMPLETE; + + // create the layout state + nsBoxLayoutState state(aPresContext, aReflowState); + + state.HandleReflow(this, PR_FALSE); + + nsSize computedSize(aReflowState.mComputedWidth,aReflowState.mComputedHeight); + + nsMargin m; + GetBorderAndPadding(m); + + // this happens sometimes. So lets handle it gracefully. + if (aReflowState.mComputedHeight == 0) { + nsSize minSize(0,0); + GetMinSize(state, minSize); + computedSize.height = minSize.height - m.top - m.bottom; + } + + // if we are told to layout intrinic then get our preferred size. + if (computedSize.width == NS_INTRINSICSIZE || computedSize.height == NS_INTRINSICSIZE) { + nsSize prefSize; + nsSize minSize; + nsSize maxSize; + GetPrefSize(state, prefSize); + GetMinSize(state, minSize); + GetMaxSize(state, maxSize); + BoundsCheck(minSize, prefSize, maxSize); + + // get our desiredSize + if (aReflowState.mComputedWidth == NS_INTRINSICSIZE) + computedSize.width = prefSize.width - m.left - m.right; + + if (aReflowState.mComputedHeight == NS_INTRINSICSIZE || aReflowState.mComputedHeight == 0) + computedSize.height = prefSize.height - m.top - m.bottom; + } + + nsRect r(0,0,computedSize.width, computedSize.height); + r.Inflate(m); + r.x = mRect.x; + r.y = mRect.y; + + SetBounds(state, r); + + // layout our children + Layout(state); + + // ok our child could have gotten bigger. So lets get its bounds + GetBounds(r); + + // get the ascent + nscoord ascent; + GetAscent(state, ascent); + + aDesiredSize.width = r.width; + aDesiredSize.height = r.height; + aDesiredSize.ascent = ascent; + aDesiredSize.descent = 0; + + return NS_OK; +} + +NS_IMETHODIMP +nsLeafBoxFrame::GetFrameName(nsString& aResult) const +{ + aResult = "LeafBox"; + return NS_OK; +} + +NS_IMETHODIMP_(nsrefcnt) +nsLeafBoxFrame::AddRef(void) +{ + return NS_OK; +} + +NS_IMETHODIMP_(nsrefcnt) +nsLeafBoxFrame::Release(void) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsLeafBoxFrame::ContentChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + nsISupports* aSubContent) +{ + NeedsRecalc(); + return nsLeafFrame::ContentChanged(aPresContext, aChild, aSubContent); +} + + +NS_INTERFACE_MAP_BEGIN(nsLeafBoxFrame) + NS_INTERFACE_MAP_ENTRY(nsIBox) +#ifdef NS_DEBUG + NS_INTERFACE_MAP_ENTRY(nsIFrameDebug) +#endif + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBox) +NS_INTERFACE_MAP_END_INHERITING(nsLeafFrame) \ No newline at end of file diff --git a/mozilla/layout/xul/base/src/nsXULLeafFrame.h b/mozilla/layout/xul/base/src/nsLeafBoxFrame.h similarity index 63% rename from mozilla/layout/xul/base/src/nsXULLeafFrame.h rename to mozilla/layout/xul/base/src/nsLeafBoxFrame.h index f919e9c3500..9938e926e5a 100644 --- a/mozilla/layout/xul/base/src/nsXULLeafFrame.h +++ b/mozilla/layout/xul/base/src/nsLeafBoxFrame.h @@ -19,27 +19,24 @@ * * Contributor(s): */ -#ifndef nsXULLeafFrame_h___ -#define nsXULLeafFrame_h___ +#ifndef nsLeafBoxFrame_h___ +#define nsLeafBoxFrame_h___ #include "nsLeafFrame.h" -#include "nsIBox.h" +#include "nsBox.h" class nsAccessKeyInfo; -class nsXULLeafFrame : public nsLeafFrame, public nsIBox +class nsLeafBoxFrame : public nsLeafFrame, public nsBox { public: - friend nsresult NS_NewXULLeafFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); - - // nsIBox frame interface - NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); - NS_IMETHOD InvalidateCache(nsIFrame* aChild); - NS_IMETHOD SetDebug(nsIPresContext* aPresContext, PRBool aDebug) { return NS_OK; } + friend nsresult NS_NewLeafBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); NS_DECL_ISUPPORTS + // nsIBox frame interface + NS_IMETHOD GetFrame(nsIFrame** aFrame); NS_IMETHOD GetFrameName(nsString& aResult) const; @@ -48,23 +45,35 @@ public: nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); - - NS_IMETHOD ContentChanged(nsIPresContext* aPresContext, + + NS_IMETHOD ContentChanged(nsIPresContext* aPresContext, nsIContent* aChild, nsISupports* aSubContent); + NS_IMETHOD DidReflow(nsIPresContext* aPresContext, + nsDidReflowStatus aStatus); + + NS_IMETHOD Init(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* asPrevInFlow); + + NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, + const nsPoint& aPoint, + nsFramePaintLayer aWhichLayer, + nsIFrame** aFrame); protected: virtual void GetDesiredSize(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, - nsHTMLReflowMetrics& aDesiredSize); + nsHTMLReflowMetrics& aDesiredSize) {} - - nsXULLeafFrame() {} + nsLeafBoxFrame(nsIPresShell* aShell); private: -}; // class nsXULLeafFrame +}; // class nsLeafBoxFrame -#endif /* nsXULLeafFrame_h___ */ +#endif /* nsLeafBoxFrame_h___ */ diff --git a/mozilla/layout/xul/base/src/nsMenuFrame.cpp b/mozilla/layout/xul/base/src/nsMenuFrame.cpp index ab1a2b017d6..ffdc6f2fa91 100644 --- a/mozilla/layout/xul/base/src/nsMenuFrame.cpp +++ b/mozilla/layout/xul/base/src/nsMenuFrame.cpp @@ -55,6 +55,7 @@ #include "nsILookAndFeel.h" #include "nsIComponentManager.h" #include "nsWidgetsCID.h" +#include "nsBoxLayoutState.h" #define NS_MENU_POPUP_LIST_INDEX (NS_AREA_FRAME_ABSOLUTE_LIST_INDEX + 1) @@ -217,12 +218,13 @@ nsMenuFrame::Destroy(nsIPresContext* aPresContext) NS_IMETHODIMP nsMenuFrame::GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, - nsFramePaintLayer aWhichLayer, + nsFramePaintLayer aWhichLayer, nsIFrame** aFrame) { - if (!mRect.Contains(aPoint)) { - return NS_ERROR_FAILURE; - } + // if it is not inside us or not in the layer in which we paint, fail + if (!mRect.Contains(aPoint)) + return NS_ERROR_FAILURE; + nsresult result = nsBoxFrame::GetFrameForPoint(aPresContext, aPoint, aWhichLayer, aFrame); if ((result != NS_OK) || (*aFrame == this)) { return result; @@ -665,6 +667,53 @@ nsMenuFrame::GetMenuChildrenElement(nsIContent** aResult) } } +NS_IMETHODIMP +nsMenuFrame::Layout(nsBoxLayoutState& aState) +{ + nsRect contentRect; + GetContentRect(contentRect); + + // lay us out + nsresult rv = nsBoxFrame::Layout(aState); + + // layout the popup. First we need to get it. + nsIFrame* popupChild = mPopupFrames.FirstChild(); + + if (popupChild) { + nsCOMPtr menulist = do_QueryInterface(mContent); + + nsIBox* ibox = nsnull; + nsresult rv2 = popupChild->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox); + NS_ASSERTION(NS_SUCCEEDED(rv2) && ibox,"popupChild is not box!!"); + + // then get its preferred size + nsSize prefSize(0,0); + nsSize minSize(0,0); + nsSize maxSize(0,0); + + ibox->GetPrefSize(aState, prefSize); + ibox->GetMinSize(aState, minSize); + ibox->GetMaxSize(aState, maxSize); + + BoundsCheck(minSize, prefSize, maxSize); + + AddMargin(ibox, prefSize); + + if (menulist && prefSize.width < contentRect.width) + prefSize.width = contentRect.width; + + // lay it out + LayoutChildAt(aState, ibox, nsRect(0,0,prefSize.width, prefSize.height)); + } + + SyncLayout(aState); + + LayoutFinished(aState); + + return rv; +} + +/** Replaced by Layout NS_IMETHODIMP nsMenuFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -777,9 +826,10 @@ nsMenuFrame::Reflow(nsIPresContext* aPresContext, } return rv; } +*/ NS_IMETHODIMP -nsMenuFrame::SetDebug(nsIPresContext* aPresContext, PRBool aDebug) +nsMenuFrame::SetDebug(nsBoxLayoutState& aState, PRBool aDebug) { // see if our state matches the given debug state PRBool debugSet = mState & NS_STATE_CURRENTLY_IN_DEBUG; @@ -788,15 +838,15 @@ nsMenuFrame::SetDebug(nsIPresContext* aPresContext, PRBool aDebug) // if it doesn't then tell each child below us the new debug state if (debugChanged) { - nsBoxFrame::SetDebug(aPresContext, aDebug); - SetDebug(aPresContext, mPopupFrames.FirstChild(), aDebug); + nsBoxFrame::SetDebug(aState, aDebug); + SetDebug(aState, mPopupFrames.FirstChild(), aDebug); } return NS_OK; } nsresult -nsMenuFrame::SetDebug(nsIPresContext* aPresContext, nsIFrame* aList, PRBool aDebug) +nsMenuFrame::SetDebug(nsBoxLayoutState& aState, nsIFrame* aList, PRBool aDebug) { if (!aList) return NS_OK; @@ -804,7 +854,7 @@ nsMenuFrame::SetDebug(nsIPresContext* aPresContext, nsIFrame* aList, PRBool aDeb while (aList) { nsIBox* ibox = nsnull; if (NS_SUCCEEDED(aList->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) { - ibox->SetDebug(aPresContext, aDebug); + ibox->SetDebug(aState, aDebug); } aList->GetNextSibling(&aList); @@ -814,13 +864,9 @@ nsMenuFrame::SetDebug(nsIPresContext* aPresContext, nsIFrame* aList, PRBool aDeb } -NS_IMETHODIMP -nsMenuFrame::DidReflow(nsIPresContext* aPresContext, - nsDidReflowStatus aStatus) -{ - nsresult rv; - rv = nsBoxFrame::DidReflow(aPresContext, aStatus); - +void +nsMenuFrame::LayoutFinished(nsBoxLayoutState& aState) +{ // Sync up the view. nsIFrame* frame = mPopupFrames.FirstChild(); nsMenuPopupFrame* menuPopup = (nsMenuPopupFrame*)frame; @@ -849,10 +895,10 @@ nsMenuFrame::DidReflow(nsIPresContext* aPresContext, popupAlign = "topleft"; } - menuPopup->SyncViewWithFrame(aPresContext, popupAnchor, popupAlign, this, -1, -1); + nsIPresContext* presContext = aState.GetPresContext(); + menuPopup->SyncViewWithFrame(presContext, popupAnchor, popupAlign, this, -1, -1); } - return rv; } NS_IMETHODIMP @@ -1088,6 +1134,12 @@ nsMenuFrame::UpdateMenuSpecialState(nsIPresContext* aPresContext) { } +NS_IMETHODIMP +nsMenuFrame::CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aAnonymousChildren) +{ + return NS_OK; +} + void nsMenuFrame::BuildAcceleratorText(nsString& aAccelString) { @@ -1295,7 +1347,8 @@ nsMenuFrame::RemoveFrame(nsIPresContext* aPresContext, if (mPopupFrames.ContainsFrame(aOldFrame)) { // Go ahead and remove this frame. mPopupFrames.DestroyFrame(aPresContext, aOldFrame); - rv = GenerateDirtyReflowCommand(aPresContext, aPresShell); + nsBoxLayoutState state(aPresContext); + rv = MarkDirtyChildren(state); } else { rv = nsBoxFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); } @@ -1319,8 +1372,9 @@ nsMenuFrame::InsertFrames(nsIPresContext* aPresContext, frameChild->GetTag(*getter_AddRefs(tag)); if (tag && tag.get() == nsXULAtoms::menupopup) { mPopupFrames.InsertFrames(nsnull, nsnull, aFrameList); - SetDebug(aPresContext, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG); - rv = GenerateDirtyReflowCommand(aPresContext, aPresShell); + nsBoxLayoutState state(aPresContext); + SetDebug(state, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG); + rv = MarkDirtyChildren(state); } else { rv = nsBoxFrame::InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList); } @@ -1346,8 +1400,9 @@ nsMenuFrame::AppendFrames(nsIPresContext* aPresContext, frameChild->GetTag(*getter_AddRefs(tag)); if (tag && tag.get() == nsXULAtoms::menupopup) { mPopupFrames.AppendFrames(nsnull, aFrameList); - SetDebug(aPresContext, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG); - rv = GenerateDirtyReflowCommand(aPresContext, aPresShell); + nsBoxLayoutState state(aPresContext); + SetDebug(state, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG); + rv = MarkDirtyChildren(state); } else { rv = nsBoxFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList); } @@ -1370,14 +1425,69 @@ nsMenuFrame::UpdateDismissalListener(nsIMenuParent* aMenuParent) nsMenuFrame::mDismissalListener->SetCurrentMenuParent(aMenuParent); } +NS_IMETHODIMP +nsMenuFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) +{ + aSize.width = 0; + aSize.height = 0; + nsresult rv = nsBoxFrame::GetPrefSize(aState, aSize); + + nsCOMPtr menulist(do_QueryInterface(mContent)); + if (menulist) { + nsCOMPtr element; + menulist->GetSelectedItem(getter_AddRefs(element)); + if (!element) { + nsAutoString value; + menulist->GetValue(value); + if (value == "") { + nsCOMPtr child; + GetMenuChildrenElement(getter_AddRefs(child)); + if (child) { + PRInt32 count; + child->ChildCount(count); + if (count > 0) { + nsCOMPtr item; + child->ChildAt(0, *getter_AddRefs(item)); + nsCOMPtr selectedElement(do_QueryInterface(item)); + if (selectedElement) + menulist->SetSelectedItem(selectedElement); + } + } + } + } + + nsSize tmpSize(-1,0); + nsIBox::AddCSSPrefSize(aState, this, tmpSize); + nscoord flex; + GetFlex(aState, flex); + + if (tmpSize.width == -1 && flex==0) { + nsIFrame* frame = mPopupFrames.FirstChild(); + if (!frame) { + MarkAsGenerated(); + frame = mPopupFrames.FirstChild(); + } + + nsIBox* ibox = nsnull; + nsresult rv2 = frame->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox); + NS_ASSERTION(NS_SUCCEEDED(rv2) && ibox,"popupChild is not box!!"); + + ibox->GetPrefSize(aState, tmpSize); + aSize.width = tmpSize.width; + } + } + + return rv; +} + +/* Need to figure out what this does. NS_IMETHODIMP nsMenuFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize) { nsresult rv = nsBoxFrame::GetBoxInfo(aPresContext, aReflowState, aSize); nsCOMPtr menulist(do_QueryInterface(mContent)); if (menulist) { - nsCalculatedBoxInfo boxInfo; - boxInfo.frame = this; + nsCalculatedBoxInfo boxInfo(this); boxInfo.prefSize.width = NS_UNCONSTRAINEDSIZE; boxInfo.prefSize.height = NS_UNCONSTRAINEDSIZE; boxInfo.flex = 0; @@ -1392,8 +1502,7 @@ nsMenuFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& a } nsCOMPtr box(do_QueryInterface(frame)); - nsCalculatedBoxInfo childInfo; - childInfo.frame = frame; + nsCalculatedBoxInfo childInfo(frame); box->GetBoxInfo(aPresContext, aReflowState, childInfo); GetRedefinedMinPrefMax(aPresContext, this, childInfo); aSize.prefSize.width = childInfo.prefSize.width; @@ -1406,4 +1515,5 @@ nsMenuFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& a } return rv; } +*/ diff --git a/mozilla/layout/xul/base/src/nsMenuFrame.h b/mozilla/layout/xul/base/src/nsMenuFrame.h index 23d77c010d8..14ddae112dc 100644 --- a/mozilla/layout/xul/base/src/nsMenuFrame.h +++ b/mozilla/layout/xul/base/src/nsMenuFrame.h @@ -58,6 +58,13 @@ public: nsMenuFrame(nsIPresShell* aShell); NS_DECL_ISUPPORTS + + // nsIBox + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); + NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + + // The nsIAnonymousContentCreator interface + NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aAnonymousItems); // The nsITimerCallback interface NS_IMETHOD_(void) Notify(nsITimer *timer); @@ -68,7 +75,7 @@ public: nsIStyleContext* aContext, nsIFrame* aPrevInFlow); - NS_IMETHOD SetDebug(nsIPresContext* aPresContext, PRBool aDebug); + NS_IMETHOD SetDebug(nsBoxLayoutState& aState, PRBool aDebug); NS_IMETHOD IsActive(PRBool& aResult) { aResult = PR_TRUE; return NS_OK; }; @@ -87,22 +94,14 @@ public: // Overridden to prevent events from ever going to children of the menu. NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, - const nsPoint& aPoint, - nsFramePaintLayer aWhichLayer, + const nsPoint& aPoint, + nsFramePaintLayer aWhichLayer, nsIFrame** aFrame); NS_IMETHOD HandleEvent(nsIPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus); - // Reflow methods - NS_IMETHOD Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); - NS_IMETHOD DidReflow(nsIPresContext* aPresContext, - nsDidReflowStatus aStatus); - NS_IMETHOD AppendFrames(nsIPresContext* aPresContext, nsIPresShell& aPresShell, nsIAtom* aListName, @@ -161,6 +160,9 @@ public: protected: + + virtual void LayoutFinished(nsBoxLayoutState& aState); + static void UpdateDismissalListener(nsIMenuParent* aMenuParent); void UpdateMenuType(nsIPresContext* aPresContext); void UpdateMenuSpecialState(nsIPresContext* aPresContext); @@ -185,10 +187,9 @@ protected: PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRInt32 aHint); - NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); protected: - nsresult SetDebug(nsIPresContext* aPresContext, nsIFrame* aList, PRBool aDebug); + nsresult SetDebug(nsBoxLayoutState& aState, nsIFrame* aList, PRBool aDebug); nsFrameList mPopupFrames; PRPackedBool mIsMenu; // Whether or not we can even have children or not. diff --git a/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp b/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp index a9fab278e91..49cd9b6121f 100644 --- a/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp +++ b/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp @@ -1245,7 +1245,7 @@ nsMenuPopupFrame::Destroy(nsIPresContext* aPresContext) NS_IMETHODIMP nsMenuPopupFrame::GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, - nsFramePaintLayer aWhichLayer, + nsFramePaintLayer aWhichLayer, nsIFrame** aFrame) { return nsBoxFrame::GetFrameForPoint(aPresContext, aPoint, aWhichLayer, aFrame); diff --git a/mozilla/layout/xul/base/src/nsMenuPopupFrame.h b/mozilla/layout/xul/base/src/nsMenuPopupFrame.h index b593c49e066..ad39a13d27e 100644 --- a/mozilla/layout/xul/base/src/nsMenuPopupFrame.h +++ b/mozilla/layout/xul/base/src/nsMenuPopupFrame.h @@ -103,7 +103,10 @@ public: NS_IMETHOD Destroy(nsIPresContext* aPresContext); - NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, nsFramePaintLayer aWhichLayer, nsIFrame** aFrame); + NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, + const nsPoint& aPoint, + nsFramePaintLayer aWhichLayer, + nsIFrame** aFrame); void GetViewOffset(nsIViewManager* aManager, nsIView* aView, nsPoint& aPoint); static void GetNearestEnclosingView(nsIPresContext* aPresContext, nsIFrame* aStartFrame, nsIView** aResult); diff --git a/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp b/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp index de1a72c4f3e..49c1499b0bc 100644 --- a/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp +++ b/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp @@ -50,6 +50,7 @@ #include "nsIDOMElement.h" #include "nsISupportsArray.h" #include "nsIDOMText.h" +#include "nsBoxLayoutState.h" #define NS_MENU_POPUP_LIST_INDEX (NS_AREA_FRAME_ABSOLUTE_LIST_INDEX + 1) @@ -198,6 +199,40 @@ nsPopupSetFrame::Destroy(nsIPresContext* aPresContext) return nsBoxFrame::Destroy(aPresContext); } +NS_IMETHODIMP +nsPopupSetFrame::Layout(nsBoxLayoutState& aState) +{ + // lay us out + nsresult rv = nsBoxFrame::Layout(aState); + + // layout the popup. First we need to get it. + nsIFrame* popupChild = GetActiveChild(); + if (popupChild) { + nsIBox* ibox = nsnull; + nsresult rv2 = popupChild->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox); + NS_ASSERTION(NS_SUCCEEDED(rv2) && ibox,"popupChild is not box!!"); + + // then get its preferred size + nsSize prefSize(0,0); + nsSize minSize(0,0); + nsSize maxSize(0,0); + + ibox->GetPrefSize(aState, prefSize); + ibox->GetMinSize(aState, minSize); + ibox->GetMaxSize(aState, maxSize); + + BoundsCheck(minSize, prefSize, maxSize); + + // lay it out + LayoutChildAt(aState, ibox, nsRect(0,0,prefSize.width, prefSize.height)); + } + + SyncLayout(aState); + + return rv; +} + +/** Replaced by layout NS_IMETHODIMP nsPopupSetFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -283,9 +318,10 @@ nsPopupSetFrame::Reflow(nsIPresContext* aPresContext, return rv; } +*/ NS_IMETHODIMP -nsPopupSetFrame::SetDebug(nsIPresContext* aPresContext, PRBool aDebug) +nsPopupSetFrame::SetDebug(nsBoxLayoutState& aState, PRBool aDebug) { // see if our state matches the given debug state PRBool debugSet = mState & NS_STATE_CURRENTLY_IN_DEBUG; @@ -294,15 +330,15 @@ nsPopupSetFrame::SetDebug(nsIPresContext* aPresContext, PRBool aDebug) // if it doesn't then tell each child below us the new debug state if (debugChanged) { - nsBoxFrame::SetDebug(aPresContext, aDebug); - SetDebug(aPresContext, mPopupFrames.FirstChild(), aDebug); + nsBoxFrame::SetDebug(aState, aDebug); + SetDebug(aState, mPopupFrames.FirstChild(), aDebug); } return NS_OK; } nsresult -nsPopupSetFrame::SetDebug(nsIPresContext* aPresContext, nsIFrame* aList, PRBool aDebug) +nsPopupSetFrame::SetDebug(nsBoxLayoutState& aState, nsIFrame* aList, PRBool aDebug) { if (!aList) return NS_OK; @@ -310,7 +346,7 @@ nsPopupSetFrame::SetDebug(nsIPresContext* aPresContext, nsIFrame* aList, PRBool while (aList) { nsIBox* ibox = nsnull; if (NS_SUCCEEDED(aList->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) { - ibox->SetDebug(aPresContext, aDebug); + ibox->SetDebug(aState, aDebug); } aList->GetNextSibling(&aList); @@ -358,7 +394,8 @@ nsPopupSetFrame::RemoveFrame(nsIPresContext* aPresContext, if (mPopupFrames.ContainsFrame(aOldFrame)) { // Go ahead and remove this frame. mPopupFrames.DestroyFrame(aPresContext, aOldFrame); - rv = GenerateDirtyReflowCommand(aPresContext, aPresShell); + nsBoxLayoutState state(aPresContext); + rv = MarkDirtyChildren(state); } else { rv = nsBoxFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); } @@ -381,8 +418,9 @@ nsPopupSetFrame::InsertFrames(nsIPresContext* aPresContext, frameChild->GetTag(*getter_AddRefs(tag)); if (tag && tag.get() == nsXULAtoms::popup) { mPopupFrames.InsertFrames(nsnull, nsnull, aFrameList); - SetDebug(aPresContext, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG); - rv = GenerateDirtyReflowCommand(aPresContext, aPresShell); + nsBoxLayoutState state(aPresContext); + SetDebug(state, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG); + rv = MarkDirtyChildren(state); } else { rv = nsBoxFrame::InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList); } @@ -408,8 +446,9 @@ nsPopupSetFrame::AppendFrames(nsIPresContext* aPresContext, frameChild->GetTag(*getter_AddRefs(tag)); if (tag && tag.get() == nsXULAtoms::popup) { mPopupFrames.AppendFrames(nsnull, aFrameList); - SetDebug(aPresContext, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG); - rv = GenerateDirtyReflowCommand(aPresContext, aPresShell); + nsBoxLayoutState state(aPresContext); + SetDebug(state, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG); + rv = MarkDirtyChildren(state); } else { rv = nsBoxFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList); } diff --git a/mozilla/layout/xul/base/src/nsPopupSetFrame.h b/mozilla/layout/xul/base/src/nsPopupSetFrame.h index bc3471f1f50..896344e3d94 100644 --- a/mozilla/layout/xul/base/src/nsPopupSetFrame.h +++ b/mozilla/layout/xul/base/src/nsPopupSetFrame.h @@ -55,7 +55,9 @@ public: nsIStyleContext* aContext, nsIFrame* aPrevInFlow); - NS_IMETHOD SetDebug(nsIPresContext* aPresContext, PRBool aDebug); + // nsIBox + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); + NS_IMETHOD SetDebug(nsBoxLayoutState& aState, PRBool aDebug); // The following four methods are all overridden so that the menu children // can be stored in a separate list (so that they don't impact reflow of the @@ -71,10 +73,6 @@ public: NS_IMETHOD Destroy(nsIPresContext* aPresContext); // Reflow methods - NS_IMETHOD Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); NS_IMETHOD DidReflow(nsIPresContext* aPresContext, nsDidReflowStatus aStatus); @@ -123,7 +121,7 @@ protected: void UpdateDismissalListener(nsIMenuParent* aMenuParent); protected: - nsresult SetDebug(nsIPresContext* aPresContext, nsIFrame* aList, PRBool aDebug); + nsresult SetDebug(nsBoxLayoutState& aState, nsIFrame* aList, PRBool aDebug); nsFrameList mPopupFrames; nsIPresContext* mPresContext; // Our pres context. diff --git a/mozilla/layout/xul/base/src/nsRepeatService.cpp b/mozilla/layout/xul/base/src/nsRepeatService.cpp index 40643b10758..7aac4c08aa1 100644 --- a/mozilla/layout/xul/base/src/nsRepeatService.cpp +++ b/mozilla/layout/xul/base/src/nsRepeatService.cpp @@ -49,7 +49,7 @@ nsRepeatService::GetInstance() { if (!gInstance) { gInstance = new nsRepeatService(); - gInstance->mRefCnt = 1; + NS_ADDREF(gInstance); } return gInstance; diff --git a/mozilla/layout/xul/base/src/nsRootBoxFrame.cpp b/mozilla/layout/xul/base/src/nsRootBoxFrame.cpp new file mode 100644 index 00000000000..baa650f6d20 --- /dev/null +++ b/mozilla/layout/xul/base/src/nsRootBoxFrame.cpp @@ -0,0 +1,261 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ +#include "nsHTMLParts.h" +#include "nsContainerFrame.h" +#include "nsCSSRendering.h" +#include "nsIDocument.h" +#include "nsIReflowCommand.h" +#include "nsIPresContext.h" +#include "nsIStyleContext.h" +#include "nsViewsCID.h" +#include "nsIView.h" +#include "nsIViewManager.h" +#include "nsIWidget.h" +#include "nsHTMLIIDs.h" +#include "nsPageFrame.h" +#include "nsIRenderingContext.h" +#include "nsGUIEvent.h" +#include "nsDOMEvent.h" +#include "nsStyleConsts.h" +#include "nsIViewManager.h" +#include "nsHTMLAtoms.h" +#include "nsIEventStateManager.h" +#include "nsIDeviceContext.h" +#include "nsIScrollableView.h" +#include "nsLayoutAtoms.h" +#include "nsIPresShell.h" +#include "nsBoxFrame.h" +#include "nsStackLayout.h" + +// Interface IDs +static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID); +static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); + +/** + * Root frame class. + * + * The root frame is the parent frame for the document element's frame. + * It only supports having a single child frame which must be an area + * frame + */ +class nsRootBoxFrame : public nsBoxFrame { +public: + + friend nsresult NS_NewBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); + + nsRootBoxFrame(nsIPresShell* aShell); + + NS_IMETHOD AppendFrames(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aFrameList); + NS_IMETHOD InsertFrames(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aPrevFrame, + nsIFrame* aFrameList); + NS_IMETHOD RemoveFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame); + + NS_IMETHOD Reflow(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus); + NS_IMETHOD HandleEvent(nsIPresContext* aPresContext, + nsGUIEvent* aEvent, + nsEventStatus* aEventStatus); + NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, + const nsPoint& aPoint, + nsFramePaintLayer aWhichLayer, + nsIFrame** aFrame); + /** + * Get the "type" of the frame + * + * @see nsLayoutAtoms::rootFrame + */ + NS_IMETHOD GetFrameType(nsIAtom** aType) const; + +#ifdef DEBUG + NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; +#endif + + +}; + +//---------------------------------------------------------------------- + +nsresult +NS_NewRootBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) +{ + NS_PRECONDITION(aNewFrame, "null OUT ptr"); + if (nsnull == aNewFrame) { + return NS_ERROR_NULL_POINTER; + } + nsRootBoxFrame* it = new (aPresShell) nsRootBoxFrame (aPresShell); + if (nsnull == it) { + return NS_ERROR_OUT_OF_MEMORY; + } + + it->SetLayoutManager(new nsStackLayout(aPresShell)); + *aNewFrame = it; + return NS_OK; +} + +nsRootBoxFrame::nsRootBoxFrame(nsIPresShell* aShell):nsBoxFrame(aShell, PR_TRUE) +{ +} + +NS_IMETHODIMP +nsRootBoxFrame::AppendFrames(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aFrameList) +{ + nsresult rv; + + NS_ASSERTION(!aListName, "unexpected child list name"); + NS_PRECONDITION(mFrames.IsEmpty(), "already have a child frame"); + if (aListName) { + // We only support unnamed principal child list + rv = NS_ERROR_INVALID_ARG; + + } else if (!mFrames.IsEmpty()) { + // We only allow a single child frame + rv = NS_ERROR_FAILURE; + + } else { + rv = nsBoxFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList); + } + + return rv; +} + +NS_IMETHODIMP +nsRootBoxFrame::InsertFrames(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aPrevFrame, + nsIFrame* aFrameList) +{ + nsresult rv; + + // Because we only support a single child frame inserting is the same + // as appending + NS_PRECONDITION(!aPrevFrame, "unexpected previous sibling frame"); + if (aPrevFrame) { + rv = NS_ERROR_UNEXPECTED; + } else { + rv = AppendFrames(aPresContext, aPresShell, aListName, aFrameList); + } + + return rv; +} + +NS_IMETHODIMP +nsRootBoxFrame::RemoveFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame) +{ + nsresult rv; + + NS_ASSERTION(!aListName, "unexpected child list name"); + if (aListName) { + // We only support the unnamed principal child list + rv = NS_ERROR_INVALID_ARG; + + } else if (aOldFrame == mFrames.FirstChild()) { + rv = nsBoxFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); + } else { + rv = NS_ERROR_FAILURE; + } + + return rv; +} + +NS_IMETHODIMP +nsRootBoxFrame::Reflow(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + return nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); +} + +NS_IMETHODIMP +nsRootBoxFrame::HandleEvent(nsIPresContext* aPresContext, + nsGUIEvent* aEvent, + nsEventStatus* aEventStatus) +{ + NS_ENSURE_ARG_POINTER(aEventStatus); + if (nsEventStatus_eConsumeNoDefault == *aEventStatus) { + return NS_OK; + } + + if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP || + aEvent->message == NS_MOUSE_MIDDLE_BUTTON_UP || + aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP) { + nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsRootBoxFrame::GetFrameForPoint(nsIPresContext* aPresContext, + const nsPoint& aPoint, + nsFramePaintLayer aWhichLayer, + nsIFrame** aFrame) +{ + // this should act like a block, so we need to override + return nsBoxFrame::GetFrameForPoint(aPresContext, aPoint, aWhichLayer, aFrame); +} + +NS_IMETHODIMP +nsRootBoxFrame::GetFrameType(nsIAtom** aType) const +{ + NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer"); + *aType = nsLayoutAtoms::rootFrame; + NS_ADDREF(*aType); + return NS_OK; +} + +#ifdef DEBUG +NS_IMETHODIMP +nsRootBoxFrame::GetFrameName(nsString& aResult) const +{ + return MakeFrameName("RootBox", aResult); +} + +NS_IMETHODIMP +nsRootBoxFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const +{ + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + *aResult = sizeof(*this); + return NS_OK; +} +#endif diff --git a/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp b/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp index 8637590630c..07dac3dbcda 100644 --- a/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp +++ b/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp @@ -53,7 +53,7 @@ NS_NewScrollbarButtonFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } - nsScrollbarButtonFrame* it = new (aPresShell) nsScrollbarButtonFrame(aPresShell); + nsScrollbarButtonFrame* it = new (aPresShell) nsScrollbarButtonFrame (aPresShell); if (nsnull == it) return NS_ERROR_OUT_OF_MEMORY; @@ -64,7 +64,7 @@ NS_NewScrollbarButtonFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) nsScrollbarButtonFrame::nsScrollbarButtonFrame(nsIPresShell* aPresShell) -:nsXULButtonFrame(aPresShell) +:nsButtonBoxFrame(aPresShell) { } @@ -79,7 +79,7 @@ nsScrollbarButtonFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr) return NS_OK; } - return nsXULButtonFrame::QueryInterface(aIID, aInstancePtr); + return nsButtonBoxFrame::QueryInterface(aIID, aInstancePtr); } NS_IMETHODIMP @@ -91,7 +91,7 @@ nsScrollbarButtonFrame::HandleEvent(nsIPresContext* aPresContext, if (aEvent->message == NS_MOUSE_EXIT|| aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP || aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) HandleRelease(aPresContext, aEvent, aEventStatus); - return nsXULButtonFrame::HandleEvent(aPresContext, aEvent, aEventStatus); + return nsButtonBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus); } @@ -245,5 +245,5 @@ nsScrollbarButtonFrame::Destroy(nsIPresContext* aPresContext) // Ensure our repeat service isn't going... it's possible that a scrollbar can disappear out // from under you while you're in the process of scrolling. nsRepeatService::GetInstance()->Stop(); - return nsXULButtonFrame::Destroy(aPresContext); + return nsButtonBoxFrame::Destroy(aPresContext); } diff --git a/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.h b/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.h index cb997f97e45..3976e520f2b 100644 --- a/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.h +++ b/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.h @@ -30,12 +30,12 @@ #ifndef nsScrollbarButtonFrame_h___ #define nsScrollbarButtonFrame_h___ -#include "nsXULButtonFrame.h" +#include "nsButtonBoxFrame.h" #include "nsITimerCallback.h" class nsSliderFrame; -class nsScrollbarButtonFrame : public nsXULButtonFrame, +class nsScrollbarButtonFrame : public nsButtonBoxFrame, public nsITimerCallback { public: diff --git a/mozilla/layout/xul/base/src/nsSliderFrame.cpp b/mozilla/layout/xul/base/src/nsSliderFrame.cpp index c720cce32ce..1982903569b 100644 --- a/mozilla/layout/xul/base/src/nsSliderFrame.cpp +++ b/mozilla/layout/xul/base/src/nsSliderFrame.cpp @@ -57,6 +57,7 @@ #include "nsINameSpaceManager.h" #include "nsIScrollableView.h" #include "nsRepeatService.h" +#include "nsBoxLayoutState.h" #define DEBUG_SLIDER PR_FALSE @@ -68,7 +69,7 @@ NS_NewSliderFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame) if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } - nsSliderFrame* it = new (aPresShell) nsSliderFrame(); + nsSliderFrame* it = new (aPresShell) nsSliderFrame(aPresShell); if (nsnull == it) return NS_ERROR_OUT_OF_MEMORY; @@ -77,8 +78,8 @@ NS_NewSliderFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame) } // NS_NewSliderFrame -nsSliderFrame::nsSliderFrame() -: mCurPos(0), mScrollbarListener(nsnull),mChange(0) +nsSliderFrame::nsSliderFrame(nsIPresShell* aPresShell):nsBoxFrame(aPresShell), + mCurPos(0), mScrollbarListener(nsnull),mChange(0) { } @@ -95,7 +96,7 @@ nsSliderFrame::Init(nsIPresContext* aPresContext, nsIStyleContext* aContext, nsIFrame* aPrevInFlow) { - nsresult rv = nsHTMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); + nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); CreateViewForFrame(aPresContext,this,aContext,PR_TRUE); nsIView* view; GetView(aPresContext, &view); @@ -153,7 +154,7 @@ nsSliderFrame::AttributeChanged(nsIPresContext* aPresContext, nsIAtom* aAttribute, PRInt32 aHint) { - nsresult rv = nsHTMLContainerFrame::AttributeChanged(aPresContext, aChild, + nsresult rv = nsBoxFrame::AttributeChanged(aPresContext, aChild, aNameSpaceID, aAttribute, aHint); // if the current position changes if (aAttribute == nsXULAtoms::curpos) { @@ -164,7 +165,8 @@ nsSliderFrame::AttributeChanged(nsIPresContext* aPresContext, } else if (aAttribute == nsXULAtoms::maxpos) { // bounds check it. - nsIContent* scrollbar = GetScrollBar(); + nsIBox* scrollbarBox = GetScrollbar(); + nsIContent* scrollbar = GetContentOf(scrollbarBox); PRInt32 current = GetCurrentPosition(scrollbar); PRInt32 max = GetMaxPosition(scrollbar); if (current < 0 || current > max) @@ -189,16 +191,8 @@ nsSliderFrame::AttributeChanged(nsIPresContext* aPresContext, nsCOMPtr shell; aPresContext->GetShell(getter_AddRefs(shell)); - /* - nsCOMPtr reflowCmd; - rv = NS_NewHTMLReflowCommand(getter_AddRefs(reflowCmd), this, - nsIReflowCommand::StyleChanged); - if (NS_SUCCEEDED(rv)) - shell->AppendReflowCommand(reflowCmd); - */ - - mState |= NS_FRAME_IS_DIRTY; - return mParent->ReflowDirtyChild(shell, this); + nsBoxLayoutState state(aPresContext); + MarkDirtyChildren(state); } return rv; @@ -211,12 +205,21 @@ nsSliderFrame::Paint(nsIPresContext* aPresContext, nsFramePaintLayer aWhichLayer) { // if we are too small to have a thumb don't paint it. - nsIFrame* thumbFrame = mFrames.FirstChild(); - NS_ASSERTION(thumbFrame,"Slider does not have a thumb!!!!"); + nsIBox* thumb; + GetChildBox(&thumb); - nsSize size(0,0); - thumbFrame->GetSize(size); - if (mRect.width < size.width || mRect.height < size.height) + NS_ASSERTION(thumb,"Slider does not have a thumb!!!!"); + + nsRect thumbRect; + thumb->GetBounds(thumbRect); + nsMargin m; + thumb->GetMargin(m); + thumbRect.Inflate(m); + + nsRect rect; + GetClientRect(rect); + + if (rect.width < thumbRect.width || rect.height < thumbRect.height) { if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { const nsStyleDisplay* disp = (const nsStyleDisplay*) @@ -236,93 +239,45 @@ nsSliderFrame::Paint(nsIPresContext* aPresContext, return NS_OK; } - return nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); -} - -nsresult -nsSliderFrame::ReflowThumb(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame* thumbFrame, - nsSize available, - nsSize computed) -{ - nsHTMLReflowState thumbReflowState(aPresContext, aReflowState, - thumbFrame, available); - - // always give the thumb as much size as it needs - thumbReflowState.mComputedWidth = computed.width; - thumbReflowState.mComputedHeight = computed.height; - - // subtract out the childs margin and border if computed - const nsStyleSpacing* spacing; - nsresult rv = thumbFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); - - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get spacing"); - if (NS_FAILED(rv)) - return rv; - - - nsMargin margin(0,0,0,0); - spacing->GetMargin(margin); - nsMargin border(0,0,0,0); - spacing->GetBorderPadding(border); - nsMargin total = margin + border; - - if (thumbReflowState.mComputedWidth != NS_INTRINSICSIZE) - thumbReflowState.mComputedWidth -= total.left + total.right; - - if (thumbReflowState.mComputedHeight != NS_INTRINSICSIZE) - thumbReflowState.mComputedHeight -= total.top + total.bottom; - - ReflowChild(thumbFrame, aPresContext, aDesiredSize, thumbReflowState, - 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); - thumbFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); - - // add the margin back in - aDesiredSize.width += margin.left + margin.right; - aDesiredSize.height += margin.top + margin.bottom; - - return NS_OK; -} - -PRBool -nsSliderFrame::IsHorizontal(nsIContent* scrollbar) -{ - PRBool isHorizontal = PR_TRUE; - nsAutoString value; - if (NS_CONTENT_ATTR_HAS_VALUE == scrollbar->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::align, value)) - { - if (value.Equals("vertical")) - isHorizontal = PR_FALSE; - } - - return isHorizontal; + return nsBoxFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); } NS_IMETHODIMP -nsSliderFrame::Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) +nsSliderFrame::Layout(nsBoxLayoutState& aBoxLayoutState) { - nsIContent* scrollbar = GetScrollBar(); + EnsureOrient(); - PRBool isHorizontal = IsHorizontal(scrollbar); + if (mState & NS_STATE_DEBUG_WAS_SET) { + if (mState & NS_STATE_SET_TO_DEBUG) + SetDebug(aBoxLayoutState, PR_TRUE); + else + SetDebug(aBoxLayoutState, PR_FALSE); + } - // flow our thumb with our computed width and its intrinsic height - nsIFrame* thumbFrame = mFrames.FirstChild(); - NS_ASSERTION(thumbFrame,"Slider does not have a thumb!!!!"); + // get the content area inside our borders + nsRect clientRect(0,0,0,0); + GetClientRect(clientRect); - nsHTMLReflowMetrics thumbSize(nsnull); + // get the scrollbar + nsIBox* scrollbarBox = GetScrollbar(); + nsIContent* scrollbar = GetContentOf(scrollbarBox); + PRBool isHorizontal = IsHorizontal(); + + // get the thumb should be our only child + nsIBox* thumbBox = nsnull; + GetChildBox(&thumbBox); + + NS_ASSERTION(thumbBox,"Slider does not have a thumb!!!!"); + + // get the thumb's pref size + nsSize thumbSize(0,0); + thumbBox->GetPrefSize(aBoxLayoutState, thumbSize); + + if (isHorizontal) + thumbSize.height = clientRect.height; + else + thumbSize.width = clientRect.width; - nsSize availableSize(isHorizontal ? NS_INTRINSICSIZE: aReflowState.mComputedWidth, isHorizontal ? aReflowState.mComputedHeight : NS_INTRINSICSIZE); - nsSize computedSize(isHorizontal ? NS_INTRINSICSIZE: aReflowState.mComputedWidth, isHorizontal ? aReflowState.mComputedHeight : NS_INTRINSICSIZE); - - ReflowThumb(aPresContext, thumbSize, aReflowState, aStatus, thumbFrame, availableSize, computedSize); - // get our current position and max position from our content node PRInt32 curpospx = GetCurrentPosition(scrollbar); PRInt32 maxpospx = GetMaxPosition(scrollbar); @@ -332,11 +287,11 @@ nsSliderFrame::Reflow(nsIPresContext* aPresContext, else if (curpospx > maxpospx) curpospx = maxpospx; - // if the computed height we are given is intrinsic then set it to some default height float p2t; - aPresContext->GetScaledPixelsToTwips(&p2t); + aBoxLayoutState.GetPresContext()->GetScaledPixelsToTwips(&p2t); nscoord onePixel = NSIntPixelsToTwips(1, p2t); + /* if (aReflowState.mComputedHeight == NS_INTRINSICSIZE) aDesiredSize.height = isHorizontal ? thumbSize.height : 200*onePixel; else { @@ -353,75 +308,56 @@ nsSliderFrame::Reflow(nsIPresContext* aPresContext, // if (aDesiredSize.width < thumbSize.width) // aDesiredSize.width = thumbSize.width; } + */ // get max pos in twips nscoord maxpos = maxpospx*onePixel; // get our maxpos in twips. This is the space we have left over in the scrollbar // after the height of the thumb has been removed - nscoord& desiredcoord = isHorizontal ? aDesiredSize.width : aDesiredSize.height; + nscoord& desiredcoord = isHorizontal ? clientRect.width : clientRect.height; nscoord& thumbcoord = isHorizontal ? thumbSize.width : thumbSize.height; nscoord ourmaxpos = desiredcoord; mRatio = float(ourmaxpos)/float(maxpos + ourmaxpos); - nscoord thumbsize = nscoord(ourmaxpos * mRatio); // if there is more room than the thumb need stretch the // thumb + + nscoord thumbsize = nscoord(ourmaxpos * mRatio); + if (thumbsize > thumbcoord) { + nscoord flex = 0; + thumbBox->GetFlex(aBoxLayoutState, flex); + // if the thumb is flexible make the thumb bigger. - nsCOMPtr content; - thumbFrame->GetContent(getter_AddRefs(content)); - - PRInt32 error; - nsAutoString value; - if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::flex, value)) - { - value.Trim("%"); - // convert to a percent. - if (value.ToFloat(&error) > 0.0) { - if (isHorizontal) - computedSize.width = thumbsize; - else - computedSize.height = thumbsize; - - ReflowThumb(aPresContext, thumbSize, aReflowState, aStatus, thumbFrame, availableSize, computedSize); - } - } + if (flex > 0) { + if (isHorizontal) + thumbSize.width = nscoord(ourmaxpos * mRatio); + else + thumbSize.height = nscoord(ourmaxpos * mRatio); + } } else { ourmaxpos -= thumbcoord; mRatio = float(ourmaxpos)/float(maxpos); } - // get our border - const nsMargin& borderPadding = aReflowState.mComputedBorderPadding; - nscoord curpos = curpospx*onePixel; // set the thumbs y coord to be the current pos * the ratio. nscoord pos = nscoord(float(curpos)*mRatio); - nsRect thumbRect(borderPadding.left, borderPadding.top, thumbSize.width, thumbSize.height); + nsRect thumbRect(clientRect.x, clientRect.y, thumbSize.width, thumbSize.height); if (isHorizontal) thumbRect.x += pos; else thumbRect.y += pos; - nsIView* view; - thumbFrame->SetRect(aPresContext, thumbRect); - thumbFrame->GetView(aPresContext, &view); - if (view) { - nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, thumbFrame, - view, nsnull); - } - - // add in our border - aDesiredSize.width += borderPadding.left + borderPadding.right; - aDesiredSize.height += borderPadding.top + borderPadding.bottom; - - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; + thumbBox->SetBounds(aBoxLayoutState, thumbRect); + thumbBox->Layout(aBoxLayoutState); + + SyncLayout(aBoxLayoutState); if (DEBUG_SLIDER) { PRInt32 c = GetCurrentPosition(scrollbar); @@ -438,9 +374,9 @@ nsSliderFrame::HandleEvent(nsIPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus) { - nsIContent* scrollbar = GetScrollBar(); - - PRBool isHorizontal = IsHorizontal(scrollbar); + nsIBox* scrollbarBox = GetScrollbar(); + nsIContent* scrollbar = GetContentOf(scrollbarBox); + PRBool isHorizontal = IsHorizontal(); if (isDraggingThumb(aPresContext)) { @@ -536,8 +472,8 @@ nsSliderFrame::HandleEvent(nsIPresContext* aPresContext, -nsIContent* -nsSliderFrame::GetScrollBar() +nsIBox* +nsSliderFrame::GetScrollbar() { // if we are in a scrollbar then return the scrollbar's content node // if we are not then return ours. @@ -545,11 +481,24 @@ nsSliderFrame::GetScrollBar() nsScrollbarButtonFrame::GetParentWithTag(nsXULAtoms::scrollbar, this, scrollbar); if (scrollbar == nsnull) - scrollbar = this; + return this; - nsCOMPtr content; - scrollbar->GetContent(getter_AddRefs(content)); + nsIBox* ibox = nsnull; + scrollbar->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox); + if (ibox == nsnull) + return this; + + return ibox; +} + +nsIContent* +nsSliderFrame::GetContentOf(nsIBox* aBox) +{ + nsIFrame* frame = nsnull; + aBox->GetFrame(&frame); + nsIContent* content = nsnull; + frame->GetContent(&content); return content; } @@ -559,7 +508,8 @@ nsSliderFrame::PageUpDown(nsIFrame* aThumbFrame, nscoord change) // on a page up or down get our page increment. We get this by getting the scrollbar we are in and // asking it for the current position and the page increment. If we are not in a scrollbar we will // get the values from our own node. - nsIContent* scrollbar = GetScrollBar(); + nsIBox* scrollbarBox = GetScrollbar(); + nsIContent* scrollbar = GetContentOf(scrollbarBox); if (mScrollbarListener) mScrollbarListener->PagedUpDown(); // Let the listener decide our increment. @@ -573,9 +523,10 @@ nsSliderFrame::PageUpDown(nsIFrame* aThumbFrame, nscoord change) nsresult nsSliderFrame::CurrentPositionChanged(nsIPresContext* aPresContext) { - nsIContent* scrollbar = GetScrollBar(); + nsIBox* scrollbarBox = GetScrollbar(); + nsIContent* scrollbar = GetContentOf(scrollbarBox); - PRBool isHorizontal = IsHorizontal(scrollbar); + PRBool isHorizontal = IsHorizontal(); // get the current position PRInt32 curpos = GetCurrentPosition(scrollbar); @@ -670,7 +621,7 @@ NS_IMETHODIMP nsSliderFrame::GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, nsFramePaintLayer aWhichLayer, nsIFrame** aFrame) -{ +{ if (isDraggingThumb(aPresContext)) { // XXX I assume it's better not to test for visibility here. @@ -678,35 +629,12 @@ NS_IMETHODIMP nsSliderFrame::GetFrameForPoint(nsIPresContext* aPresContext, return NS_OK; } - if ((! mRect.Contains(aPoint)) || - (aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND)) { + if (!mRect.Contains(aPoint)) return NS_ERROR_FAILURE; - } - nsIFrame* thumbFrame = mFrames.FirstChild(); - // XXX If thumbFrame always considers itself FOREGROUND, then it - // would be better to just call thumbFrame->GetFrameForPoint and - // return if it returns NS_OK. - nsRect thumbRect; - thumbFrame->GetRect(thumbRect); - nsPoint tmp; - tmp.MoveTo(aPoint.x - mRect.x, aPoint.y - mRect.y); - - if (thumbRect.Contains(tmp)) { - nsIStyleContext *tsc; - thumbFrame->GetStyleContext(&tsc); - if (tsc) { - const nsStyleDisplay* disp = (const nsStyleDisplay*) - tsc->GetStyleData(eStyleStruct_Display); - if (disp->IsVisible()) { - *aFrame = thumbFrame; - NS_RELEASE(tsc); - return NS_OK; - } - NS_RELEASE(tsc); - } - } + if (NS_SUCCEEDED(nsBoxFrame::GetFrameForPoint(aPresContext, aPoint, aWhichLayer, aFrame))) + return NS_OK; // always return us (if visible) const nsStyleDisplay* disp = (const nsStyleDisplay*) @@ -717,8 +645,6 @@ NS_IMETHODIMP nsSliderFrame::GetFrameForPoint(nsIPresContext* aPresContext, } return NS_ERROR_FAILURE; - - //return nsHTMLContainerFrame::GetFrameForPoint(aPresContext, aPoint, aFrame); } @@ -728,55 +654,19 @@ nsSliderFrame::SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList) { - nsresult r = nsHTMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); + nsresult r = nsBoxFrame::SetInitialChildList(aPresContext, aListName, aChildList); AddListener(); return r; } - -NS_IMETHODIMP -nsSliderFrame::RemoveFrame(nsIPresContext* aPresContext, - nsIPresShell& aPresShell, - nsIAtom* aListName, - nsIFrame* aOldFrame) -{ - // remove the child frame - nsresult rv = nsHTMLContainerFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); - mFrames.DestroyFrame(aPresContext, aOldFrame); - return rv; -} - -NS_IMETHODIMP -nsSliderFrame::InsertFrames(nsIPresContext* aPresContext, - nsIPresShell& aPresShell, - nsIAtom* aListName, - nsIFrame* aPrevFrame, - nsIFrame* aFrameList) -{ - mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList); - return nsHTMLContainerFrame::InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList); -} - -NS_IMETHODIMP -nsSliderFrame::AppendFrames(nsIPresContext* aPresContext, - nsIPresShell& aPresShell, - nsIAtom* aListName, - nsIFrame* aFrameList) -{ - mFrames.AppendFrames(nsnull, aFrameList); - return nsHTMLContainerFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList); -} - - nsresult nsSliderFrame::MouseDown(nsIDOMEvent* aMouseEvent) { //printf("Begin dragging\n"); - nsIContent* scrollbar = GetScrollBar(); - PRBool isHorizontal = IsHorizontal(scrollbar); + PRBool isHorizontal = IsHorizontal(); nsCOMPtr mouseEvent(do_QueryInterface(aMouseEvent)); @@ -885,7 +775,7 @@ nsSliderFrame::RemoveListener() NS_INTERFACE_MAP_BEGIN(nsSliderFrame) NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener) NS_INTERFACE_MAP_ENTRY(nsITimerCallback) -NS_INTERFACE_MAP_END_INHERITING(nsHTMLContainerFrame) +NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame) NS_IMETHODIMP_(nsrefcnt) @@ -905,8 +795,7 @@ nsSliderFrame::HandlePress(nsIPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus) { - nsIContent* scrollbar = GetScrollBar(); - PRBool isHorizontal = IsHorizontal(scrollbar); + PRBool isHorizontal = IsHorizontal(); nsIFrame* thumbFrame = mFrames.FirstChild(); nsRect thumbRect; @@ -969,7 +858,47 @@ nsSliderFrame::Destroy(nsIPresContext* aPresContext) RemoveListener(); // remove this line when 21571 is fixed properly // call base class Destroy() - return nsHTMLContainerFrame::Destroy(aPresContext); + return nsBoxFrame::Destroy(aPresContext); +} + +NS_IMETHODIMP +nsSliderFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) +{ + EnsureOrient(); + return nsBoxFrame::GetPrefSize(aState, aSize); +} + +NS_IMETHODIMP +nsSliderFrame::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize) +{ + EnsureOrient(); + + // our min size is just our borders and padding + return nsBox::GetMinSize(aState, aSize); +} + +NS_IMETHODIMP +nsSliderFrame::GetMaxSize(nsBoxLayoutState& aState, nsSize& aSize) +{ + EnsureOrient(); + return nsBoxFrame::GetMaxSize(aState, aSize); +} + +void +nsSliderFrame::EnsureOrient() +{ + nsIBox* scrollbarBox = GetScrollbar(); + + nsIFrame* frame = nsnull; + scrollbarBox->GetFrame(&frame); + nsFrameState state; + frame->GetFrameState(&state); + + PRBool isHorizontal = state & NS_STATE_IS_HORIZONTAL; + if (isHorizontal) + mState |= NS_STATE_IS_HORIZONTAL; + else + mState &= ~NS_STATE_IS_HORIZONTAL; } @@ -988,8 +917,7 @@ NS_IMETHODIMP_(void) nsSliderFrame::Notify(nsITimer *timer) nsRect thumbRect; thumbFrame->GetRect(thumbRect); - nsIContent* scrollbar = GetScrollBar(); - PRBool isHorizontal = IsHorizontal(scrollbar); + PRBool isHorizontal = IsHorizontal(); // see if the thumb has moved passed our original click point. // if it has we want to stop. @@ -1018,3 +946,46 @@ NS_IMETHODIMP_(void) nsSliderFrame::Notify(nsITimer *timer) PageUpDown(thumbFrame, mChange); } } + +class nsThumbFrame : public nsTitledButtonFrame +{ +public: + + friend nsresult NS_NewThumbFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); + + NS_IMETHOD HandlePress(nsIPresContext* aPresContext, + nsGUIEvent * aEvent, + nsEventStatus* aEventStatus) { return NS_OK; } + + NS_IMETHOD HandleMultiplePress(nsIPresContext* aPresContext, + nsGUIEvent * aEvent, + nsEventStatus* aEventStatus) { return NS_OK; } + + NS_IMETHOD HandleDrag(nsIPresContext* aPresContext, + nsGUIEvent * aEvent, + nsEventStatus* aEventStatus) { return NS_OK; } + + NS_IMETHOD HandleRelease(nsIPresContext* aPresContext, + nsGUIEvent * aEvent, + nsEventStatus* aEventStatus) { return NS_OK; } + + nsThumbFrame(nsIPresShell* aPresShell):nsTitledButtonFrame(aPresShell) {} +}; + + +nsresult +NS_NewThumbFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame) +{ + NS_PRECONDITION(aNewFrame, "null OUT ptr"); + if (nsnull == aNewFrame) { + return NS_ERROR_NULL_POINTER; + } + nsThumbFrame* it = new (aPresShell) nsThumbFrame(aPresShell); + if (nsnull == it) + return NS_ERROR_OUT_OF_MEMORY; + + *aNewFrame = it; + return NS_OK; + +} // NS_NewSliderFrame + diff --git a/mozilla/layout/xul/base/src/nsSliderFrame.h b/mozilla/layout/xul/base/src/nsSliderFrame.h index 9907b1730f5..0e623652862 100644 --- a/mozilla/layout/xul/base/src/nsSliderFrame.h +++ b/mozilla/layout/xul/base/src/nsSliderFrame.h @@ -28,7 +28,7 @@ #define nsSliderFrame_h__ -#include "nsHTMLContainerFrame.h" +#include "nsBoxFrame.h" #include "prtypes.h" #include "nsIAtom.h" #include "nsCOMPtr.h" @@ -47,12 +47,12 @@ class nsITimer; nsresult NS_NewSliderFrame(nsIPresShell* aPresShell, nsIFrame** aResult) ; -class nsSliderFrame : public nsHTMLContainerFrame, +class nsSliderFrame : public nsBoxFrame, public nsIDOMMouseListener, public nsITimerCallback { public: - nsSliderFrame(); + nsSliderFrame(nsIPresShell* aShell); virtual ~nsSliderFrame(); #ifdef DEBUG @@ -61,6 +61,12 @@ public: } #endif + // nsIBox + NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); + // nsIFrame overrides NS_IMETHOD Destroy(nsIPresContext* aPresContext); @@ -83,34 +89,15 @@ public: nsIStyleContext* aContext, nsIFrame* asPrevInFlow); - NS_IMETHOD Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); - - NS_IMETHOD AppendFrames(nsIPresContext* aPresContext, - nsIPresShell& aPresShell, - nsIAtom* aListName, - nsIFrame* aFrameList); - - NS_IMETHOD InsertFrames(nsIPresContext* aPresContext, - nsIPresShell& aPresShell, - nsIAtom* aListName, - nsIFrame* aPrevFrame, - nsIFrame* aFrameList); - - NS_IMETHOD RemoveFrame(nsIPresContext* aPresContext, - nsIPresShell& aPresShell, - nsIAtom* aListName, - nsIFrame* aOldFrame); - NS_IMETHOD HandleEvent(nsIPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus); - NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, - const nsPoint& aPoint, nsFramePaintLayer aWhichLayer, nsIFrame** aFrame); + NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, + const nsPoint& aPoint, + nsFramePaintLayer aWhichLayer, + nsIFrame** aFrame); NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, @@ -171,7 +158,7 @@ public: static PRInt32 GetIncrement(nsIContent* content); static PRInt32 GetPageIncrement(nsIContent* content); static PRInt32 GetIntegerAttribute(nsIContent* content, nsIAtom* atom, PRInt32 defaultValue); - static PRInt32 IsHorizontal(nsIContent* content); + void EnsureOrient(); void SetScrollbarListener(nsIScrollbarListener* aListener); @@ -196,20 +183,14 @@ public: protected: - virtual nsresult ReflowThumb(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsIFrame* thumbFrame, - nsSize available, - nsSize computed); - virtual PRIntn GetSkipSides() const { return 0; } private: - nsIContent* GetScrollBar(); + nsIBox* GetScrollbar(); + nsIContent* GetContentOf(nsIBox* aBox); + void PageUpDown(nsIFrame* aThumbFrame, nscoord change); void SetCurrentPosition(nsIContent* scrollbar, nsIFrame* aThumbFrame, nscoord pos); NS_IMETHOD DragThumb(nsIPresContext* aPresContext, PRBool aGrabMouseEvents); diff --git a/mozilla/layout/xul/base/src/nsSplitterFrame.cpp b/mozilla/layout/xul/base/src/nsSplitterFrame.cpp index ea7f5392ef6..0fdddcf835a 100644 --- a/mozilla/layout/xul/base/src/nsSplitterFrame.cpp +++ b/mozilla/layout/xul/base/src/nsSplitterFrame.cpp @@ -50,8 +50,9 @@ #include "nsIPresShell.h" #include "nsIStyleContext.h" #include "nsWidgetsCID.h" +#include "nsBoxLayoutState.h" -#define REAL_TIME_DRAG PR_FALSE +#define REAL_TIME_DRAG const PRInt32 kMaxZ = 0x7fffffff; //XXX: Shouldn't there be a define somewhere for MaxInt for PRInt32 @@ -63,7 +64,7 @@ public: nscoord max; nscoord current; nscoord changed; - nsIFrame* child; + nsIBox* child; PRInt32 flex; PRInt32 index; }; @@ -133,12 +134,13 @@ public: CollapseDirection GetCollapseDirection(); void MoveSplitterBy(nsIPresContext* aPresContext, nscoord aDiff); + void EnsureOrient(); nsSplitterFrame* mOuter; PRBool mDidDrag; nscoord mDragStartPx; nscoord mCurrentPos; - nsBoxFrame* mParentBox; + nsIBox* mParentBox; PRBool mPressed; nsSplitterInfo* mChildInfosBefore; nsSplitterInfo* mChildInfosAfter; @@ -148,6 +150,7 @@ public: nscoord mSplitterPos; nscoord mSplitterViewPos; + }; @@ -343,28 +346,38 @@ nsSplitterFrame::Init(nsIPresContext* aPresContext, nsIView* view; GetView(aPresContext, &view); -// currently this only works on win32 and mac -#ifdef XP_UNIX - view->SetContentTransparency(PR_TRUE); - view->SetZIndex(kMaxZ); +#if defined(REAL_TIME_DRAG) || defined(XP_UNIX) + view->SetContentTransparency(PR_TRUE); + view->SetZIndex(kMaxZ); #else - static NS_DEFINE_CID(kCChildCID, NS_CHILD_CID); - nsCOMPtr viewManager; - view->GetViewManager(*getter_AddRefs(viewManager)); - viewManager->SetViewContentTransparency(view, PR_TRUE); - viewManager->SetViewZIndex(view, kMaxZ); + // currently this only works on win32 and mac + static NS_DEFINE_CID(kCChildCID, NS_CHILD_CID); + nsCOMPtr viewManager; + view->GetViewManager(*getter_AddRefs(viewManager)); + viewManager->SetViewContentTransparency(view, PR_TRUE); + viewManager->SetViewZIndex(view, kMaxZ); - // Need to have a widget to appear on top of other widgets. - view->CreateWidget(kCChildCID); + // Need to have a widget to appear on top of other widgets. + view->CreateWidget(kCChildCID); #endif mInner->mState = nsSplitterFrameInner::Open; - mInner->UpdateState(); mInner->AddListener(aPresContext); - + mInner->mParentBox = nsnull; return rv; } +NS_IMETHODIMP +nsSplitterFrame::Layout(nsBoxLayoutState& aState) +{ + if (aState.GetLayoutReason() == nsBoxLayoutState::Initial) { + GetParentBox(&mInner->mParentBox); + mInner->UpdateState(); + } + return nsBoxFrame::Layout(aState); +} + + PRBool nsSplitterFrame::GetInitialOrientation(PRBool& aIsHorizontal) { @@ -419,7 +432,7 @@ nsSplitterFrame::HandleRelease(nsIPresContext* aPresContext, NS_IMETHODIMP nsSplitterFrame::GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, - nsFramePaintLayer aWhichLayer, + nsFramePaintLayer aWhichLayer, nsIFrame** aFrame) { // if the mouse is captured always return us as the frame. @@ -428,8 +441,19 @@ NS_IMETHODIMP nsSplitterFrame::GetFrameForPoint(nsIPresContext* aPresContext, // XXX It's probably better not to check visibility here, right? *aFrame = this; return NS_OK; - } else - return nsBoxFrame::GetFrameForPoint(aPresContext, aPoint, aWhichLayer, aFrame); + } else { + + if (!mRect.Contains(aPoint)) + return NS_ERROR_FAILURE; + + nsresult rv = nsBoxFrame::GetFrameForPoint(aPresContext, aPoint, aWhichLayer, aFrame); + if (rv == NS_ERROR_FAILURE) { + *aFrame = this; + rv = NS_OK; + } + + return rv; + } } NS_IMETHODIMP @@ -475,8 +499,7 @@ nsSplitterFrameInner::MouseDrag(nsIPresContext* aPresContext, nsGUIEvent* aEvent { if (IsMouseCaptured(aPresContext)) { - // printf("Dragging\n"); - + //printf("Dragging\n"); PRBool isHorizontal = !mOuter->IsHorizontal(); // convert coord to pixels @@ -576,7 +599,7 @@ nsSplitterFrameInner::MouseDrag(nsIPresContext* aPresContext, nsGUIEvent* aEvent if (currentState != Dragging) mOuter->mContent->SetAttribute(kNameSpaceID_None, nsXULAtoms::state, "dragging", PR_TRUE); -#if REAL_TIME_DRAG +#ifdef REAL_TIME_DRAG AdjustChildren(aPresContext); #else MoveSplitterBy(aPresContext, pos); @@ -702,14 +725,13 @@ nsSplitterFrameInner::MouseUp(nsIDOMEvent* aMouseEvent) nsresult nsSplitterFrameInner::MouseDown(nsIDOMEvent* aMouseEvent) { + nsBoxLayoutState state(mOuter->mPresContext); mCurrentPos = 0; mPressed = PR_TRUE; mDidDrag = PR_FALSE; - nsIFrame* parent = nsnull; - mOuter->GetParent(&parent); - mParentBox = (nsBoxFrame*)parent; + mOuter->GetParentBox(&mParentBox); // get our index nscoord childIndex = nsFrameNavigator::IndexOf(mOuter->mPresContext, mParentBox, mOuter); @@ -721,13 +743,14 @@ nsSplitterFrameInner::MouseDown(nsIDOMEvent* aMouseEvent) return NS_OK; } - PRBool isHorizontal = mParentBox->IsHorizontal(); + EnsureOrient(); + PRBool isHorizontal = !mOuter->IsHorizontal(); ResizeType resizeBefore = GetResizeBefore(); ResizeType resizeAfter = GetResizeAfter(); - delete mChildInfosBefore; - delete mChildInfosAfter; + delete[] mChildInfosBefore; + delete[] mChildInfosAfter; mChildInfosBefore = new nsSplitterInfo[childCount]; mChildInfosAfter = new nsSplitterInfo[childCount]; @@ -737,11 +760,14 @@ nsSplitterFrameInner::MouseDown(nsIDOMEvent* aMouseEvent) mChildInfosBeforeCount = 0; mChildInfosAfterCount = 0; - nsIFrame* childFrame = nsnull; - mParentBox->FirstChild(mOuter->mPresContext, nsnull, &childFrame); + nsIBox* childBox = nsnull; + mParentBox->GetChildBox(&childBox); - while (nsnull != childFrame) + while (nsnull != childBox) { + nsIFrame* childFrame = nsnull; + childBox->GetFrame(&childFrame); + nsCOMPtr content; childFrame->GetContent(getter_AddRefs(content)); nsIAtom* atom; @@ -749,41 +775,48 @@ nsSplitterFrameInner::MouseDown(nsIDOMEvent* aMouseEvent) // skip over any splitters if (atom != nsXULAtoms::splitter) { - nsBoxInfo info; - mParentBox->GetChildBoxInfo(count, info); + nsSize prefSize(0,0); + nsSize minSize(0,0); + nsSize maxSize(0,0); + nscoord flex = 0; - const nsStyleSpacing* spacing; - nsresult rv = childFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); + childBox->GetPrefSize(state, prefSize); + childBox->GetMinSize(state, minSize); + childBox->GetMaxSize(state, maxSize); + nsBox::BoundsCheck(minSize, prefSize, maxSize); - NS_ASSERTION(rv == NS_OK,"failed to get spacing info"); + mOuter->AddMargin(childBox, minSize); + mOuter->AddMargin(childBox, prefSize); + mOuter->AddMargin(childBox, maxSize); + + childBox->GetFlex(state, flex); nsMargin margin(0,0,0,0); - spacing->GetMargin(margin); + childBox->GetMargin(margin); nsRect r(0,0,0,0); - childFrame->GetRect(r); + childBox->GetBounds(r); r.Inflate(margin); if (count < childIndex) { - mChildInfosBefore[mChildInfosBeforeCount].child = childFrame; - mChildInfosBefore[mChildInfosBeforeCount].min = isHorizontal ? info.minSize.width : info.minSize.height; - mChildInfosBefore[mChildInfosBeforeCount].max = isHorizontal ? info.maxSize.width : info.maxSize.height; + mChildInfosBefore[mChildInfosBeforeCount].child = childBox; + mChildInfosBefore[mChildInfosBeforeCount].min = isHorizontal ? minSize.width : minSize.height; + mChildInfosBefore[mChildInfosBeforeCount].max = isHorizontal ? maxSize.width : maxSize.height; mChildInfosBefore[mChildInfosBeforeCount].current = isHorizontal ? r.width : r.height; - mChildInfosBefore[mChildInfosBeforeCount].flex = info.flex; + mChildInfosBefore[mChildInfosBeforeCount].flex = flex; mChildInfosBefore[mChildInfosBeforeCount].index = count; mChildInfosBeforeCount++; } else if (count > childIndex) { - mChildInfosAfter[mChildInfosAfterCount].child = childFrame; - mChildInfosAfter[mChildInfosAfterCount].min = isHorizontal ? info.minSize.width : info.minSize.height; - mChildInfosAfter[mChildInfosAfterCount].max = isHorizontal ? info.maxSize.width : info.maxSize.height; + mChildInfosAfter[mChildInfosAfterCount].child = childBox; + mChildInfosAfter[mChildInfosAfterCount].min = isHorizontal ? minSize.width : minSize.height; + mChildInfosAfter[mChildInfosAfterCount].max = isHorizontal ? maxSize.width : maxSize.height; mChildInfosAfter[mChildInfosAfterCount].current = isHorizontal ? r.width : r.height; - mChildInfosAfter[mChildInfosAfterCount].flex = info.flex; + mChildInfosAfter[mChildInfosAfterCount].flex = flex; mChildInfosAfter[mChildInfosAfterCount].index = count; mChildInfosAfterCount++; } } - nsresult rv = childFrame->GetNextSibling(&childFrame); + nsresult rv = childBox->GetNextBox(&childBox); NS_ASSERTION(rv == NS_OK,"failed to get next child"); count++; } @@ -823,7 +856,7 @@ nsSplitterFrameInner::MouseDown(nsIDOMEvent* aMouseEvent) mDragStartPx = c; - //printf("Pressed mDragStartPx=%d\n",mDragStartPx); + printf("Pressed mDragStartPx=%d\n",mDragStartPx); return NS_OK; } @@ -894,72 +927,159 @@ nsSplitterFrameInner::UpdateState() return; } - CollapseDirection direction = GetCollapseDirection(); - if (direction != None) { - nsIFrame* splitter = mOuter; - // Find the splitter's immediate sibling. - nsIFrame* splitterSibling = - nsFrameNavigator::GetChildBeforeAfter(mOuter->mPresContext, splitter, - (direction == Before)); - if (splitterSibling) { - nsCOMPtr sibling; - if (NS_SUCCEEDED(splitterSibling->GetContent(getter_AddRefs(sibling))) - && sibling) { - if (mState == Collapsed) { - // Collapsed -> Open - // Collapsed -> Dragging - sibling->UnsetAttribute(kNameSpaceID_None, nsXULAtoms::collapsed, - PR_TRUE); - } else if ((mState == Open || mState == Dragging) - && newState == Collapsed) { - // Open -> Collapsed - // Dragging -> Collapsed - sibling->SetAttribute(kNameSpaceID_None, nsXULAtoms::collapsed, - "true", PR_TRUE); + CollapseDirection direction = GetCollapseDirection(); + if (direction != None) { + nsIBox* splitter = mOuter; + // Find the splitter's immediate sibling. + nsIBox* splitterSibling = + nsFrameNavigator::GetChildBeforeAfter(mOuter->mPresContext, splitter, + (direction == Before)); + if (splitterSibling) { + nsIFrame* splitterSiblingFrame = nsnull; + splitterSibling->GetFrame(&splitterSiblingFrame); + nsCOMPtr sibling; + if (NS_SUCCEEDED(splitterSiblingFrame->GetContent(getter_AddRefs(sibling))) + && sibling) { + if (mState == Collapsed) { + // Collapsed -> Open + // Collapsed -> Dragging + sibling->UnsetAttribute(kNameSpaceID_None, nsXULAtoms::collapsed, + PR_TRUE); + } else if ((mState == Open || mState == Dragging) + && newState == Collapsed) { + // Open -> Collapsed + // Dragging -> Collapsed + sibling->SetAttribute(kNameSpaceID_None, nsXULAtoms::collapsed, + "true", PR_TRUE); + } } } } - } - mState = newState; + mState = newState; + +} + +void +nsSplitterFrameInner::EnsureOrient() +{ + nsIFrame* frame = nsnull; + mParentBox->GetFrame(&frame); + nsFrameState state; + frame->GetFrameState(&state); + + PRBool isHorizontal = !(state & NS_STATE_IS_HORIZONTAL); + if (isHorizontal) + mOuter->mState |= NS_STATE_IS_HORIZONTAL; + else + mOuter->mState &= ~NS_STATE_IS_HORIZONTAL; } void nsSplitterFrameInner::AdjustChildren(nsIPresContext* aPresContext) { - PRBool isHorizontal = mParentBox->IsHorizontal(); + EnsureOrient(); + PRBool isHorizontal = !mOuter->IsHorizontal(); + AdjustChildren(aPresContext, mChildInfosBefore, mChildInfosBeforeCount, isHorizontal); AdjustChildren(aPresContext, mChildInfosAfter, mChildInfosAfterCount, isHorizontal); + + // printf("----- Posting Dirty -----\n"); + + +#ifdef REAL_TIME_DRAG +// nsBoxLayoutState state(aPresContext); + // state.SetLayoutReason(nsBoxLayoutState::Resize); + //mParentBox->Layout(state); + /* nsCOMPtr shell; aPresContext->GetShell(getter_AddRefs(shell)); + + shell->EnterReflowLock(); + shell->ProcessReflowCommands(PR_TRUE); + shell->ExitReflowLock(PR_FALSE); +*/ + + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + nsIFrame* frame = nsnull; + mParentBox->GetFrame(&frame); + + /* + shell->EnterReflowLock(); + nsRect bounds; + mParentBox->GetBounds(bounds); + nsSize maxSize(bounds.width, bounds.height); + nsIRenderingContext* rcx = nsnull; + nsresult rv = shell->CreateRenderingContext(frame, &rcx); + nsHTMLReflowState reflowState(aPresContext, frame, + eReflowReason_Resize, rcx, maxSize); + nsBoxLayoutState state(aPresContext, reflowState); + mParentBox->Layout(state); + shell->ExitReflowLock(PR_TRUE); + */ + + shell->FlushPendingNotifications(); + + nsCOMPtr viewManager; + nsIView* view = nsnull; + frame->GetView(aPresContext, &view); + + nsRect damageRect(0,0,0,0); + mParentBox->GetContentRect(damageRect); + + if (view) { + view->GetViewManager(*getter_AddRefs(viewManager)); + viewManager->UpdateView(view, damageRect, NS_VMREFRESH_IMMEDIATE); + + } else { + nsRect rect(damageRect); + nsPoint offset; - mOuter->mState |= NS_FRAME_IS_DIRTY; - mOuter->mParent->ReflowDirtyChild(shell, mOuter->mParent); + frame->GetOffsetFromView(aPresContext, offset, &view); + NS_ASSERTION(nsnull != view, "no view"); + rect += offset; + view->GetViewManager(*getter_AddRefs(viewManager)); + viewManager->UpdateView(view, rect, NS_VMREFRESH_IMMEDIATE); + } + +#else + //mOuter->mState |= NS_FRAME_IS_DIRTY; + //mOuter->mParent->ReflowDirtyChild(shell, mOuter->mParent); + nsBoxLayoutState state(aPresContext); + mOuter->MarkDirty(state); +#endif } void nsSplitterFrameInner::AdjustChildren(nsIPresContext* aPresContext, nsSplitterInfo* aChildInfos, PRInt32 aCount, PRBool aIsHorizontal) { - // printf("------- AdjustChildren------\n"); + ///printf("------- AdjustChildren------\n"); + + nsBoxLayoutState state(aPresContext); + + nsCOMPtr shell; + state.GetPresShell(getter_AddRefs(shell)); + + float p2t; + aPresContext->GetScaledPixelsToTwips(&p2t); + nscoord onePixel = NSIntPixelsToTwips(1, p2t); for (int i=0; i < aCount; i++) { nscoord pref = aChildInfos[i].changed; - nsIFrame* childFrame = aChildInfos[i].child; - nsresult rv; + nscoord current = aChildInfos[i].current; + nsIBox* childBox = aChildInfos[i].child; + PRInt32 index = aChildInfos[i].index; - const nsStyleSpacing* spacing; - rv = childFrame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); + //printf("current=%d, pref=%d", current/onePixel, pref/onePixel); - NS_ASSERTION(rv == NS_OK,"failed to get spacing info"); + if (current/onePixel == pref/onePixel) + continue; nsMargin margin(0,0,0,0); - spacing->GetMargin(margin); - nsMargin border(0,0,0,0); - spacing->GetBorderPadding(border); - margin += border; + childBox->GetMargin(margin); nsIAtom* attribute; @@ -971,9 +1091,8 @@ nsSplitterFrameInner::AdjustChildren(nsIPresContext* aPresContext, nsSplitterInf attribute = nsHTMLAtoms::height; } - float p2t; - aPresContext->GetScaledPixelsToTwips(&p2t); - nscoord onePixel = NSIntPixelsToTwips(1, p2t); + nsIFrame* childFrame = nsnull; + childBox->GetFrame(&childFrame); nsCOMPtr content; childFrame->GetContent(getter_AddRefs(content)); @@ -981,10 +1100,17 @@ nsSplitterFrameInner::AdjustChildren(nsIPresContext* aPresContext, nsSplitterInf // set its preferred size. char ch[50]; sprintf(ch,"%d",pref/onePixel); - //printf("index=%d, pref=%s\n", i, ch); content->SetAttribute(kNameSpaceID_None, attribute, ch, PR_FALSE); - mParentBox->InvalidateCache(childFrame); +#ifndef REAL_TIME_DRAG + childBox->MarkDirty(state); +#else + childBox->MarkDirty(state); +#endif + } + + //printf("\n"); + } @@ -1068,7 +1194,9 @@ nsSplitterFrameInner::MoveSplitterBy(nsIPresContext* aPresContext, nscoord aDiff v->GetViewManager(*getter_AddRefs(vm)); v->GetBounds(vr); nsRect invalid; - if (mParentBox->IsHorizontal()) { + EnsureOrient(); + PRBool isHorizontal = !mOuter->IsHorizontal(); + if (isHorizontal) { mOuter->MoveTo(aPresContext, mSplitterPos + aDiff, r.y); vm->MoveViewTo(v, mSplitterViewPos + aDiff, vr.y); invalid.UnionRect(r,mOuter->mRect); @@ -1080,7 +1208,9 @@ nsSplitterFrameInner::MoveSplitterBy(nsIPresContext* aPresContext, nscoord aDiff // redraw immediately only what changed. This is animation so // it must be immediate. - mParentBox->Invalidate(aPresContext, invalid, PR_TRUE); + nsBoxLayoutState state(aPresContext); + mParentBox->Redraw(state, &invalid, PR_TRUE); } + diff --git a/mozilla/layout/xul/base/src/nsSplitterFrame.h b/mozilla/layout/xul/base/src/nsSplitterFrame.h index 74fc794e7ec..6f05f5443ab 100644 --- a/mozilla/layout/xul/base/src/nsSplitterFrame.h +++ b/mozilla/layout/xul/base/src/nsSplitterFrame.h @@ -48,6 +48,7 @@ public: } #endif + // nsIFrame overrides NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, nsIContent* aChild, @@ -65,6 +66,7 @@ public: nsPoint& aPoint, PRInt32& aCursor); + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); // nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, @@ -93,7 +95,10 @@ public: nsGUIEvent* aEvent, nsEventStatus* aEventStatus); - NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, nsFramePaintLayer aWhichLayer, nsIFrame** aFrame); + NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, + const nsPoint& aPoint, + nsFramePaintLayer aWhichLayer, + nsIFrame** aFrame); virtual PRBool GetInitialOrientation(PRBool& aIsHorizontal); diff --git a/mozilla/layout/xul/base/src/nsSpringFrame.cpp b/mozilla/layout/xul/base/src/nsSpringFrame.cpp index 47deab54d76..f021f44d870 100644 --- a/mozilla/layout/xul/base/src/nsSpringFrame.cpp +++ b/mozilla/layout/xul/base/src/nsSpringFrame.cpp @@ -37,7 +37,7 @@ NS_NewSpringFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } - nsSpringFrame* it = new (aPresShell) nsSpringFrame; + nsSpringFrame* it = new (aPresShell) nsSpringFrame (aPresShell); if (nsnull == it) return NS_ERROR_OUT_OF_MEMORY; @@ -48,25 +48,23 @@ NS_NewSpringFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) NS_IMETHODIMP nsSpringFrame::GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, - nsFramePaintLayer aWhichLayer, + nsFramePaintLayer aWhichLayer, nsIFrame** aFrame) { - if (!mRect.Contains(aPoint)) { + if (!mRect.Contains(aPoint)) return NS_ERROR_FAILURE; - } - // always return us (if visible) - const nsStyleDisplay* disp = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - if (disp->IsVisible()) { + // see if it is in our border, padding, or inset + nsRect r(mRect); + nsMargin m; + GetInset(m); + r.Deflate(m); + GetBorderAndPadding(m); + r.Deflate(m); + if (!r.Contains(aPoint)) { *aFrame = this; return NS_OK; } - return NS_ERROR_FAILURE; - - /* - // clicks just go right through springs. - return NS_ERROR_FAILURE; - */ + return NS_ERROR_FAILURE; } diff --git a/mozilla/layout/xul/base/src/nsSpringFrame.h b/mozilla/layout/xul/base/src/nsSpringFrame.h index 20020eb25f5..2ec9e2dd722 100644 --- a/mozilla/layout/xul/base/src/nsSpringFrame.h +++ b/mozilla/layout/xul/base/src/nsSpringFrame.h @@ -31,9 +31,10 @@ #ifndef nsSpringFrame_h___ #define nsSpringFrame_h___ -#include "nsXULLeafFrame.h" +#include "nsLeafBoxFrame.h" +struct nsPoint; -class nsSpringFrame : public nsXULLeafFrame +class nsSpringFrame : public nsLeafBoxFrame { public: @@ -41,15 +42,17 @@ public: NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, - const nsPoint& aPoint, - nsFramePaintLayer aWhichLayer, - nsIFrame** aFrame); + const nsPoint& aPoint, + nsFramePaintLayer aWhichLayer, + nsIFrame** aFrame); NS_IMETHOD GetFrameName(nsString& aResult) const { aResult = "Spring"; return NS_OK; } + + nsSpringFrame(nsIPresShell* aShell):nsLeafBoxFrame(aShell) {} }; // class nsSpringFrame diff --git a/mozilla/layout/xul/base/src/nsSprocketLayout.cpp b/mozilla/layout/xul/base/src/nsSprocketLayout.cpp new file mode 100644 index 00000000000..485f706a938 --- /dev/null +++ b/mozilla/layout/xul/base/src/nsSprocketLayout.cpp @@ -0,0 +1,1368 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Pierre Phaneuf + */ + +// +// Eric Vaughan +// Netscape Communications +// +// See documentation in associated header file +// + +#include "nsBoxLayoutState.h" +#include "nsSprocketLayout.h" +#include "nsIStyleContext.h" +#include "nsIPresContext.h" +#include "nsCOMPtr.h" +#include "nsIContent.h" +#include "nsIViewManager.h" +#include "nsIView.h" +#include "nsIPresShell.h" +#include "nsHTMLContainerFrame.h" +#include "nsBoxFrame.h" +#include "nsINameSpaceManager.h" +#include "nsHTMLAtoms.h" +#include "nsXULAtoms.h" +#include "nsBoxFrame.h" + + +#define DEBUG_SPRING_SIZE 8 +#define DEBUG_BORDER_SIZE 2 +#define COIL_SIZE 8 + +nsSprocketLayout::nsSprocketLayout(nsIPresShell* aShell) +{ +} + +PRBool +nsSprocketLayout::IsHorizontal(nsIBox* aBox) const +{ + nsIFrame* frame = nsnull; + aBox->GetFrame(&frame); + nsFrameState state; + frame->GetFrameState(&state); + return state & NS_STATE_IS_HORIZONTAL; +} + +void +nsSprocketLayout::GetFrameState(nsIBox* aBox, nsFrameState& aState) +{ + nsIFrame* frame = nsnull; + aBox->GetFrame(&frame); + frame->GetFrameState(&aState); +} + +void +nsSprocketLayout::SetFrameState(nsIBox* aBox, nsFrameState aState) +{ + nsIFrame* frame = nsnull; + aBox->GetFrame(&frame); + frame->SetFrameState(aState); +} + +NS_IMETHODIMP +nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState) +{ + aState.PushStackMemory(); + + // ----- figure out our size ---------- + nsRect contentRect; + aBox->GetContentRect(contentRect); + + // -- make sure we remove our border and padding ---- + nsRect clientRect; + aBox->GetClientRect(clientRect); + + nsRect originalClientRect(clientRect); + + nsFrameState frameState = 0; + GetFrameState(aBox, frameState); + + //if (frameState & NS_STATE_CURRENTLY_IN_DEBUG) + // printf("In debug\n"); + + // ----- build a list of our child desired sizes and computeds sizes ------ + + nsBoxSize* boxSizes = nsnull; + nsComputedBoxSize* computedBoxSizes = nsnull; + + nscoord maxAscent = 0; + aBox->GetAscent(aState, maxAscent); + + nscoord minSize = 0; + nscoord maxSize = 0; + PRInt32 flexes = 0; + PopulateBoxSizes(aBox, aState, boxSizes, computedBoxSizes, minSize, maxSize, flexes); + + nscoord width = clientRect.width; + if (!IsHorizontal(aBox)) + width = clientRect.height; + + ComputeChildSizes(aState, width, boxSizes, computedBoxSizes); + + + if (IsHorizontal(aBox)) { + clientRect.width = width; + if (clientRect.height < minSize) + clientRect.height = minSize; + + if (frameState & NS_STATE_AUTO_STRETCH) { + if (clientRect.height > maxSize) + clientRect.height = maxSize; + } + } else { + clientRect.height = width; + if (clientRect.width < minSize) + clientRect.width = minSize; + + if (frameState & NS_STATE_AUTO_STRETCH) { + if (clientRect.width > maxSize) + clientRect.width = maxSize; + } + } + + // ---------------------- + // layout all children + // ---------------------- + + PRBool needsRedraw = PR_FALSE; + PRBool finished; + nscoord passes = 0; + + + // ok what we want to do if flow each child at the location given in the spring. + // unfortunately after flowing a child it might get bigger. We have not control over this + // so it the child gets bigger or smaller than we expected we will have to do a 2nd, 3rd, 4th pass to + // adjust. + + nscoord x = 0; + nscoord y = 0; + nsIBox::Halignment halign; + nsIBox::Valignment valign; + aBox->GetVAlign(valign); + aBox->GetHAlign(halign); + nscoord origX = 0; + nscoord origY = 0; + + PRBool childResized = PR_FALSE; + + + passes = 0; + do + { + #ifdef DEBUG_REFLOW + if (passes > 0) { + AddIndents(); + printf("ChildResized doing pass: %d\n", passes); + } + #endif + + finished = PR_TRUE; + + x = clientRect.x; + y = clientRect.y; + + if (!(frameState & NS_STATE_AUTO_STRETCH)) { + if (frameState & NS_STATE_IS_HORIZONTAL) { + switch(halign) { + case nsBoxFrame::hAlign_Left: + x = clientRect.x; + break; + + case nsBoxFrame::hAlign_Center: + x = clientRect.x + (originalClientRect.width - clientRect.width)/2; + break; + + case nsBoxFrame::hAlign_Right: + x = clientRect.x + (originalClientRect.width - clientRect.width); + break; + } + } else { + switch(valign) { + case nsBoxFrame::vAlign_Top: + case nsBoxFrame::vAlign_BaseLine: + y = clientRect.y; + break; + + case nsBoxFrame::vAlign_Middle: + y = clientRect.y + (originalClientRect.height - clientRect.height)/2; + break; + + case nsBoxFrame::vAlign_Bottom: + y = clientRect.y + (originalClientRect.height - clientRect.height); + break; + } + } + } + + origX = x; + origY = y; + + nscoord nextX = x; + nscoord nextY = y; + + nsComputedBoxSize* childComputedBoxSize = computedBoxSizes; + nsBoxSize* childBoxSize = boxSizes; + + nsIBox* child = nsnull; + aBox->GetChildBox(&child); + + PRInt32 count = 0; + while (child) + { + nscoord width = clientRect.width; + nscoord height = clientRect.height; + + nsSize prefSize(0,0); + nsSize minSize(0,0); + nsSize maxSize(0,0); + + if (!(frameState & NS_STATE_AUTO_STRETCH)) { + child->GetPrefSize(aState, prefSize); + child->GetMinSize(aState, minSize); + child->GetMaxSize(aState, maxSize); + nsBox::BoundsCheck(minSize, prefSize, maxSize); + + /* + if (width < minSize.width) + width = minSize.width; + if (height < minSize.height) + height = minSize.height; + */ + AddMargin(child, prefSize); + width = prefSize.width > originalClientRect.width ? originalClientRect.width : prefSize.width; + height = prefSize.height > originalClientRect.height ? originalClientRect.height : prefSize.height; + } + + // figure our our child's computed width and height + if (frameState & NS_STATE_IS_HORIZONTAL) { + width = childComputedBoxSize->size; + } else { + height = childComputedBoxSize->size; + } + + nextX = x; + nextY = y; + + nsRect childRect(x, y, width, height); + + if (!childBoxSize->collapsed) { + /* + if (childRect.width > originalClientRect.width || childRect.height > originalClientRect.height) { + if (childRect.width > originalClientRect.width) + originalClientRect.width = childRect.width; + + if (childRect.height > originalClientRect.height) + originalClientRect.height = childRect.height; + } + */ + + if (childRect.width > clientRect.width || childRect.height > clientRect.height) { + if (childRect.width > clientRect.width) + clientRect.width = childRect.width; + + if (childRect.height > clientRect.height) + clientRect.height = childRect.height; + } + } + + ComputeChildsNextPosition(aBox, child, + x, + y, + nextX, + nextY, + childRect, + originalClientRect, + childBoxSize->ascent, + maxAscent); + + + childRect.x = x; + childRect.y = y; + + nsMargin margin(0,0,0,0); + child->GetMargin(margin); + + childRect.Deflate(margin); + + PRBool layout = PR_TRUE; + + if (passes > 0) { + layout = PR_FALSE; + } else { + // always layout if we are dirty or have dirty children + PRBool dirty = PR_FALSE; + PRBool dirtyChildren = PR_FALSE; + child->IsDirty(dirty); + child->HasDirtyChildren(dirtyChildren); + if (!(dirty || dirtyChildren) && aState.GetLayoutReason() != nsBoxLayoutState::Initial) { + layout = PR_FALSE; + } + } + + nsRect oldRect(0,0,0,0); + child->GetBounds(oldRect); + child->SetBounds(aState, childRect); + + + + PRBool sizeChanged = (childRect.width != oldRect.width || childRect.height != oldRect.height); + + if (sizeChanged) { + nsSize maxSize; + child->GetMaxSize(aState, maxSize); + + // make sure the size is in our max size. + if (childRect.width > maxSize.width) + childRect.width = maxSize.width; + + if (childRect.height > maxSize.height) + childRect.height = maxSize.height; + + // set it again + child->SetBounds(aState, childRect); + + needsRedraw = PR_TRUE; + } + + if (childBoxSize) + if(!childBoxSize->collapsed) + child->UnCollapse(aState); + + if (layout || sizeChanged) { + child->Layout(aState); + } + + // make collapsed children not show up + if (childBoxSize && childBoxSize->collapsed) { + child->Collapse(aState); + } else { + // if the child was html it may have changed its rect. Lets look + nsRect newChildRect; + child->GetBounds(newChildRect); + + if (newChildRect != childRect) + { + newChildRect.Inflate(margin); + childRect.Inflate(margin); + + // ok the child changed size + ChildResized(aBox, + aState, + child, + childBoxSize, + childComputedBoxSize, + boxSizes, + computedBoxSizes, + childRect, + newChildRect, + clientRect, + flexes, + finished); + + childResized = PR_TRUE; + + if (clientRect.width > originalClientRect.width || clientRect.height > originalClientRect.height) { + if (clientRect.width > originalClientRect.width) + originalClientRect.width = clientRect.width; + + if (clientRect.height > originalClientRect.height) + originalClientRect.height = clientRect.height; + } + + + // if the child resized then recompute it position. + ComputeChildsNextPosition(aBox, child, + x, + y, + nextX, + nextY, + newChildRect, + originalClientRect, + childBoxSize->ascent, + maxAscent); + + newChildRect.x = x; + newChildRect.y = y; + + newChildRect.Deflate(margin); + childRect.Deflate(margin); + + child->SetBounds(aState, newChildRect); + + // if we are the first we don't need to do a second pass + if (count == 0) + finished = PR_TRUE; + } + + + x = nextX; + y = nextY; + } + + childComputedBoxSize = childComputedBoxSize->next; + childBoxSize = childBoxSize->next; + + child->GetNextBox(&child); + count++; + } + + passes++; + if (passes > 10) { + break; + } + } while (PR_FALSE == finished); + + while(boxSizes) + { + nsBoxSize* toDelete = boxSizes; + boxSizes = boxSizes->next; + delete toDelete; + } + + while(computedBoxSizes) + { + nsComputedBoxSize* toDelete = computedBoxSizes; + computedBoxSizes = computedBoxSizes->next; + delete toDelete; + } + + if (childResized) { + // see if one of our children forced us to get bigger + nsRect tmpClientRect(originalClientRect); + nsMargin bp(0,0,0,0); + aBox->GetBorderAndPadding(bp); + tmpClientRect.Inflate(bp); + aBox->GetInset(bp); + tmpClientRect.Inflate(bp); + + if (tmpClientRect.width > contentRect.width || tmpClientRect.height > contentRect.height) + { + // if it did reset our bounds. + nsRect bounds(0,0,0,0); + aBox->GetBounds(bounds); + if (tmpClientRect.width > contentRect.width) + bounds.width = tmpClientRect.width; + + if (tmpClientRect.height > contentRect.height) + bounds.height = tmpClientRect.height; + + aBox->SetBounds(aState, bounds); + } + } + + x = clientRect.x; + y = clientRect.y; + + if (!(frameState & NS_STATE_AUTO_STRETCH)) { + if (frameState & NS_STATE_IS_HORIZONTAL) { + switch(halign) { + case nsBoxFrame::hAlign_Left: + x = clientRect.x; + break; + + case nsBoxFrame::hAlign_Center: + x = clientRect.x + (originalClientRect.width - clientRect.width)/2; + break; + + case nsBoxFrame::hAlign_Right: + x = clientRect.x + (originalClientRect.width - clientRect.width); + break; + } + } else { + switch(valign) { + case nsBoxFrame::vAlign_Top: + case nsBoxFrame::vAlign_BaseLine: + y = clientRect.y; + break; + + case nsBoxFrame::vAlign_Middle: + y = clientRect.y + (originalClientRect.height - clientRect.height)/2; + break; + + case nsBoxFrame::vAlign_Bottom: + y = clientRect.y + (originalClientRect.height - clientRect.height); + break; + } + } + } + + if (x != origX || y != origY) { + nsIBox* child = nsnull; + // reposition all our children + aBox->GetChildBox(&child); + + while (child) + { + nsRect childRect; + child->GetBounds(childRect); + childRect.x += (x - origX); + childRect.y += (y - origY); + child->SetBounds(aState, childRect); + child->GetNextBox(&child); + } + + } + + if (needsRedraw) + aBox->Redraw(aState); + + aState.PopStackMemory(); + + return NS_OK; +} + +void +nsSprocketLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBoxSize*& aBoxSizes, nsComputedBoxSize*& aComputedBoxSizes, nscoord& aMinSize, nscoord& aMaxSize, PRInt32& aFlexes) +{ + nsFrameState frameState = 0; + GetFrameState(aBox, frameState); + + //if (frameState & NS_STATE_CURRENTLY_IN_DEBUG) + // printf("In debug\n"); + + aMinSize = 0; + aMaxSize = NS_INTRINSICSIZE; + + PRBool isHorizontal; + + if (IsHorizontal(aBox)) + isHorizontal = PR_TRUE; + else + isHorizontal = PR_FALSE; + + // this is a nice little optimization + // it turns out that if we only have 1 flexable child + // then it does not matter what its prefered size is + // there is nothing to flex it relative. This is great + // because we can avoid asking for a preferred size in this + // case. Why is this good? Well you might have html inside it + // and asking html for its preferred size is rather expensive. + // so we can just optimize it out this way. + + // set flexes + nsIBox* child = nsnull; + aBox->GetChildBox(&child); + + PRInt32 count = 0; + aFlexes = 0; + nsBoxSize* currentBox = nsnull; + nsComputedBoxSize* currentComputed = nsnull; + + while(child) + { + if (!currentBox) { + aBoxSizes = new (aState) nsBoxSize(); + aComputedBoxSizes = new (aState) nsComputedBoxSize(); + + currentBox = aBoxSizes; + currentComputed = aComputedBoxSizes; + } else { + currentBox->next = new (aState) nsBoxSize(); + currentComputed->next = new (aState) nsComputedBoxSize(); + + currentBox = currentBox->next; + currentComputed = currentComputed->next; + } + + nscoord flex = 0; + child->GetFlex(aState, flex); + PRBool collapsed = PR_FALSE; + child->IsCollapsed(aState, collapsed); + + currentBox->flex = flex; + currentBox->collapsed = collapsed; + currentComputed->resized = PR_FALSE; + currentComputed->size = 0; + + if (flex > 0) + aFlexes++; + + child->GetNextBox(&child); + } + + // get pref, min, max + aBox->GetChildBox(&child); + currentBox = aBoxSizes; + while(child) + { + nsSize pref(0,0); + nsSize min(0,0); + nsSize max(0,0); + + // only one flexible child? Cool we will just make its preferred size + // 0 then and not even have to ask for it. + //if (flexes != 1) { + child->GetPrefSize(aState, pref); + child->GetAscent(aState, currentBox->ascent); + nsMargin margin; + child->GetMargin(margin); + currentBox->ascent += margin.top + margin.bottom; + //} + + child->GetMinSize(aState, min); + child->GetMaxSize(aState, max); + nsBox::BoundsCheck(min, pref, max); + + AddMargin(child, pref); + AddMargin(child, min); + AddMargin(child, max); + + nscoord minWidth = min.width; + nscoord maxWidth = max.width; + nscoord prefWidth = pref.width; + + if (!isHorizontal) { + minWidth = min.height; + maxWidth = max.height; + prefWidth = pref.height; + if (min.width > aMinSize) + aMinSize = min.width; + + if (max.width < aMaxSize) + aMaxSize = max.width; + + } else { + if (min.height > aMinSize) + aMinSize = min.height; + + if (max.height < aMaxSize) + aMaxSize = max.height; + } + + NS_ASSERTION(minWidth <= prefWidth && prefWidth <= maxWidth,"Bad min, pref, max widths!"); + + /* + if (minWidth > maxWidth) + minWidth = maxWidth; + + if (prefWidth > maxWidth) + prefWidth = maxWidth; + + if (prefWidth < minWidth) + prefWidth = minWidth; + */ + + currentBox->pref = prefWidth; + currentBox->min = minWidth; + currentBox->max = maxWidth; + + child->GetNextBox(&child); + currentBox = currentBox->next; + } +} + +void +nsSprocketLayout::ComputeChildsNextPosition(nsIBox* aBox, + nsIBox* aChild, + nscoord& aCurX, + nscoord& aCurY, + nscoord& aNextX, + nscoord& aNextY, + const nsRect& aCurrentChildSize, + const nsRect& aBoxRect, + nscoord childAscent, + nscoord aMaxAscent) +{ + nsFrameState frameState = 0; + GetFrameState(aBox, frameState); + + nsIBox::Halignment halign; + nsIBox::Valignment valign; + aBox->GetVAlign(valign); + aBox->GetHAlign(halign); + + if (IsHorizontal(aBox)) { + aNextX = aCurX + aCurrentChildSize.width; + + if (frameState & NS_STATE_AUTO_STRETCH) { + aCurY = aBoxRect.y; + } else { + switch (valign) + { + case nsBoxFrame::vAlign_BaseLine: + aCurY = aBoxRect.y + (aMaxAscent - childAscent); + break; + + case nsBoxFrame::vAlign_Top: + aCurY = aBoxRect.y; + break; + case nsBoxFrame::vAlign_Middle: + aCurY = aBoxRect.y + (aBoxRect.height/2 - aCurrentChildSize.height/2); + break; + case nsBoxFrame::vAlign_Bottom: + aCurY = aBoxRect.y + aBoxRect.height - aCurrentChildSize.height; + break; + } + } + } else { + aNextY = aCurY + aCurrentChildSize.height; + if (frameState & NS_STATE_AUTO_STRETCH) { + aCurX = aBoxRect.x; + } else { + switch (halign) + { + case nsBoxFrame::hAlign_Left: + aCurX = aBoxRect.x; + break; + case nsBoxFrame::hAlign_Center: + aCurX = aBoxRect.x + (aBoxRect.width/2 - aCurrentChildSize.width/2); + break; + case nsBoxFrame::hAlign_Right: + aCurX = aBoxRect.x + aBoxRect.width - aCurrentChildSize.width; + break; + } + } + } +} + +void +nsSprocketLayout::ChildResized(nsIBox* aBox, + nsBoxLayoutState& aState, + nsIBox* aChild, + nsBoxSize* aChildBoxSize, + nsComputedBoxSize* aChildComputedSize, + nsBoxSize* aBoxSizes, + nsComputedBoxSize* aComputedBoxSizes, + const nsRect& aChildLayoutRect, + nsRect& aChildActualRect, + nsRect& aContainingRect, + PRInt32 aFlexes, + PRBool& aFinished) + +{ + nsRect childCurrentRect(aChildLayoutRect); + + PRBool isHorizontal = IsHorizontal(aBox); + nscoord childLayoutWidth = GET_WIDTH(aChildLayoutRect,isHorizontal); + nscoord& childActualWidth = GET_WIDTH(aChildActualRect,isHorizontal); + nscoord& containingWidth = GET_WIDTH(aContainingRect,isHorizontal); + + nscoord childLayoutHeight = GET_HEIGHT(aChildLayoutRect,isHorizontal); + nscoord& childActualHeight = GET_HEIGHT(aChildActualRect,isHorizontal); + nscoord& containingHeight = GET_HEIGHT(aContainingRect,isHorizontal); + + PRBool recompute = PR_FALSE; + + // if we are a horizontal box see if the child will fit inside us. + if ( childActualHeight > containingHeight) { + // if we are a horizontal box and the the child it bigger than our height + + // ok if the height changed then we need to reflow everyone but us at the new height + // so we will set the changed index to be us. And signal that we need a new pass. + + nsSize max(0,0); + aChild->GetMaxSize(aState, max); + + if (isHorizontal) + childActualHeight = max.height < childActualHeight ? max.height : childActualHeight; + else + childActualHeight = max.width < childActualHeight ? max.width : childActualHeight; + + // only set if it changes + if (childActualHeight > containingHeight) { + containingHeight = childActualHeight; + + // remember we do not need to clear the resized list because changing the height of a horizontal box + // will not affect the width of any of its children because block flow left to right, top to bottom. Just trust me + // on this one. + aFinished = PR_FALSE; + + // only recompute if there are flexes. + if (aFlexes > 0) { + // relayout everything + recompute = PR_TRUE; + InvalidateComputedSizes(aComputedBoxSizes); + nsComputedBoxSize* node = aComputedBoxSizes; + + while(node) { + node->resized = PR_FALSE; + node = node->next; + } + + } + } + } + + if (childActualWidth > childLayoutWidth) { + nsSize max(0,0); + aChild->GetMaxSize(aState, max); + + // our width now becomes the new size + + if (isHorizontal) + childActualWidth = max.width < childActualWidth ? max.width : childActualWidth; + else + childActualWidth = max.height < childActualWidth ? max.height : childActualWidth; + + if (childActualWidth > childLayoutWidth) { + aChildComputedSize->size = childActualWidth; + aChildBoxSize->min = childActualWidth; + if (aChildBoxSize->pref < childActualWidth) + aChildBoxSize->pref = childActualWidth; + + // if we have flexible elements with us then reflex things. Otherwise we can skip doing it. + if (aFlexes > 0) { + InvalidateComputedSizes(aComputedBoxSizes); + + nsComputedBoxSize* node = aComputedBoxSizes; + aChildComputedSize->resized = PR_TRUE; + + while(node) { + if (node->resized) + node->valid = PR_TRUE; + + node = node->next; + } + + recompute = PR_TRUE; + aFinished = PR_FALSE; + } else { + containingWidth += aChildComputedSize->size - childLayoutWidth; + } + } + } + + if (recompute) + ComputeChildSizes(aState, containingWidth, aBoxSizes, aComputedBoxSizes); + + if (childCurrentRect != aChildActualRect) { + aChild->SetBounds(aState, aChildActualRect); + aChild->Layout(aState); + } + +} + +void +nsSprocketLayout::InvalidateComputedSizes(nsComputedBoxSize* aComputedBoxSizes) +{ + while(aComputedBoxSizes) { + aComputedBoxSizes->valid = PR_FALSE; + aComputedBoxSizes = aComputedBoxSizes->next; + } +} + + +void +nsSprocketLayout::ComputeChildSizes(nsBoxLayoutState& aState, + nscoord& aGivenSize, + nsBoxSize* aBoxSizes, + nsComputedBoxSize* aComputedBoxSizes) +{ + PRInt32 sizeRemaining = aGivenSize; + PRInt32 springConstantsRemaining = 0; + + // ----- calculate the springs constants and the size remaining ----- + + nsBoxSize* boxSizes = aBoxSizes; + nsComputedBoxSize* computedBoxSizes = aComputedBoxSizes; + PRInt32 count = 0; + PRInt32 validCount = 0; + + while (boxSizes || computedBoxSizes) + { + NS_ASSERTION(!boxSizes || (boxSizes->min <= boxSizes->pref && boxSizes->pref <= boxSizes->max),"bad pref, min, max size"); + + // ignore collapsed children + if (boxSizes && boxSizes->collapsed) + { + computedBoxSizes->valid = PR_TRUE; + computedBoxSizes->size = boxSizes->pref; + validCount++; + } else { + if (computedBoxSizes && computedBoxSizes->valid) { + sizeRemaining -= computedBoxSizes->size; + validCount++; + } else { + if (boxSizes) { + if (boxSizes->flex == 0) + { + computedBoxSizes->valid = PR_TRUE; + computedBoxSizes->size = boxSizes->pref; + validCount++; + } + + springConstantsRemaining += boxSizes->flex; + sizeRemaining -= boxSizes->pref; + } + } + } + + boxSizes = boxSizes->next; + computedBoxSizes = computedBoxSizes->next; + count++; + } + + // everything accounted for? + if (validCount < count) + { + // ----- Ok we are give a size to fit into so stretch or squeeze to fit + // ----- Make sure we look at our min and max size + PRBool limit = PR_TRUE; + for (int pass=1; PR_TRUE == limit; pass++) + { + limit = PR_FALSE; + boxSizes = aBoxSizes; + computedBoxSizes = aComputedBoxSizes; + + while (boxSizes || computedBoxSizes) { + + // ignore collapsed springs + + if (!(boxSizes && boxSizes->collapsed)) { + + nscoord pref = 0; + nscoord max = NS_INTRINSICSIZE; + nscoord min = 0; + nscoord flex = 0; + + if (boxSizes) + { + pref = boxSizes->pref; + min = boxSizes->min; + max = boxSizes->max; + flex = boxSizes->flex; + } + + // ----- look at our min and max limits make sure we aren't too small or too big ----- + if (!(computedBoxSizes && computedBoxSizes->valid)) { + PRInt32 newSize = pref + (sizeRemaining*flex/springConstantsRemaining); + if (newSize<=min) { + + if (computedBoxSizes) { + computedBoxSizes->size = min; + computedBoxSizes->valid = PR_TRUE; + } + + springConstantsRemaining -= flex; + sizeRemaining += pref; + sizeRemaining -= min; + limit = PR_TRUE; + } else if (newSize>=max) { + if (computedBoxSizes) { + computedBoxSizes->size = max; + computedBoxSizes->valid = PR_TRUE; + } + springConstantsRemaining -= flex; + sizeRemaining += pref; + sizeRemaining -= max; + limit = PR_TRUE; + } + } + } + boxSizes = boxSizes->next; + computedBoxSizes = computedBoxSizes->next; + } + } + } + + // ---- once we have removed and min and max issues just stretch us out in the remaining space + // ---- or shrink us. Depends on the size remaining and the spring constants + aGivenSize = 0; + boxSizes = aBoxSizes; + computedBoxSizes = aComputedBoxSizes; + + while (boxSizes || computedBoxSizes) { + + // ignore collapsed springs + if (!(boxSizes && boxSizes->collapsed)) { + + nscoord pref = 0; + nscoord flex = 0; + if (boxSizes) { + pref = boxSizes->pref; + flex = boxSizes->flex; + } + + if (computedBoxSizes) { + if (!computedBoxSizes->valid) { + computedBoxSizes->size = pref + flex*sizeRemaining/springConstantsRemaining; + computedBoxSizes->valid = PR_TRUE; + } + + aGivenSize += computedBoxSizes->size; + } + } + + boxSizes = boxSizes->next; + computedBoxSizes = computedBoxSizes->next; + } +} + + +NS_IMETHODIMP +nsSprocketLayout::GetPrefSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSize) +{ + PRBool isHorizontal = IsHorizontal(aBox); + + aSize.width = 0; + aSize.height = 0; + + // run through all the children and get there min, max, and preferred sizes + // return us the size of the box + + nsIBox* child = nsnull; + aBox->GetChildBox(&child); + + while (child) + { + // ignore collapsed children + PRBool isCollapsed = PR_FALSE; + child->IsCollapsed(aState, isCollapsed); + + if (!isCollapsed) + { + nsSize pref(0,0); + child->GetPrefSize(aState, pref); + AddMargin(child, pref); + AddLargestSize(aSize, pref, isHorizontal); + } + + child->GetNextBox(&child); + } + + // now add our border and padding and insets + AddBorderAndPadding(aBox, aSize); + AddInset(aBox, aSize); + + return NS_OK; +} + +NS_IMETHODIMP +nsSprocketLayout::GetMinSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSize) +{ + PRBool isHorizontal = IsHorizontal(aBox); + + + aSize.width = 0; + aSize.height = 0; + + // run through all the children and get there min, max, and preferred sizes + // return us the size of the box + + nsIBox* child = nsnull; + aBox->GetChildBox(&child); + + while (child) + { + // ignore collapsed children + PRBool isCollapsed = PR_FALSE; + aBox->IsCollapsed(aState, isCollapsed); + + if (!isCollapsed) + { + nsSize min(0,0); + nsSize pref(0,0); + nscoord flex = 0; + + child->GetMinSize(aState, min); + child->GetFlex(aState, flex); + + // if the child is not flexible then + // its min size is its pref size. + if (flex == 0) { + child->GetPrefSize(aState, pref); + if (isHorizontal) + min.width = pref.width; + else + min.height = pref.height; + } + + AddMargin(child, min); + AddLargestSize(aSize, min, isHorizontal); + } + + child->GetNextBox(&child); + } + +// now add our border and padding and insets + AddBorderAndPadding(aBox, aSize); + AddInset(aBox,aSize); + + return NS_OK; +} + +NS_IMETHODIMP +nsSprocketLayout::GetMaxSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSize) +{ + + PRBool isHorizontal = IsHorizontal(aBox); + + + aSize.width = NS_INTRINSICSIZE; + aSize.height = NS_INTRINSICSIZE; + + // run through all the children and get there min, max, and preferred sizes + // return us the size of the box + + + nsIBox* child = nsnull; + aBox->GetChildBox(&child); + + while (child) + { + // ignore collapsed children + PRBool isCollapsed = PR_FALSE; + aBox->IsCollapsed(aState, isCollapsed); + + if (!isCollapsed) + { + // if completely redefined don't even ask our child for its size. + nsSize max(NS_INTRINSICSIZE, NS_INTRINSICSIZE); + child->GetMaxSize(aState, max); + + AddMargin(child, max); + AddSmallestSize(aSize, max, isHorizontal); + } + + child->GetNextBox(&child); + + } + + // now add our border and padding and insets + AddBorderAndPadding(aBox, aSize); + AddInset(aBox, aSize); + + return NS_OK; +} + + +NS_IMETHODIMP +nsSprocketLayout::GetAscent(nsIBox* aBox, nsBoxLayoutState& aState, nscoord& aAscent) +{ + + PRBool isHorizontal = IsHorizontal(aBox); + + aAscent = 0; + + // run through all the children and get there min, max, and preferred sizes + // return us the size of the box + + nsIBox* child = nsnull; + aBox->GetChildBox(&child); + + while (child) + { + // ignore collapsed children + PRBool isCollapsed = PR_FALSE; + aBox->IsCollapsed(aState, isCollapsed); + + if (!isCollapsed) + { + // if completely redefined don't even ask our child for its size. + nscoord ascent = 0; + child->GetAscent(aState, ascent); + + nsMargin margin; + child->GetMargin(margin); + ascent += margin.top + margin.bottom; + + if (isHorizontal) + { + if (ascent > aAscent) + aAscent = ascent; + } else { + if (aAscent == 0) + aAscent = ascent; + } + } + child->GetNextBox(&child); + + } + + return NS_OK; +} + +NS_IMETHODIMP +nsSprocketLayout::GetFlex(nsIBox* aBox, nsBoxLayoutState& aState, nscoord& aFlex) +{ + return aBox->GetFlex(aState, aFlex); +} + + +NS_IMETHODIMP +nsSprocketLayout::IsCollapsed(nsIBox* aBox, nsBoxLayoutState& aState, PRBool& IsCollapsed) +{ + return aBox->IsCollapsed(aState, IsCollapsed); +} + +void +nsSprocketLayout::SetLargestSize(nsSize& aSize1, const nsSize& aSize2, PRBool aIsHorizontal) +{ + if (aIsHorizontal) + { + if (aSize1.height < aSize2.height) + aSize1.height = aSize2.height; + } else { + if (aSize1.width < aSize2.width) + aSize1.width = aSize2.width; + } +} + +void +nsSprocketLayout::SetSmallestSize(nsSize& aSize1, const nsSize& aSize2, PRBool aIsHorizontal) +{ + if (aIsHorizontal) + { + if (aSize1.height > aSize2.height) + aSize1.height = aSize2.height; + } else { + if (aSize1.width > aSize2.width) + aSize1.width = aSize2.width; + + } +} + +void +nsSprocketLayout::AddLargestSize(nsSize& aSize, const nsSize& aSizeToAdd, PRBool aIsHorizontal) +{ + if (aIsHorizontal) + AddCoord(aSize.width, aSizeToAdd.width); + else + AddCoord(aSize.height, aSizeToAdd.height); + + SetLargestSize(aSize, aSizeToAdd, aIsHorizontal); +} + +void +nsSprocketLayout::AddCoord(nscoord& aCoord, nscoord aCoordToAdd) +{ + if (aCoord != NS_INTRINSICSIZE) + { + if (aCoordToAdd == NS_INTRINSICSIZE) + aCoord = aCoordToAdd; + else + aCoord += aCoordToAdd; + } +} +void +nsSprocketLayout::AddSmallestSize(nsSize& aSize, const nsSize& aSizeToAdd, PRBool aIsHorizontal) +{ + if (aIsHorizontal) + AddCoord(aSize.width, aSizeToAdd.width); + else + AddCoord(aSize.height, aSizeToAdd.height); + + SetSmallestSize(aSize, aSizeToAdd, aIsHorizontal); +} + +PRBool +nsSprocketLayout::GetDefaultFlex(PRInt32& aFlex) +{ + aFlex = 0; + return PR_TRUE; +} + +void +nsBoxSize::Add(nsSize minSize, + nsSize prefSize, + nsSize maxSize, + nscoord ascent, + nscoord flex, + PRBool aIsHorizontal) +{ + nscoord pref2; + nscoord min2; + nscoord max2; + + if (aIsHorizontal) { + pref2 = prefSize.width; + min2 = minSize.width; + max2 = maxSize.width; + } else { + pref2 = prefSize.height; + min2 = minSize.height; + max2 = maxSize.height; + } + + if (min2 > min) + min = min2; + + if (pref2 > pref) + pref = pref2; + + if (max2 < max) + max = max2; +} + +void +nsBoxSize::Add(const nsMargin& aMargin, PRBool aIsHorizontal) +{ + if (aIsHorizontal) { + left += aMargin.left; + right += aMargin.right; + } else { + left += aMargin.top; + right += aMargin.bottom; + } +} + +nsComputedBoxSize::nsComputedBoxSize() +{ + resized = PR_FALSE; + valid = PR_FALSE; + size = 0; + next = nsnull; +} + +nsBoxSize::nsBoxSize() +{ + pref = 0; + min = 0; + max = NS_INTRINSICSIZE; + collapsed = PR_FALSE; + ascent = 0; + left = 0; + right = 0; + flex = 0; + next = nsnull; +} + + +void* +nsBoxSize::operator new(size_t sz, nsBoxLayoutState& aState) +{ + void* mem = 0; + aState.AllocateStackMemory(sz,&mem); + return mem; +} + + +void +nsBoxSize::operator delete(void* aPtr, size_t sz) +{ +} + + +void* +nsComputedBoxSize::operator new(size_t sz, nsBoxLayoutState& aState) +{ + + void* mem = 0; + aState.AllocateStackMemory(sz,&mem); + return mem; +} + +void +nsComputedBoxSize::operator delete(void* aPtr, size_t sz) +{ +} diff --git a/mozilla/layout/xul/base/src/nsSprocketLayout.h b/mozilla/layout/xul/base/src/nsSprocketLayout.h new file mode 100644 index 00000000000..c063ff7d2c1 --- /dev/null +++ b/mozilla/layout/xul/base/src/nsSprocketLayout.h @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Author: + * Eric D Vaughan + * + * Contributor(s): + */ + +#ifndef nsSprocketLayout_h___ +#define nsSprocketLayout_h___ + +#include "nsBoxLayout.h" + +class nsBoxSize +{ +public: + + nsBoxSize(); + + nscoord pref; + nscoord min; + nscoord max; + nscoord ascent; + nscoord flex; + nscoord left; + nscoord right; + PRBool collapsed; + + nsBoxSize* next; + + void Add(nsSize minSize, + nsSize prefSize, + nsSize maxSize, + nscoord ascent, + nscoord flex, + PRBool aIsHorizontal); + + void Add(const nsMargin& aMargin, PRBool aIsHorizontal); + + void* operator new(size_t sz, nsBoxLayoutState& aState); + void operator delete(void* aPtr, size_t sz); +}; + +class nsComputedBoxSize +{ +public: + nsComputedBoxSize(); + + nscoord size; + PRBool valid; + PRBool resized; + nsComputedBoxSize* next; + + void* operator new(size_t sz, nsBoxLayoutState& aState); + void operator delete(void* aPtr, size_t sz); +}; + + +#define GET_WIDTH(size, isHorizontal) (isHorizontal ? size.width : size.height) +#define GET_HEIGHT(size, isHorizontal) (isHorizontal ? size.height : size.width) +#define GET_X(size, isHorizontal) (isHorizontal ? size.x : size.y) +#define GET_Y(size, isHorizontal) (isHorizontal ? size.y : size.x) +#define GET_COORD(aX, aY, isHorizontal) (isHorizontal ? aX : aY) + +#define SET_WIDTH(size, coord, isHorizontal) if (isHorizontal) { (size).width = (coord); } else { (size).height = (coord); } +#define SET_HEIGHT(size, coord, isHorizontal) if (isHorizontal) { (size).height = (coord); } else { (size).width = (coord); } +#define SET_X(size, coord, isHorizontal) if (isHorizontal) { (size).x = (coord); } else { (size).y = (coord); } +#define SET_Y(size, coord, isHorizontal) if (isHorizontal) { (size).y = (coord); } else { (size).x = (coord); } + +#define SET_COORD(aX, aY, coord, isHorizontal) if (isHorizontal) { aX = (coord); } else { aY = (coord); } + + +class nsBoxSizeList +{ +public: + virtual nsBoxSize* GetBoxSize(nsBoxLayoutState& aState)=0; + virtual nsBoxSizeList* GetFirst()=0; + virtual nsBoxSizeList* GetLast()=0; + virtual nsBoxSizeList* GetNext()=0; + virtual nsBoxSizeList* GetParent()=0; + virtual void SetParent(nsBoxSizeList* aParent)=0; + virtual void SetNext(nsIPresShell* aShell, nsBoxSizeList* aNext)=0; + virtual void Append(nsIPresShell* aShell, nsBoxSizeList* aChild)=0; + virtual void Clear(nsIPresShell* aShell)=0; + virtual PRInt32 GetCount()=0; + virtual void Desecrate()=0; + virtual void AddRef()=0; + virtual void Release(nsIPresShell* aShell)=0; +}; + +class nsSprocketLayout : public nsBoxLayout { + +public: + + + NS_IMETHOD Layout(nsIBox* aBox, nsBoxLayoutState& aState); + + NS_IMETHOD GetPrefSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMinSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMaxSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetFlex(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nscoord& aFlex); + NS_IMETHOD GetAscent(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent); + NS_IMETHOD IsCollapsed(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, PRBool& aCollapsed); + + nsSprocketLayout(nsIPresShell* aShell); + +protected: + + virtual PRBool IsHorizontal(nsIBox* aBox) const; + virtual void SetLargestSize(nsSize& aSize1, const nsSize& aSize2, PRBool aIsHorizontal); + virtual void SetSmallestSize(nsSize& aSize1, const nsSize& aSize2, PRBool aIsHorizontal); + virtual void AddLargestSize(nsSize& aSize, const nsSize& aSizeToAdd, PRBool aIsHorizontal); + virtual void AddSmallestSize(nsSize& aSize, const nsSize& aSizeToAdd, PRBool aIsHorizontal); + virtual void AddCoord(nscoord& aCoord, nscoord aCoordToAdd); + + virtual void ComputeChildsNextPosition(nsIBox* aBox, + nsIBox* aChild, + nscoord& aCurX, + nscoord& aCurY, + nscoord& aNextX, + nscoord& aNextY, + const nsRect& aChildSize, + const nsRect& aContainingRect, + nscoord childAscent, + nscoord aMaxAscent); + + virtual void ChildResized(nsIBox* aBox, + nsBoxLayoutState& aState, + nsIBox* aChild, + nsBoxSize* aChildBoxSize, + nsComputedBoxSize* aChildComputedBoxSize, + nsBoxSize* aBoxSizes, + nsComputedBoxSize* aComputedBoxSizes, + const nsRect& aChildLayoutRect, + nsRect& aChildActualRect, + nsRect& aContainingRect, + PRInt32 aFlexes, + PRBool& aFinished); + + virtual void ComputeChildSizes(nsBoxLayoutState& aState, + nscoord& aGivenSize, + nsBoxSize* aBoxSizes, + nsComputedBoxSize* aComputedBoxSizes); + + + virtual void PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsBoxSize*& aBoxSizes, nsComputedBoxSize*& aComputedBoxSizes, nscoord& aMinSize, nscoord& aMaxSize, PRInt32& aFlexes); + + virtual void InvalidateComputedSizes(nsComputedBoxSize* aComputedBoxSizes); + + virtual PRBool GetDefaultFlex(PRInt32& aFlex); + + virtual void GetFrameState(nsIBox* aBox, nsFrameState& aState); + virtual void SetFrameState(nsIBox* aBox, nsFrameState aState); + +}; + +#endif + diff --git a/mozilla/layout/xul/base/src/nsStackFrame.cpp b/mozilla/layout/xul/base/src/nsStackFrame.cpp index 686225cc432..8bdb7716e2c 100644 --- a/mozilla/layout/xul/base/src/nsStackFrame.cpp +++ b/mozilla/layout/xul/base/src/nsStackFrame.cpp @@ -43,7 +43,8 @@ #include "nsStyleChangeList.h" #include "nsCSSRendering.h" #include "nsIViewManager.h" - +#include "nsBoxLayoutState.h" +#include "nsStackLayout.h" nsresult NS_NewStackFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) @@ -59,108 +60,32 @@ NS_NewStackFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) *aNewFrame = it; return NS_OK; -} // NS_NewDeckFrame +} // NS_NewStackFrame + +nsCOMPtr nsStackFrame::gLayout = nsnull; nsStackFrame::nsStackFrame(nsIPresShell* aPresShell):nsBoxFrame(aPresShell) { + if (!gLayout) + gLayout = new nsStackLayout(aPresShell); + + SetLayoutManager(gLayout); } -NS_IMETHODIMP -nsStackFrame::Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) -{ - // Get the element's tag - nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - return rv; -} - -void -nsStackFrame::AddChildSize(nsBoxInfo& aInfo, nsBoxInfo& aChildInfo) -{ - // largest preferred size - if (aChildInfo.prefSize.width > aInfo.prefSize.width) - aInfo.prefSize.width = aChildInfo.prefSize.width; - - if (aChildInfo.prefSize.height > aInfo.prefSize.height) - aInfo.prefSize.height = aChildInfo.prefSize.height; - - // largest min size - if (aChildInfo.minSize.width > aInfo.minSize.width) - aInfo.minSize.width = aChildInfo.minSize.width; - - if (aChildInfo.minSize.height > aInfo.minSize.height) - aInfo.minSize.height = aChildInfo.minSize.height; - - // smallest max size - if (aChildInfo.maxSize.width < aInfo.maxSize.width) - aInfo.maxSize.width = aChildInfo.maxSize.width; - - if (aChildInfo.maxSize.height < aInfo.maxSize.height) - aInfo.maxSize.height = aChildInfo.maxSize.height; -} - - -void -nsStackFrame::ComputeChildsNextPosition(nsCalculatedBoxInfo* aInfo, nscoord& aCurX, nscoord& aCurY, nscoord& aNextX, nscoord& aNextY, const nsSize& aCurrentChildSize, const nsRect& aBoxRect, nscoord aMaxAscent) -{ - // let everything layout on top of each other. - aCurX = aNextX = aBoxRect.x; - aCurY = aNextY = aBoxRect.y; -} - -void -nsStackFrame::ChildResized(nsIFrame* aFrame, nsHTMLReflowMetrics& aDesiredSize, nsRect& aRect, nscoord& aMaxAscent, nsCalculatedBoxInfo& aInfo, PRBool*& aResized, PRInt32 aInfoCount, nscoord& aChangedIndex, PRBool& aFinished, nscoord aIndex, nsString& aReason) -{ - if (aDesiredSize.width > aRect.width) { - aRect.width = aDesiredSize.width; - InvalidateChildren(); - LayoutChildrenInRect(aRect, aMaxAscent); - aReason = "child's width got bigger"; - aChangedIndex = aIndex; - aFinished = PR_FALSE; - } else if (aDesiredSize.height > aRect.height) { - aRect.height = aDesiredSize.height; - InvalidateChildren(); - LayoutChildrenInRect(aRect, aMaxAscent); - aReason = "child's height got bigger"; - aChangedIndex = aIndex; - aFinished = PR_FALSE; - } -} - -void -nsStackFrame::LayoutChildrenInRect(nsRect& aGivenSize, nscoord& aMaxAscent) -{ - nsInfoList* list = GetInfoList(); - nsCalculatedBoxInfo* info = list->GetFirst(); - - while(info) { - info->calculatedSize.width = aGivenSize.width; - info->calculatedSize.height = aGivenSize.height; - info->mFlags |= NS_FRAME_BOX_SIZE_VALID; - info = info->next; - } - - aMaxAscent = 0; -} - NS_IMETHODIMP nsStackFrame::GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, - nsFramePaintLayer aWhichLayer, + nsFramePaintLayer aWhichLayer, nsIFrame** aFrame) { + return nsBoxFrame::GetFrameForPoint(aPresContext, aPoint, aWhichLayer, aFrame); + + /* nsRect r(mRect); - // if it is not inside us or not in the layer in which we paint, fail - if ((aWhichLayer != NS_FRAME_PAINT_LAYER_BACKGROUND) || - (!r.Contains(aPoint))) { - return NS_ERROR_FAILURE; - } + if (!r.Contains(aPoint)) + return NS_ERROR_FAILURE; // is it inside our border, padding, and debugborder or insets? nsMargin im(0,0,0,0); @@ -209,6 +134,7 @@ nsStackFrame::GetFrameForPoint(nsIPresContext* aPresContext, } } + #ifdef NS_DEBUG printf("\n------------"); @@ -217,8 +143,9 @@ nsStackFrame::GetFrameForPoint(nsIPresContext* aPresContext, printf("--------------\n"); #endif - return rv; + return rv; + */ } @@ -278,4 +205,3 @@ nsStackFrame::PaintChild(nsIPresContext* aPresContext, nsBoxFrame::PaintChild(aPresContext, aRenderingContext, aDirtyRect, aFrame, NS_FRAME_PAINT_LAYER_FOREGROUND); } } - diff --git a/mozilla/layout/xul/base/src/nsStackFrame.h b/mozilla/layout/xul/base/src/nsStackFrame.h index 638428eed05..68c3e3cf6e5 100644 --- a/mozilla/layout/xul/base/src/nsStackFrame.h +++ b/mozilla/layout/xul/base/src/nsStackFrame.h @@ -24,7 +24,7 @@ Eric D Vaughan A frame that can have multiple children. Only one child may be displayed at one time. So the - can be flipped though like a deck of cards. + can be flipped though like a Stack of cards. **/ @@ -39,33 +39,13 @@ public: friend nsresult NS_NewStackFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); - - - NS_IMETHOD Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* asPrevInFlow); - - NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, - const nsPoint& aPoint, - nsFramePaintLayer aWhichLayer, - nsIFrame** aFrame); - NS_IMETHOD GetFrameName(nsString& aResult) const { aResult = "Stack"; return NS_OK; } - - - -protected: - - nsStackFrame(nsIPresShell* aShell); - - // Paint one child frame + // Paint one child frame virtual void PaintChild(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, @@ -76,10 +56,11 @@ protected: nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer); - virtual void ComputeChildsNextPosition( nsCalculatedBoxInfo* aInfo, nscoord& aCurX, nscoord& aCurY, nscoord& aNextX, nscoord& aNextY, const nsSize& aCurrentChildSize, const nsRect& aBoxRect, nscoord aMaxAscent); - virtual void ChildResized(nsIFrame* aFrame, nsHTMLReflowMetrics& aDesiredSize, nsRect& aRect, nscoord& aMaxAscent, nsCalculatedBoxInfo& aInfo, PRBool*& aResized, PRInt32 aInfoCount, nscoord& aChangedIndex, PRBool& aFinished, nscoord aIndex, nsString& aReason); - virtual void LayoutChildrenInRect(nsRect& aSize, nscoord& aMaxAscent); - virtual void AddChildSize(nsBoxInfo& aInfo, nsBoxInfo& aChildInfo); + + NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, + const nsPoint& aPoint, + nsFramePaintLayer aWhichLayer, + nsIFrame** aFrame); private: virtual nsresult GetStackedFrameForPoint(nsIPresContext* aPresContext, @@ -87,6 +68,14 @@ private: const nsRect& aRect, const nsPoint& aPoint, nsIFrame** aFrame); +protected: + + nsStackFrame(nsIPresShell* aPresShell); + +private: + + static nsCOMPtr gLayout; + }; // class nsStackFrame diff --git a/mozilla/layout/xul/base/src/nsStackLayout.cpp b/mozilla/layout/xul/base/src/nsStackLayout.cpp new file mode 100644 index 00000000000..9c129e54317 --- /dev/null +++ b/mozilla/layout/xul/base/src/nsStackLayout.cpp @@ -0,0 +1,266 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +// +// Eric Vaughan +// Netscape Communications +// +// See documentation in associated header file +// + +#include "nsStackLayout.h" +#include "nsIStyleContext.h" +#include "nsIPresContext.h" +#include "nsIContent.h" +#include "nsCOMPtr.h" +#include "nsHTMLIIDs.h" +#include "nsUnitConversion.h" +#include "nsINameSpaceManager.h" +#include "nsXULAtoms.h" +#include "nsHTMLAtoms.h" +#include "nsIReflowCommand.h" +#include "nsHTMLParts.h" +#include "nsIPresShell.h" +#include "nsStyleChangeList.h" +#include "nsCSSRendering.h" +#include "nsIViewManager.h" +#include "nsBoxLayoutState.h" +#include "nsIBox.h" + +nsStackLayout::nsStackLayout(nsIPresShell* aPresShell) +{ +} + + +NS_IMETHODIMP +nsStackLayout::GetPrefSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + aSize.width = 0; + aSize.height = 0; + + // run through all the children and get there min, max, and preferred sizes + // return us the size of the box + + nsIBox* child = nsnull; + aBox->GetChildBox(&child); + + while (child) + { + // ignore collapsed children + PRBool isCollapsed = PR_FALSE; + child->IsCollapsed(aBoxLayoutState, isCollapsed); + + if (!isCollapsed) + { + nsSize pref(0,0); + child->GetPrefSize(aBoxLayoutState, pref); + AddMargin(child, pref); + AddLargestSize(aSize, pref); + } + + child->GetNextBox(&child); + } + + // now add our border and padding and insets + AddBorderAndPadding(aBox, aSize); + AddInset(aBox, aSize); + + return NS_OK; +} + +NS_IMETHODIMP +nsStackLayout::GetMinSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + aSize.width = 0; + aSize.height = 0; + + // run through all the children and get there min, max, and preferred sizes + // return us the size of the box + + nsIBox* child = nsnull; + aBox->GetChildBox(&child); + + while (child) + { + // ignore collapsed children + PRBool isCollapsed = PR_FALSE; + aBox->IsCollapsed(aBoxLayoutState, isCollapsed); + + if (!isCollapsed) + { + nsSize min(0,0); + child->GetMinSize(aBoxLayoutState, min); + AddMargin(child, min); + AddLargestSize(aSize, min); + } + + child->GetNextBox(&child); + } + +// now add our border and padding and insets + AddBorderAndPadding(aBox, aSize); + AddInset(aBox,aSize); + + return NS_OK; +} + +NS_IMETHODIMP +nsStackLayout::GetMaxSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + + aSize.width = NS_INTRINSICSIZE; + aSize.height = NS_INTRINSICSIZE; + + // run through all the children and get there min, max, and preferred sizes + // return us the size of the box + + + nsIBox* child = nsnull; + aBox->GetChildBox(&child); + + while (child) + { + // ignore collapsed children + PRBool isCollapsed = PR_FALSE; + aBox->IsCollapsed(aBoxLayoutState, isCollapsed); + + if (!isCollapsed) + { + // if completely redefined don't even ask our child for its size. + nsSize max(NS_INTRINSICSIZE, NS_INTRINSICSIZE); + child->GetMaxSize(aBoxLayoutState, max); + + AddMargin(child, max); + AddSmallestSize(aSize, max); + } + + child->GetNextBox(&child); + + } + + // now add our border and padding and insets + AddBorderAndPadding(aBox, aSize); + AddInset(aBox, aSize); + + return NS_OK; +} + + +NS_IMETHODIMP +nsStackLayout::GetAscent(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent) +{ + aAscent = 0; + + // run through all the children and get there min, max, and preferred sizes + // return us the size of the box + + nsIBox* child = nsnull; + aBox->GetChildBox(&child); + + while (child) + { + // ignore collapsed children + PRBool isCollapsed = PR_FALSE; + aBox->IsCollapsed(aBoxLayoutState, isCollapsed); + + if (!isCollapsed) + { + // if completely redefined don't even ask our child for its size. + nscoord ascent = 0; + child->GetAscent(aBoxLayoutState, ascent); + nsMargin margin; + child->GetMargin(margin); + ascent += margin.top + margin.bottom; + + if (ascent > aAscent) + aAscent = ascent; + } + + child->GetNextBox(&child); + + } + + return NS_OK; +} + +NS_IMETHODIMP +nsStackLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState) +{ + nsRect clientRect; + aBox->GetClientRect(clientRect); + + nsIBox* child = nsnull; + PRBool grow; + + do { + aBox->GetChildBox(&child); + grow = PR_FALSE; + while (child) + { + nsMargin margin; + child->GetMargin(margin); + nsRect childRect(clientRect); + childRect.Deflate(margin); + child->SetBounds(aState, childRect); + child->Layout(aState); + child->GetBounds(childRect); + childRect.Inflate(margin); + + // did the child push back on us and get bigger? + if (childRect.width > clientRect.width) { + clientRect.width = childRect.width; + grow = PR_TRUE; + } + + if (childRect.height > clientRect.height) { + clientRect.height = childRect.height; + grow = PR_TRUE; + } + + child->GetNextBox(&child); + } + } while(grow); + + // if some HTML inside us got bigger we need to force ourselves to + // get bigger + nsRect bounds; + aBox->GetBounds(bounds); + nsMargin bp; + aBox->GetBorderAndPadding(bp); + clientRect.Inflate(bp); + aBox->GetInset(bp); + clientRect.Inflate(bp); + + if (clientRect.width > bounds.width || clientRect.height > bounds.height) + { + if (clientRect.width > bounds.width) + bounds.width = clientRect.width; + if (clientRect.height > bounds.height) + bounds.height = clientRect.height; + + aBox->SetBounds(aState, bounds); + } + + return NS_OK; +} + + diff --git a/mozilla/layout/xul/base/src/nsStackLayout.h b/mozilla/layout/xul/base/src/nsStackLayout.h new file mode 100644 index 00000000000..0ecaf28d811 --- /dev/null +++ b/mozilla/layout/xul/base/src/nsStackLayout.h @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +/** + + Eric D Vaughan + A frame that can have multiple children. Only one child may be displayed at one time. So the + can be flipped though like a deck of cards. + +**/ + +#ifndef nsStackLayout_h___ +#define nsStackLayout_h___ + +#include "nsBoxLayout.h" + +class nsStackLayout : public nsBoxLayout +{ +public: + + nsStackLayout(nsIPresShell* aShell); + + NS_IMETHOD Layout(nsIBox* aBox, nsBoxLayoutState& aState); + + NS_IMETHOD GetPrefSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMinSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMaxSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetAscent(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent); +}; // class nsStackLayout + + + +#endif + diff --git a/mozilla/layout/xul/base/src/nsTabFrame.cpp b/mozilla/layout/xul/base/src/nsTabFrame.cpp index d799c92c131..043bd9f050d 100644 --- a/mozilla/layout/xul/base/src/nsTabFrame.cpp +++ b/mozilla/layout/xul/base/src/nsTabFrame.cpp @@ -62,7 +62,7 @@ NS_NewTabFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) } // NS_NewTabFrame nsTabFrame::nsTabFrame(nsIPresShell* aPresShell) -:nsXULButtonFrame(aPresShell) +:nsButtonBoxFrame(aPresShell) { } diff --git a/mozilla/layout/xul/base/src/nsTabFrame.h b/mozilla/layout/xul/base/src/nsTabFrame.h index 7bb1771a1fb..27ab068093f 100644 --- a/mozilla/layout/xul/base/src/nsTabFrame.h +++ b/mozilla/layout/xul/base/src/nsTabFrame.h @@ -30,11 +30,11 @@ #ifndef nsTabFrame_h___ #define nsTabFrame_h___ -#include "nsXULButtonFrame.h" +#include "nsButtonBoxFrame.h" class nsTabControlFrame; -class nsTabFrame : public nsXULButtonFrame +class nsTabFrame : public nsButtonBoxFrame { public: diff --git a/mozilla/layout/xul/base/src/nsXULTextFrame.cpp b/mozilla/layout/xul/base/src/nsTextBoxFrame.cpp similarity index 84% rename from mozilla/layout/xul/base/src/nsXULTextFrame.cpp rename to mozilla/layout/xul/base/src/nsTextBoxFrame.cpp index c32b52506bf..9ea32cfd3f7 100644 --- a/mozilla/layout/xul/base/src/nsXULTextFrame.cpp +++ b/mozilla/layout/xul/base/src/nsTextBoxFrame.cpp @@ -27,7 +27,7 @@ // See documentation in associated header file // -#include "nsXULTextFrame.h" +#include "nsTextBoxFrame.h" #include "nsCOMPtr.h" #include "nsIDeviceContext.h" #include "nsIFontMetrics.h" @@ -38,6 +38,7 @@ #include "nsIStyleContext.h" #include "nsIContent.h" #include "nsINameSpaceManager.h" +#include "nsBoxLayoutState.h" #define ELIPSIS "..." @@ -61,13 +62,13 @@ public: // Creates a new Toolbar frame and returns it in |aNewFrame| // nsresult -NS_NewXULTextFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) +NS_NewTextBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) { NS_PRECONDITION(aNewFrame, "null OUT ptr"); if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } - nsXULTextFrame* it = new (aPresShell) nsXULTextFrame; + nsTextBoxFrame* it = new (aPresShell) nsTextBoxFrame (aPresShell); if (nsnull == it) return NS_ERROR_OUT_OF_MEMORY; @@ -79,7 +80,7 @@ NS_NewXULTextFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) NS_IMETHODIMP -nsXULTextFrame::AttributeChanged(nsIPresContext* aPresContext, +nsTextBoxFrame::AttributeChanged(nsIPresContext* aPresContext, nsIContent* aChild, PRInt32 aNameSpaceID, nsIAtom* aAttribute, @@ -96,23 +97,23 @@ nsXULTextFrame::AttributeChanged(nsIPresContext* aPresContext, UpdateAccessUnderline(); if (aResize) { - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - mState |= NS_FRAME_IS_DIRTY; - mParent->ReflowDirtyChild(shell, this); + nsBoxLayoutState state(aPresContext); + MarkDirty(state); } else if (aRedraw) { - Invalidate(aPresContext, nsRect(0,0,mRect.width, mRect.height), PR_FALSE); + nsBoxLayoutState state(aPresContext); + Redraw(state); } return NS_OK; } -nsXULTextFrame::nsXULTextFrame():mCropType(CropRight),mTitle(""), mAccessKeyInfo(nsnull) +nsTextBoxFrame::nsTextBoxFrame(nsIPresShell* aShell):nsLeafBoxFrame(aShell),mTitle(""), mCropType(CropRight),mAccessKeyInfo(nsnull) { mState |= NS_STATE_NEED_LAYOUT; + NeedsRecalc(); } -nsXULTextFrame::~nsXULTextFrame() +nsTextBoxFrame::~nsTextBoxFrame() { if (mAccessKeyInfo) delete mAccessKeyInfo; @@ -120,13 +121,13 @@ nsXULTextFrame::~nsXULTextFrame() NS_IMETHODIMP -nsXULTextFrame::Init(nsIPresContext* aPresContext, +nsTextBoxFrame::Init(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParent, nsIStyleContext* aContext, nsIFrame* aPrevInFlow) { - nsresult rv = nsXULLeafFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); + nsresult rv = nsLeafBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); PRBool a,b,c; UpdateAttributes(aPresContext, nsnull, a, b, c /* all */); @@ -139,7 +140,7 @@ nsXULTextFrame::Init(nsIPresContext* aPresContext, nsAutoString accesskey; mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::accesskey, accesskey); - if (!accesskey.IsEmpty()) { + if (accesskey != "") { if (!mAccessKeyInfo) mAccessKeyInfo = new nsAccessKeyInfo(); @@ -168,7 +169,7 @@ nsXULTextFrame::Init(nsIPresContext* aPresContext, } void -nsXULTextFrame::UpdateAttributes(nsIPresContext* aPresContext, nsIAtom* aAttribute, PRBool& aResize, PRBool& aRedraw, PRBool& aUpdateAccessUnderline) +nsTextBoxFrame::UpdateAttributes(nsIPresContext* aPresContext, nsIAtom* aAttribute, PRBool& aResize, PRBool& aRedraw, PRBool& aUpdateAccessUnderline) { aResize = PR_FALSE; aRedraw = PR_FALSE; @@ -222,14 +223,14 @@ nsXULTextFrame::UpdateAttributes(nsIPresContext* aPresContext, nsIAtom* aAttrib } NS_IMETHODIMP -nsXULTextFrame::Paint(nsIPresContext* aPresContext, +nsTextBoxFrame::Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { const nsStyleDisplay* disp = (const nsStyleDisplay*) mStyleContext->GetStyleData(eStyleStruct_Display); - if (!disp->IsVisibleOrCollapsed()) + if (!disp->IsVisible()) return NS_OK; if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { @@ -251,7 +252,7 @@ nsXULTextFrame::Paint(nsIPresContext* aPresContext, void -nsXULTextFrame::LayoutTitle(nsIPresContext* aPresContext, +nsTextBoxFrame::LayoutTitle(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer, @@ -298,7 +299,7 @@ nsXULTextFrame::LayoutTitle(nsIPresContext* aPresContext, } NS_IMETHODIMP -nsXULTextFrame::PaintTitle(nsIPresContext* aPresContext, +nsTextBoxFrame::PaintTitle(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer, @@ -364,7 +365,7 @@ nsXULTextFrame::PaintTitle(nsIPresContext* aPresContext, } void -nsXULTextFrame::GetTextSize(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, +nsTextBoxFrame::GetTextSize(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsString& aString, nsSize& aSize, nscoord& aAscent) { const nsStyleFont* fontStyle = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); @@ -381,7 +382,7 @@ nsXULTextFrame::GetTextSize(nsIPresContext* aPresContext, nsIRenderingContext& a } void -nsXULTextFrame::CalculateTitleForWidth(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, nscoord aWidth) +nsTextBoxFrame::CalculateTitleForWidth(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, nscoord aWidth) { if (mTitle.Length() == 0) return; @@ -534,13 +535,13 @@ nsXULTextFrame::CalculateTitleForWidth(nsIPresContext* aPresContext, nsIRenderin } void -nsXULTextFrame::UpdateAccessUnderline() +nsTextBoxFrame::UpdateAccessUnderline() { #ifndef XP_UNIX nsAutoString accesskey; mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::accesskey, accesskey); - if (accesskey.IsEmpty()) { + if (accesskey == "") { if (mAccessKeyInfo) { delete mAccessKeyInfo; mAccessKeyInfo = nsnull; @@ -559,41 +560,95 @@ nsXULTextFrame::UpdateAccessUnderline() NS_IMETHODIMP -nsXULTextFrame::Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aMetrics, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) +nsTextBoxFrame::Layout(nsBoxLayoutState& aBoxLayoutState) { mState |= NS_STATE_NEED_LAYOUT; - return nsXULLeafFrame::Reflow(aPresContext, aMetrics, aReflowState, aStatus); + return nsLeafBoxFrame::Layout(aBoxLayoutState); +} + +NS_IMETHODIMP +nsTextBoxFrame::NeedsRecalc() +{ + mNeedsRecalc = PR_TRUE; + return NS_OK; +} + +void +nsTextBoxFrame::CalcTextSize(nsBoxLayoutState& aBoxLayoutState) +{ + if (mNeedsRecalc) + { + nsSize size; + nscoord ascent = 0; + nsIPresContext* presContext = aBoxLayoutState.GetPresContext(); + nsIRenderingContext* rendContext = aBoxLayoutState.GetReflowState()->rendContext; + if (rendContext) { + GetTextSize(presContext, *rendContext, + mTitle, size, mAscent); + mTextSize = size; + mNeedsRecalc = PR_FALSE; + } + } } /** * Ok return our dimensions */ NS_IMETHODIMP -nsXULTextFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize) +nsTextBoxFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) { - // depending on the type of alignment add in the space for the text - nsSize size; - nscoord ascent = 0; - GetTextSize(aPresContext, *aReflowState.rendContext, - mTitle, size, ascent); + CalcTextSize(aBoxLayoutState); + + aSize = mTextSize; - aSize.ascent = ascent; - aSize.prefSize = size; - aSize.minSize = size; + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSPrefSize(aBoxLayoutState, this, aSize); + + return NS_OK; +} - // if there is cropping our min width becomes 0 - if (mCropType != CropNone) - aSize.minSize.width = 0; - - return NS_OK; +/** + * Ok return our dimensions + */ +NS_IMETHODIMP +nsTextBoxFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + CalcTextSize(aBoxLayoutState); + + aSize = mTextSize; + + // if there is cropping our min width becomes our border and padding + if (mCropType != CropNone) { + aSize.width = 0; + } + + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSMinSize(aBoxLayoutState, this, aSize); + + return NS_OK; } NS_IMETHODIMP -nsXULTextFrame::GetFrameName(nsString& aResult) const +nsTextBoxFrame::GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent) +{ + CalcTextSize(aBoxLayoutState); + + aAscent = mAscent; + + nsMargin m(0,0,0,0); + GetBorderAndPadding(m); + aAscent += m.top; + GetInset(m); + aAscent += m.top; + + return NS_OK; +} + +NS_IMETHODIMP +nsTextBoxFrame::GetFrameName(nsString& aResult) const { aResult = "Text[value="; aResult += mTitle; diff --git a/mozilla/layout/xul/base/src/nsXULTextFrame.h b/mozilla/layout/xul/base/src/nsTextBoxFrame.h similarity index 79% rename from mozilla/layout/xul/base/src/nsXULTextFrame.h rename to mozilla/layout/xul/base/src/nsTextBoxFrame.h index 1aa91ebfe3d..84a59064e24 100644 --- a/mozilla/layout/xul/base/src/nsXULTextFrame.h +++ b/mozilla/layout/xul/base/src/nsTextBoxFrame.h @@ -19,23 +19,27 @@ * * Contributor(s): */ -#ifndef nsXULTextFrame_h___ -#define nsXULTextFrame_h___ +#ifndef nsTextBoxFrame_h___ +#define nsTextBoxFrame_h___ -#include "nsXULLeafFrame.h" +#include "nsLeafBoxFrame.h" class nsAccessKeyInfo; -class nsXULTextFrame : public nsXULLeafFrame +class nsTextBoxFrame : public nsLeafBoxFrame { public: + // nsIBox + NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent); + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); + NS_IMETHOD NeedsRecalc(); + enum CroppingStyle { CropNone, CropLeft, CropRight, CropCenter }; - friend nsresult NS_NewXULTextFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); - - // nsIBox frame interface - NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); + friend nsresult NS_NewTextBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); NS_IMETHOD Init(nsIPresContext* aPresContext, nsIContent* aContent, @@ -53,19 +57,14 @@ public: virtual void UpdateAttributes(nsIPresContext* aPresContext, nsIAtom* aAttribute, PRBool& aResize, PRBool& aRedraw, PRBool& aUpdateAccessUnderline); - // nsIHTMLReflow overrides - NS_IMETHOD Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); - + NS_IMETHOD Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer); - ~nsXULTextFrame(); + ~nsTextBoxFrame(); protected: void UpdateAccessUnderline(); @@ -82,8 +81,9 @@ protected: nsFramePaintLayer aWhichLayer, const nsRect& aTextRect); + virtual void CalcTextSize(nsBoxLayoutState& aBoxLayoutState); - nsXULTextFrame(); + nsTextBoxFrame(nsIPresShell* aShell); virtual void CalculateTitleForWidth(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, nscoord aWidth); virtual void GetTextSize(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsString& aString, nsSize& aSize, nscoord& aAscent); @@ -95,6 +95,9 @@ private: nsString mCroppedTitle; nscoord mTitleWidth; nsAccessKeyInfo* mAccessKeyInfo; -}; // class nsXULTextFrame + PRBool mNeedsRecalc; + nsSize mTextSize; + nscoord mAscent; +}; // class nsTextBoxFrame -#endif /* nsXULTextFrame_h___ */ +#endif /* nsTextBoxFrame_h___ */ diff --git a/mozilla/layout/xul/base/src/nsTitledBoxFrame.cpp b/mozilla/layout/xul/base/src/nsTitledBoxFrame.cpp index 73556e852ea..d98ace98fb4 100644 --- a/mozilla/layout/xul/base/src/nsTitledBoxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsTitledBoxFrame.cpp @@ -58,6 +58,9 @@ public: NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList); + + NS_IMETHOD GetBorderAndPadding(nsMargin& aBorderAndPadding); + NS_METHOD Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -81,12 +84,7 @@ public: } #endif - NS_IMETHOD Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); - - virtual PRBool GetInitialOrientation(PRBool& aHorizontal) { aHorizontal = PR_FALSE; return PR_TRUE; } + virtual PRBool GetInitialOrientation(PRBool& aHorizontal) { aHorizontal = PR_FALSE; return PR_TRUE; } nsIFrame* GetTitleFrame(nsIPresContext* aPresContext, nsRect& aRect); nsIFrame* GetContentFrame(nsIPresContext* aPresContext); @@ -321,28 +319,11 @@ nsTitledBoxFrame::GetContentFrame(nsIPresContext* aPresContext) return next; } -NS_IMETHODIMP -nsTitledBoxFrame::Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) +NS_IMETHODIMP +nsTitledBoxFrame::GetBorderAndPadding(nsMargin& aBorderAndPadding) { - if (aReflowState.mComputedBorderPadding.top != 0) - { - nsHTMLReflowState newState(aReflowState); - - if (newState.mComputedHeight != NS_INTRINSICSIZE) - newState.mComputedHeight += aReflowState.mComputedBorderPadding.top; - - // remove the border from border padding - ((nsMargin&)newState.mComputedBorderPadding).top = 0; - ((nsMargin&)newState.mComputedPadding).top = 0; - - // reflow us again with the correct values. - return Reflow(aPresContext, aDesiredSize, newState, aStatus); - } - - return nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + aBorderAndPadding.SizeTo(0,0,0,0); + return NS_OK; } NS_IMETHODIMP diff --git a/mozilla/layout/xul/base/src/nsTitledButtonFrame.cpp b/mozilla/layout/xul/base/src/nsTitledButtonFrame.cpp index 210e19f262b..614f53c1112 100644 --- a/mozilla/layout/xul/base/src/nsTitledButtonFrame.cpp +++ b/mozilla/layout/xul/base/src/nsTitledButtonFrame.cpp @@ -38,6 +38,7 @@ #include "nsCOMPtr.h" #include "nsIPresContext.h" #include "nsButtonFrameRenderer.h" +#include "nsBoxLayoutState.h" #include "nsHTMLParts.h" #include "nsString.h" @@ -71,6 +72,7 @@ #include "nsIDOMHTMLMapElement.h" #include "nsIStyleSet.h" #include "nsIStyleContext.h" +#include "nsBoxLayoutState.h" #include "nsFormControlHelper.h" @@ -130,6 +132,11 @@ nsTitledButtonFrame::UpdateImageFrame(nsIPresContext* aPresContext, PRUint32 aStatus) { if (NS_IMAGE_LOAD_STATUS_SIZE_AVAILABLE & aStatus) { + nsTitledButtonFrame* us = (nsTitledButtonFrame*)aFrame; + nsBoxLayoutState state(aPresContext); + us->MarkDirty(state); + + /* // Now that the size is available, trigger a content-changed reflow nsIContent* content = nsnull; aFrame->GetContent(&content); @@ -142,6 +149,7 @@ nsTitledButtonFrame::UpdateImageFrame(nsIPresContext* aPresContext, } NS_RELEASE(content); } + */ } return NS_OK; } @@ -158,7 +166,7 @@ NS_NewTitledButtonFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } - nsTitledButtonFrame* it = new (aPresShell) nsTitledButtonFrame; + nsTitledButtonFrame* it = new (aPresShell) nsTitledButtonFrame (aPresShell); if (nsnull == it) return NS_ERROR_OUT_OF_MEMORY; @@ -187,10 +195,8 @@ nsTitledButtonFrame::AttributeChanged(nsIPresContext* aPresContext, UpdateAccessUnderline(); if (aResize) { - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - mState |= NS_FRAME_IS_DIRTY; - mParent->ReflowDirtyChild(shell, this); + nsBoxLayoutState state(aPresContext); + MarkDirty(state); } else if (aRedraw) { mRenderer->Redraw(aPresContext); } @@ -210,7 +216,10 @@ nsTitledButtonFrame::AttributeChanged(nsIPresContext* aPresContext, return NS_OK; } -nsTitledButtonFrame::nsTitledButtonFrame() +nsTitledButtonFrame::nsTitledButtonFrame(nsIPresShell* aShell):nsLeafBoxFrame(aShell), + mPrefSize(0,0), + mMinSize(0,0), + mAscent(0) { mTitle = ""; mAlign = GetDefaultAlignment(); @@ -218,8 +227,9 @@ nsTitledButtonFrame::nsTitledButtonFrame() mNeedsLayout = PR_TRUE; mNeedsAccessUpdate = PR_TRUE; mHasImage = PR_FALSE; - mHasOnceBeenInMixedState = PR_FALSE; - mRenderer = new nsTitledButtonRenderer(); + mHasOnceBeenInMixedState = PR_FALSE; + mRenderer = new nsTitledButtonRenderer(); + NeedsRecalc(); } nsTitledButtonFrame::~nsTitledButtonFrame() @@ -227,13 +237,21 @@ nsTitledButtonFrame::~nsTitledButtonFrame() delete mRenderer; } + +NS_IMETHODIMP +nsTitledButtonFrame::NeedsRecalc() +{ + mNeedsRecalc = PR_TRUE; + return NS_OK; +} + NS_METHOD nsTitledButtonFrame::Destroy(nsIPresContext* aPresContext) { // Release image loader first so that it's refcnt can go to zero mImageLoader.StopAllLoadImages(aPresContext); - return nsXULLeafFrame::Destroy(aPresContext); + return nsLeafBoxFrame::Destroy(aPresContext); } @@ -244,7 +262,7 @@ nsTitledButtonFrame::Init(nsIPresContext* aPresContext, nsIStyleContext* aContext, nsIFrame* aPrevInFlow) { - nsresult rv = nsXULLeafFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); + nsresult rv = nsLeafBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); mRenderer->SetNameSpace(kNameSpaceID_None); mRenderer->SetFrame(this,aPresContext); @@ -938,21 +956,6 @@ nsTitledButtonFrame::PaintImage(nsIPresContext* aPresContext, return NS_OK; } - -NS_IMETHODIMP -nsTitledButtonFrame::Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aMetrics, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) -{ - - - mNeedsLayout = PR_TRUE; - nsresult result = nsXULLeafFrame::Reflow(aPresContext, aMetrics, aReflowState, aStatus); - - return result; -} - struct nsTitleRecessedBorder : public nsStyleSpacing { nsTitleRecessedBorder(nscoord aBorderWidth) : nsStyleSpacing() @@ -1204,7 +1207,7 @@ nsTitledButtonFrame::HandleEvent(nsIPresContext* aPresContext, break; } - return nsXULLeafFrame::HandleEvent(aPresContext, aEvent, aEventStatus); + return nsLeafBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus); } // @@ -1388,22 +1391,79 @@ nsTitledButtonFrame::GetImageSize(nsIPresContext* aPresContext) * Ok return our dimensions */ NS_IMETHODIMP -nsTitledButtonFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize) +nsTitledButtonFrame::Layout(nsBoxLayoutState& aState) { - GetImageSize(aPresContext); + mNeedsLayout = PR_TRUE; + return nsLeafBoxFrame::Layout(aState); +} - aSize.minSize.width = mImageRect.width; - aSize.minSize.height = mImageRect.height; - aSize.prefSize.width = mImageRect.width; - aSize.prefSize.height = mImageRect.height; +/** + * Ok return our dimensions + */ +NS_IMETHODIMP +nsTitledButtonFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + if (mNeedsRecalc) { + CacheSizes(aBoxLayoutState); + } + + aSize = mPrefSize; + return NS_OK; +} + +/** + * Ok return our dimensions + */ +NS_IMETHODIMP +nsTitledButtonFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + if (mNeedsRecalc) { + CacheSizes(aBoxLayoutState); + } + + aSize = mMinSize; + return NS_OK; +} + +NS_IMETHODIMP +nsTitledButtonFrame::GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aCoord) +{ + if (mNeedsRecalc) { + CacheSizes(aBoxLayoutState); + } + + aCoord = mAscent; + return NS_OK; +} + +/** + * Ok return our dimensions + */ +void +nsTitledButtonFrame::CacheSizes(nsBoxLayoutState& aBoxLayoutState) +{ + nsIPresContext* presContext = aBoxLayoutState.GetPresContext(); + const nsHTMLReflowState* state = aBoxLayoutState.GetReflowState(); + if (!state) + return; + + nsIRenderingContext* rendContext = state->rendContext; + + GetImageSize(presContext); + + mMinSize.width = mImageRect.width; + mMinSize.height = mImageRect.height; + mPrefSize.width = mImageRect.width; + mPrefSize.height = mImageRect.height; // depending on the type of alignment add in the space for the text nsSize size; nscoord ascent = 0; - GetTextSize(aPresContext, *aReflowState.rendContext, + + GetTextSize(presContext, *rendContext, mTitle, size, ascent); - aSize.ascent = ascent; + mAscent = ascent; switch (mAlign) { case NS_SIDE_TOP: @@ -1411,59 +1471,81 @@ nsTitledButtonFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflow // if we have an image add the image to our min size if (mHasImage) - aSize.minSize.width = aSize.prefSize.width; + mMinSize.width = mPrefSize.width; // if we are not cropped then our min size also includes the text. if (mCropType == CropNone) - aSize.minSize.width = PR_MAX(size.width, aSize.minSize.width); + mMinSize.width = PR_MAX(size.width, mMinSize.width); - if (size.width > aSize.prefSize.width) - aSize.prefSize.width = size.width; + if (size.width > mPrefSize.width) + mPrefSize.width = size.width; if (mTitle.Length() > 0) { - aSize.prefSize.height += size.height; + mPrefSize.height += size.height; if (mHasImage) - aSize.prefSize.height += mSpacing; + mPrefSize.height += mSpacing; } - aSize.minSize.height = aSize.prefSize.height; + mMinSize.height = mPrefSize.height; break; case NS_SIDE_LEFT: case NS_SIDE_RIGHT: - if (size.height > aSize.prefSize.height) - aSize.prefSize.height = size.height; + if (size.height > mPrefSize.height) + mPrefSize.height = size.height; if (mHasImage) - aSize.minSize.width = aSize.prefSize.width; + mMinSize.width = mPrefSize.width; // if we are not cropped then our min size also includes the text. if (mCropType == CropNone) - aSize.minSize.width += size.width; + mMinSize.width += size.width; if (mTitle.Length() > 0) { - aSize.prefSize.width += size.width; + mPrefSize.width += size.width; if (mHasImage) { - aSize.prefSize.width += mSpacing; - aSize.minSize.width += mSpacing; + mPrefSize.width += mSpacing; + mMinSize.width += mSpacing; } } break; } + nscoord oldHeight = mPrefSize.height; + nsMargin focusBorder = mRenderer->GetAddedButtonBorderAndPadding(); - aSize.prefSize.width += focusBorder.left + focusBorder.right; - aSize.prefSize.height += focusBorder.top + focusBorder.bottom; + mPrefSize.width += focusBorder.left + focusBorder.right; + mPrefSize.height += focusBorder.top + focusBorder.bottom; - aSize.minSize.width += focusBorder.left + focusBorder.right; - aSize.minSize.height += focusBorder.top + focusBorder.bottom; + mMinSize.width += focusBorder.left + focusBorder.right; + mMinSize.height += focusBorder.top + focusBorder.bottom; - ascent += focusBorder.top; - return NS_OK; + AddBorderAndPadding(mPrefSize); + AddInset(mPrefSize); + nsIBox::AddCSSPrefSize(aBoxLayoutState, this, mPrefSize); + + AddBorderAndPadding(mMinSize); + AddInset(mMinSize); + nsIBox::AddCSSMinSize(aBoxLayoutState, this, mMinSize); + + if (mPrefSize.width < mMinSize.width) + mPrefSize.width = mMinSize.width; + + if (mPrefSize.height < mMinSize.height) + mPrefSize.height = mMinSize.height; + + nsMargin m(0,0,0,0); + GetBorderAndPadding(m); + mAscent += m.top; + GetInset(m); + mAscent += m.top; + mAscent += focusBorder.top; + + mNeedsRecalc = PR_FALSE; } NS_IMETHODIMP diff --git a/mozilla/layout/xul/base/src/nsTitledButtonFrame.h b/mozilla/layout/xul/base/src/nsTitledButtonFrame.h index d2952db7bdd..6b020d1e1b1 100644 --- a/mozilla/layout/xul/base/src/nsTitledButtonFrame.h +++ b/mozilla/layout/xul/base/src/nsTitledButtonFrame.h @@ -23,23 +23,28 @@ #define nsTitledButtonFrame_h___ #include "nsHTMLImageLoader.h" -#include "nsXULLeafFrame.h" +#include "nsLeafBoxFrame.h" class nsIPopUpMenu; class nsTitledButtonRenderer; -class nsTitledButtonFrame : public nsXULLeafFrame +class nsTitledButtonFrame : public nsLeafBoxFrame { public: + // nsIBox + NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent); + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); + NS_IMETHOD NeedsRecalc(); + + // our methods enum CroppingStyle { CropNone, CropLeft, CropRight, CropCenter }; friend nsresult NS_NewTitledButtonFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); // nsIBox frame interface - NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); - - NS_IMETHOD SetDebug(nsIPresContext* aPresContext, PRBool aDebug) { return NS_OK; } NS_IMETHOD Init(nsIPresContext* aPresContext, nsIContent* aContent, @@ -67,11 +72,6 @@ public: virtual void UpdateAttributes(nsIPresContext* aPresContext, nsIAtom* aAttribute, PRBool& aResize, PRBool& aRedraw, PRBool& aUpdateAccessUnderline); virtual void UpdateImage(nsIPresContext* aPresContext, PRBool& aResize); - // nsIHTMLReflow overrides - NS_IMETHOD Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); NS_IMETHOD Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -86,6 +86,8 @@ public: ~nsTitledButtonFrame(); protected: + void CacheSizes(nsBoxLayoutState& aBoxLayoutState); + enum CheckState { eUnset, eOff, eOn, eMixed } ; CheckState GetCurrentCheckState(); @@ -124,7 +126,7 @@ protected: PRUint32& aMaxFit, nsIRenderingContext& aContext); - nsTitledButtonFrame(); + nsTitledButtonFrame(nsIPresShell* aShell); virtual void CalculateTitleForWidth(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, nscoord aWidth); @@ -170,6 +172,12 @@ private: PRInt32 mAccesskeyIndex; nscoord mBeforeWidth, mAccessWidth, mAccessUnderlineSize, mAccessOffset; + nsSize mPrefSize; + nsSize mMinSize; + nscoord mAscent; + PRBool mNeedsRecalc; + + // nsIPopUpMenu * mPopUpMenu; // PRBool mMenuIsPoppedUp; diff --git a/mozilla/layout/xul/base/src/nsToolbarFrame.cpp b/mozilla/layout/xul/base/src/nsToolbarFrame.cpp index af771a3d9b0..48962844224 100644 --- a/mozilla/layout/xul/base/src/nsToolbarFrame.cpp +++ b/mozilla/layout/xul/base/src/nsToolbarFrame.cpp @@ -284,39 +284,6 @@ nsToolbarFrame :: Paint ( nsIPresContext* aPresContext, } // Paint -#if 0 -// -// GetFrameForPoint -// -// Override to process events in our own frame -// -NS_IMETHODIMP -nsToolbarFrame :: GetFrameForPoint ( nsIPresContext* aPresContext, - const nsPoint& aPoint, - nsFramePaintLayer aWhichLayer, - nsIFrame** aFrame) -{ - nsresult retVal = nsHTMLContainerFrame::GetFrameForPoint(aPresContext, aPoint, aWhichLayer, aFrame); - - if (! mRect.Contains(aPoint)) { - return retVal; - } - - // returning NS_OK means that we tell the frame finding code that we have something - // and to stop looking elsewhere for a frame. - if ( aFrame && *aFrame == this ) - retVal = NS_OK; - else if ( retVal != NS_OK ) { - *aFrame = this; - retVal = NS_OK; - } - - return retVal; - -} // GetFrameForPoint -#endif - - // // HandleEvent // diff --git a/mozilla/layout/xul/base/src/nsToolbarFrame.h b/mozilla/layout/xul/base/src/nsToolbarFrame.h index c9eca0328b9..a20b5e89c72 100644 --- a/mozilla/layout/xul/base/src/nsToolbarFrame.h +++ b/mozilla/layout/xul/base/src/nsToolbarFrame.h @@ -73,13 +73,6 @@ public: const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer); - // nsFrame overrides -#if 0 - NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, - const nsPoint& aPoint, // Overridden to capture events - nsFramePaintLayer aWhichLayer, - nsIFrame** aFrame); -#endif NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, nsIContent* aChild, PRInt32 aNameSpaceID, diff --git a/mozilla/layout/xul/base/src/nsToolboxFrame.cpp b/mozilla/layout/xul/base/src/nsToolboxFrame.cpp index 1b61744b96a..8464385f8df 100644 --- a/mozilla/layout/xul/base/src/nsToolboxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsToolboxFrame.cpp @@ -41,6 +41,7 @@ #include "nsIPresContext.h" #include "nsIWidget.h" #include "nsINameSpaceManager.h" +#include "nsBoxLayoutState.h" #include "nsIServiceManager.h" #include "nsWidgetsCID.h" @@ -103,7 +104,7 @@ nsToolboxFrame :: nsToolboxFrame (nsIPresShell* aShell):nsBoxFrame(aShell) mGrippyHilighted(kNoGrippyHilighted), kCollapsedAtom(dont_AddRef( NS_NewAtom("collapsed"))), kHiddenAtom(dont_AddRef( NS_NewAtom("hidden"))), - mDragListenerDelegate(nsnull) + mDragListenerDelegate(nsnull), mNeedsCalc(PR_TRUE) { } @@ -203,6 +204,8 @@ nsToolboxFrame::Init(nsIPresContext* aPresContext, nsIStyleContext* aContext, nsIFrame* aPrevInFlow) { + mPresContext = aPresContext; + nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); UpdateStyles(aPresContext); @@ -313,39 +316,67 @@ nsToolboxFrame :: DrawGrippy ( nsIPresContext* aPresContext, nsIRenderingContex } // DrawGrippy +/* NS_IMETHODIMP nsToolboxFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize) { CalculateGrippies(aPresContext); return nsBoxFrame::GetBoxInfo(aPresContext, aReflowState, aSize); } +*/ -NS_IMETHODIMP -nsToolboxFrame :: Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) +NS_IMETHODIMP +nsToolboxFrame::NeedsRecalc() { - nsresult errCode = nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); - errCode = ReflowGrippies(aPresContext, aDesiredSize, aReflowState, aStatus); - return errCode; + nsresult rv = nsBoxFrame::NeedsRecalc(); + mNeedsCalc = PR_TRUE; + return rv; +} -} // Reflow + +NS_IMETHODIMP +nsToolboxFrame::GetInset(nsMargin& aMargin) +{ + if (mNeedsCalc) + { + CalculateGrippies(mPresContext); + mNeedsCalc = PR_FALSE; + } + + nsBoxFrame::GetInset(aMargin); + aMargin += mInset; + + return NS_OK; +} + +NS_IMETHODIMP +nsToolboxFrame::Layout(nsBoxLayoutState& aState) +{ + // lay us out + nsresult rv = nsBoxFrame::Layout(aState); + LayoutGrippies(aState); + return rv; +} // After we have been flowed this should be flowed to place the grippies at there // physical locations. nsresult -nsToolboxFrame::ReflowGrippies(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) +nsToolboxFrame::LayoutGrippies(nsBoxLayoutState& aState) { // get the rect we can place the grippies in. This is inside our borders and debug rect. - nsRect innerRect(0,0,0,0); - GetInnerRect(innerRect); + nsRect ourRect(0,0,0,0); + GetRect(ourRect); + ourRect.x = 0; + ourRect.y = 0; + nsRect innerRect(ourRect); + nsMargin border(0,0,0,0); + GetBorderAndPadding(border); + innerRect.Deflate(border); + + nsIPresContext* presContext = aState.GetPresContext(); float p2t; - aPresContext->GetScaledPixelsToTwips(&p2t); + presContext->GetScaledPixelsToTwips(&p2t); nscoord onePixel = NSIntPixelsToTwips(1, p2t); nscoord grippyWidth = kGrippyWidthInPixels * onePixel; // remember to leave room for the grippy on the right nscoord collapsedGrippyHeight = kCollapsedGrippyHeightInPixels * onePixel; @@ -356,14 +387,19 @@ nsToolboxFrame::ReflowGrippies(nsIPresContext* aPresContext, // iterate over all visible toolbar frames, moving the associated grippy // next to the toolbar mNumToolbars = 0; - nsIFrame* childFrame = mFrames.FirstChild(); - while ( childFrame ) { + nsIBox* childBox; + GetChildBox(&childBox); + + while ( childBox ) { // get the childs rect and figure out the grippy size + nsIFrame* childFrame = nsnull; + childBox->GetFrame(&childFrame); + nsCOMPtr childContent; childFrame->GetContent(getter_AddRefs(childContent)); nsRect grippyRect; - childFrame->GetRect(grippyRect); + childBox->GetBounds(grippyRect); if ( isHorz ) { grippyRect.y = innerRect.y; @@ -380,7 +416,7 @@ nsToolboxFrame::ReflowGrippies(nsIPresContext* aPresContext, // Set the location of the grippy to the left... grippyInfo->SetBounds(grippyRect); - errCode = childFrame->GetNextSibling(&childFrame); + errCode = childBox->GetNextBox(&childBox); NS_ASSERTION(errCode == NS_OK, "failed to get next child"); mNumToolbars++; } @@ -393,9 +429,9 @@ nsToolboxFrame::ReflowGrippies(nsIPresContext* aPresContext, // horzontal toolbox our height is our width. Thats why we just use // height here on both x and y coords. if ( isHorz ) - currGrippy->mBoundingRect.x = aDesiredSize.width - collapsedGrippyHeight; + currGrippy->mBoundingRect.x = ourRect.width - collapsedGrippyHeight; else - currGrippy->mBoundingRect.y = aDesiredSize.height - collapsedGrippyHeight; + currGrippy->mBoundingRect.y = ourRect.height - collapsedGrippyHeight; } } @@ -407,6 +443,7 @@ nsToolboxFrame::ReflowGrippies(nsIPresContext* aPresContext, void nsToolboxFrame::CalculateGrippies(nsIPresContext* aPresContext) { + // compute amount (in twips) each toolbar will be offset from the right because of // the grippy float p2t; @@ -562,52 +599,6 @@ nsToolboxFrame :: ClearGrippyList ( nsVoidArray & inList ) } // ClearGrippyList -// -// GetInset -// -// Our Reflow() method computes a margin for the grippies and for collased grippies (if -// any). Return this pre-computed margin when asked by the box. -// -void -nsToolboxFrame::GetInset(nsMargin& margin) -{ - nsBoxFrame::GetInset(margin); - margin += mInset; -} - - -#if 0 -// -// GetFrameForPoint -// -// Override to process events in our own frame -// -NS_IMETHODIMP -nsToolboxFrame :: GetFrameForPoint(nsIPresContext* aPresContext, - const nsPoint& aPoint, - nsFramePaintLayer aWhichLayer, - nsIFrame** aFrame) -{ - nsresult retVal = nsHTMLContainerFrame::GetFrameForPoint(aPresContext, aPoint, aWhichLayer, aFrame); - - if (! mRect.Contains(aPoint)) { - return retVal; - } - - // returning NS_OK means that we tell the frame finding code that we have something - // and to stop looking elsewhere for a frame. - if ( aFrame && *aFrame == this ) - retVal = NS_OK; - else if ( retVal != NS_OK ) { - *aFrame = this; - retVal = NS_OK; - } - return retVal; - -} // GetFrameForPoint -#endif - - // // HandleEvent // diff --git a/mozilla/layout/xul/base/src/nsToolboxFrame.h b/mozilla/layout/xul/base/src/nsToolboxFrame.h index 62c171fadef..019210766b8 100644 --- a/mozilla/layout/xul/base/src/nsToolboxFrame.h +++ b/mozilla/layout/xul/base/src/nsToolboxFrame.h @@ -58,14 +58,12 @@ class nsToolboxFrame : public nsBoxFrame public: friend nsresult NS_NewToolboxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); - // nsIHTMLReflow overrides - NS_IMETHOD Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); - - NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); + // nsIBox + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); + NS_IMETHOD GetInset(nsMargin& aInset); + NS_IMETHOD NeedsRecalc(); + // nsIFrame NS_IMETHOD Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, @@ -85,14 +83,6 @@ public: NS_IMETHOD SetAdditionalStyleContext(PRInt32 aIndex, nsIStyleContext* aStyleContext); -#if 0 - // Overridden to capture events - NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, - const nsPoint& aPoint, - nsFramePaintLayer aWhichLayer, - nsIFrame** aFrame); -#endif - /*BEGIN implementations of dragevent handler interface*/ virtual nsresult HandleEvent(nsIDOMEvent* aEvent); virtual nsresult DragEnter(nsIDOMEvent* aDragEvent); @@ -135,10 +125,7 @@ protected: virtual void UpdateStyles(nsIPresContext* aPresContext); virtual void CalculateGrippies(nsIPresContext* aPresContext); - virtual nsresult ReflowGrippies(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); + virtual nsresult LayoutGrippies(nsBoxLayoutState& aBoxLayoutState); void RefreshStyleContext(nsIPresContext* aPresContext, @@ -167,7 +154,6 @@ protected: nsCOMPtr mGrippyRolloverStyle; nsMargin mInset; - virtual void GetInset(nsMargin& margin); unsigned long mSumOfToolbarHeights; nsVoidArray mGrippies; // list of all active grippies @@ -186,6 +172,7 @@ protected: // nsISupports interface NS_DECL_ISUPPORTS + // nsIDOMEventListener interface virtual nsresult HandleEvent(nsIDOMEvent* aEvent) { @@ -235,6 +222,8 @@ protected: nsToolboxFrame ( const nsToolboxFrame& aFrame ) ; // DO NOT IMPLEMENT nsToolboxFrame& operator= ( const nsToolboxFrame& aFrame ) ; // DO NOT IMPLEMENT + PRBool mNeedsCalc; + nsIPresContext* mPresContext; }; // class nsToolboxFrame #endif diff --git a/mozilla/layout/xul/base/src/nsXULLeafFrame.cpp b/mozilla/layout/xul/base/src/nsXULLeafFrame.cpp deleted file mode 100644 index 7cc5157f23f..00000000000 --- a/mozilla/layout/xul/base/src/nsXULLeafFrame.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * The contents of this file are subject to the Netscape Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is Mozilla Communicator client code. - * - * The Initial Developer of the Original Code is Netscape Communications - * Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - */ - -// -// Eric Vaughan -// Netscape Communications -// -// See documentation in associated header file -// - -#include "nsXULLeafFrame.h" -#include "nsCOMPtr.h" -#include "nsIDeviceContext.h" -#include "nsIFontMetrics.h" -#include "nsHTMLAtoms.h" -#include "nsXULAtoms.h" -#include "nsIPresContext.h" -#include "nsIRenderingContext.h" -#include "nsIStyleContext.h" -#include "nsIContent.h" -#include "nsINameSpaceManager.h" - -// -// NS_NewToolbarFrame -// -// Creates a new Toolbar frame and returns it in |aNewFrame| -// -nsresult -NS_NewXULLeafFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) -{ - NS_PRECONDITION(aNewFrame, "null OUT ptr"); - if (nsnull == aNewFrame) { - return NS_ERROR_NULL_POINTER; - } - nsXULLeafFrame* it = new (aPresShell) nsXULLeafFrame; - if (nsnull == it) - return NS_ERROR_OUT_OF_MEMORY; - - // it->SetFlags(aFlags); - *aNewFrame = it; - return NS_OK; - -} // NS_NewTextFrame - - - -NS_IMETHODIMP -nsXULLeafFrame::Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aMetrics, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) -{ - - if (eReflowReason_Incremental == aReflowState.reason) { - nsIFrame* targetFrame; - - // See if it's targeted at us - aReflowState.reflowCommand->GetTarget(targetFrame); - if (this == targetFrame) { - Invalidate(aPresContext, nsRect(0,0,mRect.width,mRect.height), PR_FALSE); - } - } else if (eReflowReason_Dirty == aReflowState.reason) { - Invalidate(aPresContext, nsRect(0,0,mRect.width,mRect.height), PR_FALSE); - } - - - nsresult result = nsLeafFrame::Reflow(aPresContext, aMetrics, aReflowState, aStatus); - - if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) - NS_ASSERTION(aMetrics.width == aReflowState.mComputedWidth + aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right, - "Text width is wrong!!!"); - - if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) - NS_ASSERTION(aMetrics.height == aReflowState.mComputedHeight + aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom, - "Text height is wrong!!!"); - - return result; -} - -void -nsXULLeafFrame::GetDesiredSize(nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - nsHTMLReflowMetrics& aDesiredSize) -{ - // get our info object. - nsBoxInfo info; - info.Clear(); - - GetBoxInfo(aPresContext, aReflowState, info); - - // size is our preferred unless calculated. - aDesiredSize.width = info.prefSize.width; - aDesiredSize.height = info.prefSize.height; - - // if either the width or the height was not computed use our intrinsic size - if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) - aDesiredSize.width = aReflowState.mComputedWidth; - - if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) { - aDesiredSize.height = aReflowState.mComputedHeight; - nscoord descent = info.prefSize.height - info.ascent; - aDesiredSize.ascent = aDesiredSize.height - descent; - if (aDesiredSize.ascent < 0) - aDesiredSize.ascent = 0; - } else { - aDesiredSize.ascent = info.ascent; - } - - -} - - - -NS_IMETHODIMP -nsXULLeafFrame::InvalidateCache(nsIFrame* aChild) -{ - // we don't cache any information - return NS_OK; -} - -/** - * Ok return our dimensions - */ -NS_IMETHODIMP -nsXULLeafFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize) -{ - aSize.prefSize.width = 0; - aSize.prefSize.height = 0; - aSize.minSize.width = 0; - aSize.minSize.height = 0; - aSize.maxSize.width = NS_INTRINSICSIZE; - aSize.maxSize.height = NS_INTRINSICSIZE; - aSize.ascent = 0; - return NS_OK; -} - -/** - * We can be a nsIBox - */ -NS_IMETHODIMP -nsXULLeafFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr) -{ - if (NULL == aInstancePtr) { - return NS_ERROR_NULL_POINTER; - } - - *aInstancePtr = NULL; - - if (aIID.Equals(NS_GET_IID(nsIBox))) { - *aInstancePtr = (void*)(nsIBox*) this; - NS_ADDREF_THIS(); - return NS_OK; - } - - return nsLeafFrame::QueryInterface(aIID, aInstancePtr); -} - -/* - * We are a frame and we do not maintain a ref count - */ -NS_IMETHODIMP_(nsrefcnt) -nsXULLeafFrame::AddRef(void) -{ - return NS_OK; -} - -NS_IMETHODIMP_(nsrefcnt) -nsXULLeafFrame::Release(void) -{ - return NS_OK; -} - - -NS_IMETHODIMP -nsXULLeafFrame::GetFrameName(nsString& aResult) const -{ - aResult = "Leaf"; - return NS_OK; -} - -NS_IMETHODIMP -nsXULLeafFrame::ContentChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - nsISupports* aSubContent) -{ - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - mState |= NS_FRAME_IS_DIRTY; - return mParent->ReflowDirtyChild(shell, this); - -} - diff --git a/mozilla/layout/xul/content/src/nsXULAtomList.h b/mozilla/layout/xul/content/src/nsXULAtomList.h index cdd0b327209..528b4893b0c 100644 --- a/mozilla/layout/xul/content/src/nsXULAtomList.h +++ b/mozilla/layout/xul/content/src/nsXULAtomList.h @@ -97,6 +97,7 @@ XUL_ATOM(crop, "crop") XUL_ATOM(mode, "mode") XUL_ATOM(box, "box") +XUL_ATOM(mousethrough, "mousethrough") XUL_ATOM(flex, "flex") XUL_ATOM(spring, "spring") XUL_ATOM(orient, "orient") @@ -130,6 +131,13 @@ XUL_ATOM(resizeafter, "resizeafter") XUL_ATOM(state, "state") XUL_ATOM(debug, "debug") +// grid +XUL_ATOM(grid, "grid") +XUL_ATOM(rows, "rows") +XUL_ATOM(columns, "columns") +XUL_ATOM(row, "row") +XUL_ATOM(column, "column") + // toolbar & toolbar d&d atoms XUL_ATOM(ddDropLocation, "dd-droplocation") XUL_ATOM(ddDropLocationCoord, "dd-droplocationcoord") diff --git a/mozilla/profile/resources/content/profileSelection.xul b/mozilla/profile/resources/content/profileSelection.xul index 6c817c09185..879cc0eac93 100644 --- a/mozilla/profile/resources/content/profileSelection.xul +++ b/mozilla/profile/resources/content/profileSelection.xul @@ -31,7 +31,7 @@ - - - &introgeneral.label; - + &introgeneral.label; &pmTextA.label; diff --git a/mozilla/profile/resources/skin/profile.css b/mozilla/profile/resources/skin/profile.css index 61ea7102782..653138ba315 100644 --- a/mozilla/profile/resources/skin/profile.css +++ b/mozilla/profile/resources/skin/profile.css @@ -48,8 +48,8 @@ box[type="largeheader"] > toolbar > .circle { } /* profile selection dialog */ -deck#prattle { - max-width: 17em; +html#intro { + width: 17em; } box#managebuttons > button { diff --git a/mozilla/xpfe/components/sidebar/resources/sidebarOverlay.css b/mozilla/xpfe/components/sidebar/resources/sidebarOverlay.css index 0380197b60d..37269dfc160 100644 --- a/mozilla/xpfe/components/sidebar/resources/sidebarOverlay.css +++ b/mozilla/xpfe/components/sidebar/resources/sidebarOverlay.css @@ -24,8 +24,6 @@ splitter#sidebar-splitter { margin-right: 2px; margin-top: 2px; - min-width: 8px; - max-width: 8px; padding: 0px; border: none; background-color: #003366; @@ -68,7 +66,6 @@ box#sidebar-box { margin-top: 2px; width: 162px; min-height: 1px; - min-width: 1px; max-width: 400px; border: none; border-bottom: 8px solid #003366; @@ -151,3 +148,7 @@ box#sidebar-panels-bottom > box.texttab + box.texttab { *[hidden="true"] { display: none; } + +box#title-box { + min-width: 10px; +} diff --git a/mozilla/xpfe/global/resources/skin/global.css b/mozilla/xpfe/global/resources/skin/global.css index 50ca6bd3327..7dd52820716 100644 --- a/mozilla/xpfe/global/resources/skin/global.css +++ b/mozilla/xpfe/global/resources/skin/global.css @@ -535,28 +535,51 @@ grippy:hover:active{ background-color: #99CCFF; } -box[align="vertical"]>splitter grippy { +box[orient="vertical"]>splitter grippy { /* a horizontal splitter */ - min-width: 60px; - max-height: 4px; + width: 60px; + height:8px; } -box[align="horizontal"]>splitter grippy { +box>splitter grippy { /* a vertical splitter */ - max-width: 4px; - min-height: 60px; + width: 8px; + height: 60px; +} + +window[orient="vertical"]>splitter grippy { + /* a horizontal splitter */ + width: 8px; + height: 10px; +} + +window>splitter grippy { + /* a vertical splitter */ + width: 8px; + height: 60px; +} + +box[orient="vertical"]>splitter { + /* a vertical splitter */ + cursor: n-resize; +} + +window[orient="vertical"]>splitter { + /* a vertical splitter */ + cursor: n-resize; +} + +/* for backwards compatibility */ +box[align="vertical"]>splitter grippy { + /* a horizontal splitter */ + width: 60px; + height: 8px; } window[align="vertical"]>splitter grippy { /* a horizontal splitter */ - min-width: 60px; - max-height: 4px; -} - -window[align="horizontal"]>splitter grippy { - /* a vertical splitter */ - max-width: 4px; - min-height: 60px; + width: 60px; + height: 8px; } box[align="vertical"]>splitter { @@ -596,7 +619,7 @@ splitter.gray-horizontal-splitter grippy:active { splitter.gray-horizontal-splitter #begincap { min-width: 8px; - max-width: 8px; + width: 8px; background-image: url("chrome://global/skin/gray-bottomleft.gif"); background-repeat: no-repeat; background-position: 0% 100%; @@ -604,10 +627,34 @@ splitter.gray-horizontal-splitter #begincap { splitter.gray-horizontal-splitter #endcap { min-width: 8px; - max-width: 8px; + width: 8px; } +/****** Progress Meter ********/ + +progressmeter[align="horizontal"] { + height: 1em; +} + +box.progress-bar { + background-color : #9999cc; +} + +box.progress-remainder { + background-color: #999999; +} + +progressmeter[mode="undetermined"] > .internal-box +{ + background-image: url(chrome://global/skin/progressmeter-busy.gif); +} + +progressmeter[mode="undetermined"] > .internal-box > stack > progressbar +{ + display: none; +} + /********* Box ********/ box @@ -660,6 +707,7 @@ menubar { menu { color: black; + vertical-align: middle; } menu[disabled="true"] { @@ -668,6 +716,7 @@ menu[disabled="true"] { menuitem { color: black; + vertical-align: middle; } menuitem[disabled="true"] { @@ -808,7 +857,6 @@ popup > menuitem[menuactive="true"][disabled="true"] { .menu-right { padding: 0px; border: 0px; - width: 10px; margin-top: 0px; margin-bottom: 0px; margin-left: 6px; @@ -819,7 +867,6 @@ popup > menuitem[menuactive="true"][disabled="true"] { color: inherit; padding: 0px; border: 0px; - width: 13px; margin-top: 0px; margin-bottom: 0px; margin-right: 2px; @@ -888,6 +935,80 @@ menu[menuactive="true"] > .menu-right { list-style-image: url("chrome://global/skin/menu-arrow-hover.gif"); } + +menulist, menubutton { + padding: 1px 0px 1px 0px; +} + +menulist > .menu-text, +menubutton > .menu-text { + padding-left: 4px; + padding-right: 4px; + border: 1px inset #CCCCCC; +} + +menubutton > .menu-button { + border: 1px outset #CCCCCC; + padding: 2px; +} + +menubutton > .menu-button:active { + border: 1px inset #CCCCCC; + padding: 3px 1px 1px 3px; +} + + +menubutton > .menu-dropmarker, +menulist > .menu-dropmarker { + border: 1px outset #CCCCCC; + list-style-image: url("chrome://global/skin/scroll-down.gif"); + padding: 0px 2px 0px 2px; +} + +menubutton[open="true"] > .menu-dropmarker, +menulist[open="true"] > .menu-dropmarker { + border: 1px inset #CCCCCC; + padding: 1px 1px -1px 3px; +} + +menubutton menupopup, menulist menupopup { + border: 1px outset #CCCCCC; +} + +menulist[editable="true"] { + padding: 0px; +} + +menulist[editable="true"] > .menu-text { + border-left: none; + border-top: 1px inset #CCCCCC; + border-right: 1px inset #CCCCCC; + border-bottom: 1px inset #CCCCCC; + margin: 0px 2px 0px 0px; +} + +menulist[editable="true"] > .menu-dropmarker { + border: 1px outset #CCCCCC; +} + +menulist[editable="true"][open="true"] > .menu-dropmarker { + border: 1px inset #CCCCCC; +} + +menulist[editable="true"] > .menu-icon { + list-style-image: url("chrome://bookmarks/skin/bookmark-item.gif"); + background-color: white; + padding: 1px; + border-left: 1px inset #CCCCCC; + border-top: 1px inset #CCCCCC; + border-right: none; + border-bottom: 1px inset #CCCCCC; +} + +menulist menupopup > menuseparator { + border-bottom: 2px groove #CCCCCC; +} + /******** Rules for menus on the standard toolbars ***************/ menu.standard { diff --git a/mozilla/xpfe/global/resources/skin/xul.css b/mozilla/xpfe/global/resources/skin/xul.css index 38f0fe7f63f..7d52fb21769 100644 --- a/mozilla/xpfe/global/resources/skin/xul.css +++ b/mozilla/xpfe/global/resources/skin/xul.css @@ -44,8 +44,6 @@ template { window { overflow: hidden; - height: 100%; - width: 100%; } /********************************** diff --git a/mozilla/xpfe/global/resources/skin/xulBindings.xml b/mozilla/xpfe/global/resources/skin/xulBindings.xml index cc8646e022e..c6686855cfc 100644 --- a/mozilla/xpfe/global/resources/skin/xulBindings.xml +++ b/mozilla/xpfe/global/resources/skin/xulBindings.xml @@ -48,9 +48,9 @@ - + - +