diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 6dd7ba2731bf..664380b7a8ae 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -4569,15 +4569,16 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsIPresShell* aPresShell, const nsStyleDisplay* styleDisplay; newFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) styleDisplay); - nsIFrame * blkFrame; - NS_NewBlockFrame(shell, &blkFrame, flags); + nsIFrame * areaFrame; + //NS_NewBlockFrame(shell, &areaFrame, flags); + NS_NewAreaFrame(shell, &areaFrame, flags | NS_BLOCK_SHRINK_WRAP);// | NS_BLOCK_MARGIN_ROOT); // Resolve style and initialize the frame nsIStyleContext* styleContext; aPresContext->ResolvePseudoStyleContextFor(aContent, nsHTMLAtoms::fieldsetContentPseudo, aStyleContext, PR_FALSE, &styleContext); InitAndRestoreFrame(aPresContext, aState, aContent, - newFrame, styleContext, nsnull, blkFrame); + newFrame, styleContext, nsnull, areaFrame); NS_RELEASE(styleContext); @@ -4587,7 +4588,7 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsIPresShell* aPresShell, HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, &haveFirstLetterStyle, &haveFirstLineStyle); nsFrameConstructorSaveState floaterSaveState; - aState.PushFloaterContainingBlock(blkFrame, floaterSaveState, + aState.PushFloaterContainingBlock(areaFrame, floaterSaveState, haveFirstLetterStyle, haveFirstLineStyle); @@ -4600,10 +4601,10 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsIPresShell* aPresShell, if (isPositionedContainingBlock) { // The area frame becomes a container for child frames that are // absolutely positioned - aState.PushAbsoluteContainingBlock(blkFrame, absoluteSaveState); + aState.PushAbsoluteContainingBlock(areaFrame, absoluteSaveState); } - ProcessChildren(aPresShell, aPresContext, aState, aContent, blkFrame, PR_FALSE, + ProcessChildren(aPresShell, aPresContext, aState, aContent, areaFrame, PR_FALSE, childItems, PR_TRUE); static NS_DEFINE_IID(kLegendFrameCID, NS_LEGEND_FRAME_CID); @@ -4617,7 +4618,7 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsIPresShell* aPresShell, nsIFrame * nxt; legendFrame->GetNextSibling(&nxt); previous->SetNextSibling(nxt); - blkFrame->SetNextSibling(legendFrame); + areaFrame->SetNextSibling(legendFrame); legendFrame->SetParent(newFrame); legendFrame->SetNextSibling(nsnull); break; @@ -4625,7 +4626,7 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsIPresShell* aPresShell, nsIFrame * nxt; legendFrame->GetNextSibling(&nxt); childItems.childList = nxt; - blkFrame->SetNextSibling(legendFrame); + areaFrame->SetNextSibling(legendFrame); legendFrame->SetParent(newFrame); legendFrame->SetNextSibling(nsnull); break; @@ -4636,21 +4637,21 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsIPresShell* aPresShell, } // Set the scrolled frame's initial child lists - blkFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); + areaFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); if (isPositionedContainingBlock && aState.mAbsoluteItems.childList) { - blkFrame->SetInitialChildList(aPresContext, + areaFrame->SetInitialChildList(aPresContext, nsLayoutAtoms::absoluteList, aState.mAbsoluteItems.childList); } if (aState.mFloatedItems.childList) { - blkFrame->SetInitialChildList(aPresContext, + areaFrame->SetInitialChildList(aPresContext, nsLayoutAtoms::floaterList, aState.mFloatedItems.childList); } // Set the scroll frame's initial child list - newFrame->SetInitialChildList(aPresContext, nsnull, blkFrame); + newFrame->SetInitialChildList(aPresContext, nsnull, areaFrame); // our new frame retured is the top frame which is the list frame. aNewFrame = newFrame; @@ -5152,11 +5153,11 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell, nsFrameConstructorState& aState, nsIContent* aParent, nsIDocument* aDocument, - nsIFrame* aNewFrame, + nsIFrame* aParentFrame, nsFrameItems& aChildItems) { - nsCOMPtr creator(do_QueryInterface(aNewFrame)); + nsCOMPtr creator(do_QueryInterface(aParentFrame)); if (!creator) return NS_OK; @@ -5180,8 +5181,14 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell, content->SetParent(aParent); content->SetDocument(aDocument, PR_TRUE); - // create the frame and attach it to our frame - ConstructFrame(aPresShell, aPresContext, aState, content, aNewFrame, aChildItems); + nsIFrame * newFrame = nsnull; + nsresult rv = creator->CreateFrameFor(aPresContext, content, &newFrame); + if (NS_SUCCEEDED(rv) && newFrame != nsnull) { + aChildItems.AddChild(newFrame); + } else { + // create the frame and attach it to our frame + ConstructFrame(aPresShell, aPresContext, aState, content, aParentFrame, aChildItems); + } } return NS_OK; diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index eeec58df6326..900ec0bd9ff5 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -57,11 +57,13 @@ #include "nsTextFragment.h" #include "nsCSSFrameConstructor.h" #include "nsIDocument.h" +#include "nsIScrollableFrame.h" #ifdef DO_NEW_REFLOW #include "nsIFontMetrics.h" #endif +static const PRBool kGoodToGo = PR_FALSE; static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); static NS_DEFINE_IID(kIComboboxControlFrameIID, NS_ICOMBOBOXCONTROLFRAME_IID); @@ -906,6 +908,7 @@ nsComboboxControlFrame::ReflowCombobox(nsIPresContext * aPresContext, nsHTMLReflowState txtKidReflowState(aPresContext, aReflowState, aDisplayFrame, txtAvailSize); aDisplayFrame->WillReflow(aPresContext); + //aDisplayFrame->MoveTo(aPresContext, dspBorderPadding.left + aBorderPadding.left, dspBorderPadding.top + aBorderPadding.top); aDisplayFrame->MoveTo(aPresContext, aBorderPadding.left, aBorderPadding.top); nsIView* view; aDisplayFrame->GetView(aPresContext, &view); @@ -943,8 +946,8 @@ nsComboboxControlFrame::ReflowCombobox(nsIPresContext * aPresContext, // set the display rect to be left justifed and // fills the entire area except the button nscoord x = aBorderPadding.left; - displayRect.x = x; - displayRect.y = aBorderPadding.top; + displayRect.x = x;// + dspBorderPadding.left; + displayRect.y = aBorderPadding.top;// + dspBorderPadding.top; displayRect.height = insideHeight; displayRect.width = dispWidth - aBtnWidth; aDisplayFrame->SetRect(aPresContext, displayRect); @@ -1228,24 +1231,18 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // then it look like we are suppose to be showing the dropdown // XXX - It is really to bad we have to reflow at all // just to get it to show up or be hidden + nsIFrame * incrementalChild; + aReflowState.reflowCommand->GetNext(incrementalChild); if (nsViewVisibility_kHide == vis && mDroppedDown) { bail = PR_TRUE; // Do a constrained reflow at a predetermined size // to have the dropdown shown - firstPassState.reason = eReflowReason_StyleChange; - firstPassState.reflowCommand = nsnull; - mListControlFrame->SetOverrideReflowOptimization(PR_TRUE); nscoord width = mCacheSize.width > kSizeNotSet?PR_MAX(mCacheSize.width, dropdownRect.width):NS_UNCONSTRAINEDSIZE; - ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, width, NS_UNCONSTRAINEDSIZE); - + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, aReflowState, aStatus, width, NS_UNCONSTRAINEDSIZE); } else if (nsViewVisibility_kShow == vis && !mDroppedDown) { bail = PR_TRUE; - // Do a Unconstrained reflow to "roll" it up - // then cache that unconstrained size - firstPassState.reason = eReflowReason_StyleChange; - firstPassState.reflowCommand = nsnull; - mListControlFrame->SetOverrideReflowOptimization(PR_TRUE); - ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + nscoord width = mCacheSize.width > kSizeNotSet?PR_MAX(mCacheSize.width, dropdownRect.width):NS_UNCONSTRAINEDSIZE; + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, aReflowState, aStatus, width, NS_UNCONSTRAINEDSIZE); // cache the values here also, // since we just did an unconstrained reflow mCachedUncDropdownSize.width = dropdownDesiredSize.width; @@ -1294,13 +1291,13 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, //mListControlFrame->SetOverrideReflowOptimization(PR_TRUE); } else if (targetFrame == mDisplayFrame || targetFrame == buttonFrame) { - /*if (targetFrame == mDisplayFrame) { + if (targetFrame == mDisplayFrame) { nsresult rv = ReflowComboChildFrame(mDisplayFrame, aPresContext, aDesiredSize, aReflowState, aStatus, aReflowState.availableWidth, aReflowState.availableHeight); return rv; - }*/ + } // The incremental reflow is targeted at either the block or the button REFLOW_DEBUG_MSG2("-----------------Target is %s------------\n", (targetFrame == mDisplayFrame?"DisplayItem Frame":"DropDown Btn Frame")); @@ -1314,6 +1311,27 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, UNCONSTRAINED_CHECK(); return rv; } else { + nsIFrame * plainLstFrame; + if (NS_SUCCEEDED(mListControlFrame->QueryInterface(kIFrameIID, (void**)&plainLstFrame))) { + nsIFrame * frame; + plainLstFrame->FirstChild(aPresContext, nsnull, &frame); + nsIScrollableFrame * scrollFrame; + if (NS_SUCCEEDED(frame->QueryInterface(NS_GET_IID(nsIScrollableFrame), (void**)&scrollFrame))) { + nsRect rect; + plainLstFrame->GetRect(rect); + nsresult rvv = plainLstFrame->Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + + aDesiredSize.width = mCacheSize.width; + aDesiredSize.height = mCacheSize.height; + + if (aDesiredSize.maxElementSize != nsnull) { + aDesiredSize.maxElementSize->width = mCachedMaxElementSize.width; + aDesiredSize.maxElementSize->height = mCachedMaxElementSize.height; + } + return NS_OK; + } + } + // Here the target of the reflow was a child of the dropdown list // so we must do a full reflow REFLOW_DEBUG_MSG("-----------------Target is Dropdown's Child (Option Item)------------\n"); @@ -1572,12 +1590,6 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, } -//------------------------------------------------------------------------------- -//------------------------------------------------------------------------------- -// Done with New Reflow -//------------------------------------------------------------------------------- -//------------------------------------------------------------------------------- - //-------------------------------------------------------------- NS_IMETHODIMP nsComboboxControlFrame::GetName(nsString* aResult) @@ -1646,7 +1658,6 @@ nsComboboxControlFrame::GetFrameForPoint(nsIPresContext* aPresContext, nsIFrame** aFrame) { PRBool inThisFrame = mRect.Contains(aPoint); - if (! ((mState & NS_FRAME_OUTSIDE_CHILDREN) || inThisFrame) ) { return NS_ERROR_FAILURE; } @@ -1661,13 +1672,17 @@ nsComboboxControlFrame::GetFrameForPoint(nsIPresContext* aPresContext, return NS_ERROR_FAILURE; } +#if 0 if (aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND) { nsresult rv = GetFrameForPointUsing(aPresContext, aPoint, nsnull, NS_FRAME_PAINT_LAYER_FOREGROUND, PR_FALSE, aFrame); if (NS_SUCCEEDED(rv)) return rv; return GetFrameForPointUsing(aPresContext, aPoint, nsnull, NS_FRAME_PAINT_LAYER_BACKGROUND, PR_TRUE, aFrame); } - return NS_ERROR_FAILURE; +#else + *aFrame = this; + return NS_OK; +#endif } @@ -1847,15 +1862,19 @@ nsComboboxControlFrame::SelectionChanged() if (shouldSetValue) { rv = mDisplayContent->SetText(mTextStr.GetUnicode(), mTextStr.Length(), PR_TRUE); nsFrameState state; - mTextFrame->GetFrameState(&state); - state |= NS_FRAME_IS_DIRTY; - mTextFrame->SetFrameState(state); + //mTextFrame->GetFrameState(&state); + //state |= NS_FRAME_IS_DIRTY; + //mTextFrame->SetFrameState(state); mDisplayFrame->GetFrameState(&state); state |= NS_FRAME_IS_DIRTY; mDisplayFrame->SetFrameState(state); nsCOMPtr shell; rv = mPresContext->GetShell(getter_AddRefs(shell)); ReflowDirtyChild(shell, (nsIFrame*) mDisplayFrame); + + nsCOMPtr presShell; + mPresContext->GetShell(getter_AddRefs(presShell)); + presShell->FlushPendingNotifications(); } } return rv; @@ -2006,6 +2025,9 @@ nsComboboxControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) NS_IMETHODIMP nsComboboxControlFrame::CreateDisplayFrame(nsIPresContext* aPresContext) { + if (kGoodToGo) { + return NS_OK; + } nsCOMPtr shell; aPresContext->GetShell(getter_AddRefs(shell)); @@ -2090,11 +2112,13 @@ nsComboboxControlFrame::CreateAnonymousContent(nsIPresContext* aPresContext, mDisplayContent = do_QueryInterface(labelContent); mDisplayContent->SetText(value.GetUnicode(), value.Length(), PR_TRUE); - nsIDocument* doc; + /*nsIDocument* doc; mContent->GetDocument(doc); labelContent->SetDocument(doc, PR_FALSE); NS_RELEASE(doc); mContent->AppendChildTo(labelContent, PR_FALSE); + */ + aChildList.AppendElement(labelContent); // create button which drops the list down result = NS_NewHTMLInputElement(&mButtonContent, nsHTMLAtoms::input); @@ -2108,6 +2132,82 @@ nsComboboxControlFrame::CreateAnonymousContent(nsIPresContext* aPresContext, return NS_OK; } +NS_IMETHODIMP +nsComboboxControlFrame::CreateFrameFor(nsIPresContext* aPresContext, + nsIContent * aContent, + nsIFrame** aFrame) +{ + NS_PRECONDITION(nsnull != aFrame, "null ptr"); + NS_PRECONDITION(nsnull != aContent, "null ptr"); + NS_PRECONDITION(nsnull != aPresContext, "null ptr"); + + *aFrame = nsnull; + NS_ASSERTION(mDisplayContent != nsnull, "mDisplayContent can't be null!"); + + if (!kGoodToGo) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr content(do_QueryInterface(mDisplayContent)); + if (aContent == content.get()) { + // Get PresShell + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + + // Start by by creating a containing frame + nsresult rv = NS_NewBlockFrame(shell, (nsIFrame**)&mDisplayFrame, NS_BLOCK_SPACE_MGR); + if (NS_FAILED(rv)) { return rv; } + if (!mDisplayFrame) { return NS_ERROR_NULL_POINTER; } + + // create the style context for the anonymous block frame + nsCOMPtr styleContext; + rv = aPresContext->ResolvePseudoStyleContextFor(content, + nsHTMLAtoms::mozDisplayComboboxControlFrame, + mStyleContext, + PR_FALSE, + getter_AddRefs(styleContext)); + if (NS_FAILED(rv)) { return rv; } + if (!styleContext) { return NS_ERROR_NULL_POINTER; } + + // Create a text frame and put it inside the block frame + rv = NS_NewTextFrame(shell, &mTextFrame); + if (NS_FAILED(rv)) { return rv; } + if (!mTextFrame) { return NS_ERROR_NULL_POINTER; } + nsCOMPtr textStyleContext; + rv = aPresContext->ResolvePseudoStyleContextFor(content, + nsHTMLAtoms::mozDisplayComboboxControlFrame,//nsHTMLAtoms::textPseudo, + styleContext, + PR_FALSE, + getter_AddRefs(textStyleContext)); + if (NS_FAILED(rv)) { return rv; } + if (!textStyleContext) { return NS_ERROR_NULL_POINTER; } + + // initialize the text frame + nsCOMPtr content(do_QueryInterface(mDisplayContent)); + mTextFrame->Init(aPresContext, content, mDisplayFrame, textStyleContext, nsnull); + mTextFrame->SetInitialChildList(aPresContext, nsnull, nsnull); + + /*nsCOMPtr frameManager; + rv = shell->GetFrameManager(getter_AddRefs(frameManager)); + if (NS_FAILED(rv)) { return rv; } + if (!frameManager) { return NS_ERROR_NULL_POINTER; } + frameManager->SetPrimaryFrameFor(content, mTextFrame); + */ + + rv = mDisplayFrame->Init(aPresContext, content, this, styleContext, nsnull); + if (NS_FAILED(rv)) { return rv; } + + mDisplayFrame->SetInitialChildList(aPresContext, nsnull, mTextFrame); + *aFrame = mDisplayFrame; + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + + + + NS_IMETHODIMP nsComboboxControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight) { @@ -2137,13 +2237,13 @@ nsComboboxControlFrame::Destroy(nsIPresContext* aPresContext) // Cleanup frames in popup child list mPopupFrames.DestroyFrames(aPresContext); - if (mDisplayFrame) { + /*if (mDisplayFrame) { mFrameConstructor->RemoveMappingsForFrameSubtree(aPresContext, mDisplayFrame, nsnull); mDisplayFrame->Destroy(aPresContext); mDisplayFrame=nsnull; - } + }*/ - if (mDisplayContent) { + /*if (mDisplayContent) { nsCOMPtr content(do_QueryInterface(mDisplayContent)); if (content) { PRInt32 index; @@ -2151,7 +2251,7 @@ nsComboboxControlFrame::Destroy(nsIPresContext* aPresContext) mContent->RemoveChildAt(index, PR_FALSE); } } - } + }*/ return nsAreaFrame::Destroy(aPresContext); } @@ -2181,6 +2281,17 @@ nsComboboxControlFrame::SetInitialChildList(nsIPresContext* aPresContext, } else { rv = nsAreaFrame::SetInitialChildList(aPresContext, aListName, aChildList); InitTextStr(aPresContext, PR_FALSE); + + nsIFrame * child = aChildList; + while (child != nsnull) { + nsIFormControlFrame* fcFrame = nsnull; + nsresult rv = child->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + if (NS_FAILED(rv) && fcFrame == nsnull) { + mDisplayFrame = child; + break; + } + child->GetNextSibling(&child); + } } return rv; } @@ -2282,6 +2393,10 @@ nsComboboxControlFrame::Paint(nsIPresContext* aPresContext, #endif nsAreaFrame::Paint(aPresContext,aRenderingContext,aDirtyRect,aWhichLayer); + if (kGoodToGo) { + return NS_OK; + } + if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { if (mDisplayFrame) { aRenderingContext.PushState(); @@ -2293,12 +2408,38 @@ nsComboboxControlFrame::Paint(nsIPresContext* aPresContext, mDisplayFrame, NS_FRAME_PAINT_LAYER_BACKGROUND); PaintChild(aPresContext, aRenderingContext, aDirtyRect, mDisplayFrame, NS_FRAME_PAINT_LAYER_FOREGROUND); + + ///////////////////// + // draw focus + // XXX This is only temporary + nsCOMPtr stateManager; + nsresult rv = mPresContext->GetEventStateManager(getter_AddRefs(stateManager)); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr content; + rv = stateManager->GetFocusedContent(getter_AddRefs(content)); + if (NS_SUCCEEDED(rv) && content && content.get() == mContent) { + aRenderingContext.SetLineStyle(nsLineStyle_kDotted); + aRenderingContext.SetColor(0); + //aRenderingContext.DrawRect(clipRect); + float p2t; + aPresContext->GetPixelsToTwips(&p2t); + nscoord onePixel = NSIntPixelsToTwips(1, p2t); + clipRect.width -= onePixel; + clipRect.height -= onePixel; + aRenderingContext.DrawLine(clipRect.x, clipRect.y, + clipRect.x+clipRect.width, clipRect.y); + aRenderingContext.DrawLine(clipRect.x+clipRect.width, clipRect.y, + clipRect.x+clipRect.width, clipRect.y+clipRect.height); + aRenderingContext.DrawLine(clipRect.x+clipRect.width, clipRect.y+clipRect.height, + clipRect.x, clipRect.y+clipRect.height); + aRenderingContext.DrawLine(clipRect.x, clipRect.y+clipRect.height, + clipRect.x, clipRect.y); + } + } + ///////////////////// aRenderingContext.PopState(clipEmpty); } } - //nsRect rect(0, 0, 50000, 50000); - //aRenderingContext.SetColor(NS_RGB(255, 0, 0)); - //aRenderingContext.FillRect(rect); return NS_OK; } diff --git a/layout/forms/nsComboboxControlFrame.h b/layout/forms/nsComboboxControlFrame.h index 7ed74554b699..a2f772dbbf00 100644 --- a/layout/forms/nsComboboxControlFrame.h +++ b/layout/forms/nsComboboxControlFrame.h @@ -28,8 +28,8 @@ #endif #ifdef DEBUG_rods -//#define DO_REFLOW_DEBUG -//#define DO_REFLOW_COUNTER +#define DO_REFLOW_DEBUG +#define DO_REFLOW_COUNTER //#define DO_UNCONSTRAINED_CHECK //#define DO_PIXELS //#define DO_NEW_REFLOW @@ -79,6 +79,9 @@ public: // nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aChildList); + NS_IMETHOD CreateFrameFor(nsIPresContext* aPresContext, + nsIContent * aContent, + nsIFrame** aFrame); // nsIFrame NS_IMETHOD Init(nsIPresContext* aPresContext, @@ -174,7 +177,10 @@ public: NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); //nsIRollupListener + // NS_DECL_NSIROLLUPLISTENER NS_IMETHOD Rollup(); + NS_IMETHOD ShouldRollupOnMouseWheelEvent(nsIWidget *aWidget, PRBool *aShouldRollup) + { *aShouldRollup = PR_FALSE; return NS_OK;} NS_IMETHOD SetFrameConstructor(nsCSSFrameConstructor *aConstructor) { mFrameConstructor = aConstructor; return NS_OK;} // not owner - do not addref! diff --git a/layout/forms/nsFileControlFrame.h b/layout/forms/nsFileControlFrame.h index fbd1f293aeba..4f7b4ed42a28 100644 --- a/layout/forms/nsFileControlFrame.h +++ b/layout/forms/nsFileControlFrame.h @@ -116,6 +116,9 @@ public: // from nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aChildList); + NS_IMETHOD CreateFrameFor(nsIPresContext* aPresContext, + nsIContent * aContent, + nsIFrame** aFrame) { if (aFrame) *aFrame = nsnull; return NS_ERROR_FAILURE; } // mouse events when out browse button is pressed diff --git a/layout/forms/nsGfxButtonControlFrame.h b/layout/forms/nsGfxButtonControlFrame.h index 7290ca219f1a..a5063ab07c39 100644 --- a/layout/forms/nsGfxButtonControlFrame.h +++ b/layout/forms/nsGfxButtonControlFrame.h @@ -68,6 +68,9 @@ public: // nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aChildList); + NS_IMETHOD CreateFrameFor(nsIPresContext* aPresContext, + nsIContent * aContent, + nsIFrame** aFrame) { if (aFrame) *aFrame = nsnull; return NS_ERROR_FAILURE; } protected: NS_IMETHOD AddComputedBorderPaddingToDesiredSize(nsHTMLReflowMetrics& aDesiredSize, diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index 785e4b447af4..14b4f521020e 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/layout/forms/nsListControlFrame.cpp @@ -56,6 +56,7 @@ #include "nsLayoutAtoms.h" #include "nsIFontMetrics.h" #include "nsVoidArray.h" +#include "nsIScrollableFrame.h" #include "nsISelectElement.h" @@ -225,6 +226,8 @@ nsListControlFrame::nsListControlFrame() mEndExtendedIndex = kNothingSelected; mStartExtendedIndex = kNothingSelected; mIsCapturingMouseEvents = PR_FALSE; + mDelayedIndexSetting = kNothingSelected; + mDelayedValueSetting = PR_FALSE; mSelectionCache = new nsVoidArray(); mSelectionCacheLength = 0; @@ -367,6 +370,18 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, printSize("CW", aReflowState.mComputedWidth); printSize("CH", aReflowState.mComputedHeight); printf("\n"); +#if 0 + { + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display); + printf("+++++++++++++++++++++++++++++++++ "); + switch (display->mVisible) { + case NS_STYLE_VISIBILITY_COLLAPSE: printf("NS_STYLE_VISIBILITY_COLLAPSE\n");break; + case NS_STYLE_VISIBILITY_HIDDEN: printf("NS_STYLE_VISIBILITY_HIDDEN\n");break; + case NS_STYLE_VISIBILITY_VISIBLE: printf("NS_STYLE_VISIBILITY_VISIBLE\n");break; + } + } +#endif #endif // DEBUG_rodsXXX PRBool bailOnWidth; @@ -430,6 +445,11 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, #endif // DEBUG_rodsXXX + if (mDelayedIndexSetting != kNothingSelected) { + SetOptionSelected(mDelayedIndexSetting, mDelayedValueSetting); + mDelayedIndexSetting = kNothingSelected; + } + // If all the content and frames are here // then initialize it before reflow if (mIsAllContentHere && !mHasBeenInitialized) { @@ -537,6 +557,16 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, return res; } + nsIScrollableFrame * scrollableFrame = nsnull; + nsRect scrolledRect; + if (NS_SUCCEEDED(QueryInterface(NS_GET_IID(nsIScrollableFrame), (void**)&scrollableFrame))) { + nsIFrame * scrolledFrame; + scrollableFrame->GetScrolledFrame(aPresContext, scrolledFrame); + NS_ASSERTION(scrolledFrame != nsnull, "Must have scrollable frame"); + scrolledFrame->GetRect(scrolledRect); + } else { + NS_ASSERTION(scrollableFrame != nsnull, "Must have scrollableFrame frame"); + } // Compute the bounding box of the contents of the list using the area // calculated by the first reflow as a starting point. // @@ -1614,17 +1644,28 @@ nsListControlFrame::SetContentSelected(PRInt32 aIndex, PRBool aSelected) return; } nsIContent* content = GetOptionContent(aIndex); - //NS_ASSERTION(nsnull != content && aIndex == 0, "Failed to retrieve option content"); - if (nsnull != content) { - if (aSelected) { - DisplaySelected(content); - // Now that it is selected scroll to it - ScrollToFrame(content); - } else { - DisplayDeselected(content); + + nsCOMPtr presShell; + mPresContext->GetShell(getter_AddRefs(presShell)); + nsIFrame * childframe; + nsresult result = presShell->GetPrimaryFrameFor(content, &childframe); + if (NS_SUCCEEDED(result) && childframe != nsnull) { + //NS_ASSERTION(nsnull != content && aIndex == 0, "Failed to retrieve option content"); + if (nsnull != content) { + if (aSelected) { + DisplaySelected(content); + // Now that it is selected scroll to it + ScrollToFrame(content); + } else { + DisplayDeselected(content); + } + NS_RELEASE(content); } - NS_RELEASE(content); + } else { + mDelayedIndexSetting = aIndex; + mDelayedValueSetting = aSelected; } + } //--------------------------------------------------------- diff --git a/layout/forms/nsListControlFrame.h b/layout/forms/nsListControlFrame.h index 90679599cf08..85990a820b88 100644 --- a/layout/forms/nsListControlFrame.h +++ b/layout/forms/nsListControlFrame.h @@ -265,6 +265,9 @@ protected: PRBool mOverrideReflowOpt; + PRInt32 mDelayedIndexSetting; + PRBool mDelayedValueSetting; + nsIPresContext* mPresContext; // XXX: Remove the need to cache the pres context. nsCOMPtr mPresState; // Need cache state when list is null diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 85856e75024b..b3a4bb08ebcb 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -103,6 +103,9 @@ public: // nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aAnonymousItems); + NS_IMETHOD CreateFrameFor(nsIPresContext* aPresContext, + nsIContent * aContent, + nsIFrame** aFrame) { if (aFrame) *aFrame = nsnull; return NS_ERROR_FAILURE; } // nsIBox methods NS_DECL_ISUPPORTS diff --git a/layout/generic/nsIAnonymousContentCreator.h b/layout/generic/nsIAnonymousContentCreator.h index c2294dd9a7be..feb843496e06 100644 --- a/layout/generic/nsIAnonymousContentCreator.h +++ b/layout/generic/nsIAnonymousContentCreator.h @@ -31,6 +31,8 @@ class nsIPresContext; class nsISupportsArray; class nsIAtom; +class nsIStyleContext; +class nsIFrame; // {41a69e00-2d6d-11d3-b033-a1357139787c} @@ -47,6 +49,12 @@ public: static const nsIID& GetIID() { static nsIID iid = NS_IANONYMOUS_CONTENT_CREATOR_IID; return iid; } NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aAnonymousItems)=0; + + // If the creator doesn't want to create special fframe ro frame hierarchy + // then it should null out the style content arg and return NS_ERROR_FAILURE + NS_IMETHOD CreateFrameFor(nsIPresContext* aPresContext, + nsIContent * aContent, + nsIFrame** aFrame)=0; }; nsresult NS_CreateAnonymousNode(nsIContent* aParent, nsIAtom* aTag, PRInt32 aNameSpaceId, nsCOMPtr& aNewNode); diff --git a/layout/html/base/src/nsGfxScrollFrame.h b/layout/html/base/src/nsGfxScrollFrame.h index 85856e75024b..b3a4bb08ebcb 100644 --- a/layout/html/base/src/nsGfxScrollFrame.h +++ b/layout/html/base/src/nsGfxScrollFrame.h @@ -103,6 +103,9 @@ public: // nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aAnonymousItems); + NS_IMETHOD CreateFrameFor(nsIPresContext* aPresContext, + nsIContent * aContent, + nsIFrame** aFrame) { if (aFrame) *aFrame = nsnull; return NS_ERROR_FAILURE; } // nsIBox methods NS_DECL_ISUPPORTS diff --git a/layout/html/base/src/nsIAnonymousContentCreator.h b/layout/html/base/src/nsIAnonymousContentCreator.h index c2294dd9a7be..feb843496e06 100644 --- a/layout/html/base/src/nsIAnonymousContentCreator.h +++ b/layout/html/base/src/nsIAnonymousContentCreator.h @@ -31,6 +31,8 @@ class nsIPresContext; class nsISupportsArray; class nsIAtom; +class nsIStyleContext; +class nsIFrame; // {41a69e00-2d6d-11d3-b033-a1357139787c} @@ -47,6 +49,12 @@ public: static const nsIID& GetIID() { static nsIID iid = NS_IANONYMOUS_CONTENT_CREATOR_IID; return iid; } NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aAnonymousItems)=0; + + // If the creator doesn't want to create special fframe ro frame hierarchy + // then it should null out the style content arg and return NS_ERROR_FAILURE + NS_IMETHOD CreateFrameFor(nsIPresContext* aPresContext, + nsIContent * aContent, + nsIFrame** aFrame)=0; }; nsresult NS_CreateAnonymousNode(nsIContent* aParent, nsIAtom* aTag, PRInt32 aNameSpaceId, nsCOMPtr& aNewNode); diff --git a/layout/html/forms/src/nsComboboxControlFrame.cpp b/layout/html/forms/src/nsComboboxControlFrame.cpp index eeec58df6326..900ec0bd9ff5 100644 --- a/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/layout/html/forms/src/nsComboboxControlFrame.cpp @@ -57,11 +57,13 @@ #include "nsTextFragment.h" #include "nsCSSFrameConstructor.h" #include "nsIDocument.h" +#include "nsIScrollableFrame.h" #ifdef DO_NEW_REFLOW #include "nsIFontMetrics.h" #endif +static const PRBool kGoodToGo = PR_FALSE; static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); static NS_DEFINE_IID(kIComboboxControlFrameIID, NS_ICOMBOBOXCONTROLFRAME_IID); @@ -906,6 +908,7 @@ nsComboboxControlFrame::ReflowCombobox(nsIPresContext * aPresContext, nsHTMLReflowState txtKidReflowState(aPresContext, aReflowState, aDisplayFrame, txtAvailSize); aDisplayFrame->WillReflow(aPresContext); + //aDisplayFrame->MoveTo(aPresContext, dspBorderPadding.left + aBorderPadding.left, dspBorderPadding.top + aBorderPadding.top); aDisplayFrame->MoveTo(aPresContext, aBorderPadding.left, aBorderPadding.top); nsIView* view; aDisplayFrame->GetView(aPresContext, &view); @@ -943,8 +946,8 @@ nsComboboxControlFrame::ReflowCombobox(nsIPresContext * aPresContext, // set the display rect to be left justifed and // fills the entire area except the button nscoord x = aBorderPadding.left; - displayRect.x = x; - displayRect.y = aBorderPadding.top; + displayRect.x = x;// + dspBorderPadding.left; + displayRect.y = aBorderPadding.top;// + dspBorderPadding.top; displayRect.height = insideHeight; displayRect.width = dispWidth - aBtnWidth; aDisplayFrame->SetRect(aPresContext, displayRect); @@ -1228,24 +1231,18 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // then it look like we are suppose to be showing the dropdown // XXX - It is really to bad we have to reflow at all // just to get it to show up or be hidden + nsIFrame * incrementalChild; + aReflowState.reflowCommand->GetNext(incrementalChild); if (nsViewVisibility_kHide == vis && mDroppedDown) { bail = PR_TRUE; // Do a constrained reflow at a predetermined size // to have the dropdown shown - firstPassState.reason = eReflowReason_StyleChange; - firstPassState.reflowCommand = nsnull; - mListControlFrame->SetOverrideReflowOptimization(PR_TRUE); nscoord width = mCacheSize.width > kSizeNotSet?PR_MAX(mCacheSize.width, dropdownRect.width):NS_UNCONSTRAINEDSIZE; - ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, width, NS_UNCONSTRAINEDSIZE); - + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, aReflowState, aStatus, width, NS_UNCONSTRAINEDSIZE); } else if (nsViewVisibility_kShow == vis && !mDroppedDown) { bail = PR_TRUE; - // Do a Unconstrained reflow to "roll" it up - // then cache that unconstrained size - firstPassState.reason = eReflowReason_StyleChange; - firstPassState.reflowCommand = nsnull; - mListControlFrame->SetOverrideReflowOptimization(PR_TRUE); - ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + nscoord width = mCacheSize.width > kSizeNotSet?PR_MAX(mCacheSize.width, dropdownRect.width):NS_UNCONSTRAINEDSIZE; + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, aReflowState, aStatus, width, NS_UNCONSTRAINEDSIZE); // cache the values here also, // since we just did an unconstrained reflow mCachedUncDropdownSize.width = dropdownDesiredSize.width; @@ -1294,13 +1291,13 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, //mListControlFrame->SetOverrideReflowOptimization(PR_TRUE); } else if (targetFrame == mDisplayFrame || targetFrame == buttonFrame) { - /*if (targetFrame == mDisplayFrame) { + if (targetFrame == mDisplayFrame) { nsresult rv = ReflowComboChildFrame(mDisplayFrame, aPresContext, aDesiredSize, aReflowState, aStatus, aReflowState.availableWidth, aReflowState.availableHeight); return rv; - }*/ + } // The incremental reflow is targeted at either the block or the button REFLOW_DEBUG_MSG2("-----------------Target is %s------------\n", (targetFrame == mDisplayFrame?"DisplayItem Frame":"DropDown Btn Frame")); @@ -1314,6 +1311,27 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, UNCONSTRAINED_CHECK(); return rv; } else { + nsIFrame * plainLstFrame; + if (NS_SUCCEEDED(mListControlFrame->QueryInterface(kIFrameIID, (void**)&plainLstFrame))) { + nsIFrame * frame; + plainLstFrame->FirstChild(aPresContext, nsnull, &frame); + nsIScrollableFrame * scrollFrame; + if (NS_SUCCEEDED(frame->QueryInterface(NS_GET_IID(nsIScrollableFrame), (void**)&scrollFrame))) { + nsRect rect; + plainLstFrame->GetRect(rect); + nsresult rvv = plainLstFrame->Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + + aDesiredSize.width = mCacheSize.width; + aDesiredSize.height = mCacheSize.height; + + if (aDesiredSize.maxElementSize != nsnull) { + aDesiredSize.maxElementSize->width = mCachedMaxElementSize.width; + aDesiredSize.maxElementSize->height = mCachedMaxElementSize.height; + } + return NS_OK; + } + } + // Here the target of the reflow was a child of the dropdown list // so we must do a full reflow REFLOW_DEBUG_MSG("-----------------Target is Dropdown's Child (Option Item)------------\n"); @@ -1572,12 +1590,6 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, } -//------------------------------------------------------------------------------- -//------------------------------------------------------------------------------- -// Done with New Reflow -//------------------------------------------------------------------------------- -//------------------------------------------------------------------------------- - //-------------------------------------------------------------- NS_IMETHODIMP nsComboboxControlFrame::GetName(nsString* aResult) @@ -1646,7 +1658,6 @@ nsComboboxControlFrame::GetFrameForPoint(nsIPresContext* aPresContext, nsIFrame** aFrame) { PRBool inThisFrame = mRect.Contains(aPoint); - if (! ((mState & NS_FRAME_OUTSIDE_CHILDREN) || inThisFrame) ) { return NS_ERROR_FAILURE; } @@ -1661,13 +1672,17 @@ nsComboboxControlFrame::GetFrameForPoint(nsIPresContext* aPresContext, return NS_ERROR_FAILURE; } +#if 0 if (aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND) { nsresult rv = GetFrameForPointUsing(aPresContext, aPoint, nsnull, NS_FRAME_PAINT_LAYER_FOREGROUND, PR_FALSE, aFrame); if (NS_SUCCEEDED(rv)) return rv; return GetFrameForPointUsing(aPresContext, aPoint, nsnull, NS_FRAME_PAINT_LAYER_BACKGROUND, PR_TRUE, aFrame); } - return NS_ERROR_FAILURE; +#else + *aFrame = this; + return NS_OK; +#endif } @@ -1847,15 +1862,19 @@ nsComboboxControlFrame::SelectionChanged() if (shouldSetValue) { rv = mDisplayContent->SetText(mTextStr.GetUnicode(), mTextStr.Length(), PR_TRUE); nsFrameState state; - mTextFrame->GetFrameState(&state); - state |= NS_FRAME_IS_DIRTY; - mTextFrame->SetFrameState(state); + //mTextFrame->GetFrameState(&state); + //state |= NS_FRAME_IS_DIRTY; + //mTextFrame->SetFrameState(state); mDisplayFrame->GetFrameState(&state); state |= NS_FRAME_IS_DIRTY; mDisplayFrame->SetFrameState(state); nsCOMPtr shell; rv = mPresContext->GetShell(getter_AddRefs(shell)); ReflowDirtyChild(shell, (nsIFrame*) mDisplayFrame); + + nsCOMPtr presShell; + mPresContext->GetShell(getter_AddRefs(presShell)); + presShell->FlushPendingNotifications(); } } return rv; @@ -2006,6 +2025,9 @@ nsComboboxControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) NS_IMETHODIMP nsComboboxControlFrame::CreateDisplayFrame(nsIPresContext* aPresContext) { + if (kGoodToGo) { + return NS_OK; + } nsCOMPtr shell; aPresContext->GetShell(getter_AddRefs(shell)); @@ -2090,11 +2112,13 @@ nsComboboxControlFrame::CreateAnonymousContent(nsIPresContext* aPresContext, mDisplayContent = do_QueryInterface(labelContent); mDisplayContent->SetText(value.GetUnicode(), value.Length(), PR_TRUE); - nsIDocument* doc; + /*nsIDocument* doc; mContent->GetDocument(doc); labelContent->SetDocument(doc, PR_FALSE); NS_RELEASE(doc); mContent->AppendChildTo(labelContent, PR_FALSE); + */ + aChildList.AppendElement(labelContent); // create button which drops the list down result = NS_NewHTMLInputElement(&mButtonContent, nsHTMLAtoms::input); @@ -2108,6 +2132,82 @@ nsComboboxControlFrame::CreateAnonymousContent(nsIPresContext* aPresContext, return NS_OK; } +NS_IMETHODIMP +nsComboboxControlFrame::CreateFrameFor(nsIPresContext* aPresContext, + nsIContent * aContent, + nsIFrame** aFrame) +{ + NS_PRECONDITION(nsnull != aFrame, "null ptr"); + NS_PRECONDITION(nsnull != aContent, "null ptr"); + NS_PRECONDITION(nsnull != aPresContext, "null ptr"); + + *aFrame = nsnull; + NS_ASSERTION(mDisplayContent != nsnull, "mDisplayContent can't be null!"); + + if (!kGoodToGo) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr content(do_QueryInterface(mDisplayContent)); + if (aContent == content.get()) { + // Get PresShell + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + + // Start by by creating a containing frame + nsresult rv = NS_NewBlockFrame(shell, (nsIFrame**)&mDisplayFrame, NS_BLOCK_SPACE_MGR); + if (NS_FAILED(rv)) { return rv; } + if (!mDisplayFrame) { return NS_ERROR_NULL_POINTER; } + + // create the style context for the anonymous block frame + nsCOMPtr styleContext; + rv = aPresContext->ResolvePseudoStyleContextFor(content, + nsHTMLAtoms::mozDisplayComboboxControlFrame, + mStyleContext, + PR_FALSE, + getter_AddRefs(styleContext)); + if (NS_FAILED(rv)) { return rv; } + if (!styleContext) { return NS_ERROR_NULL_POINTER; } + + // Create a text frame and put it inside the block frame + rv = NS_NewTextFrame(shell, &mTextFrame); + if (NS_FAILED(rv)) { return rv; } + if (!mTextFrame) { return NS_ERROR_NULL_POINTER; } + nsCOMPtr textStyleContext; + rv = aPresContext->ResolvePseudoStyleContextFor(content, + nsHTMLAtoms::mozDisplayComboboxControlFrame,//nsHTMLAtoms::textPseudo, + styleContext, + PR_FALSE, + getter_AddRefs(textStyleContext)); + if (NS_FAILED(rv)) { return rv; } + if (!textStyleContext) { return NS_ERROR_NULL_POINTER; } + + // initialize the text frame + nsCOMPtr content(do_QueryInterface(mDisplayContent)); + mTextFrame->Init(aPresContext, content, mDisplayFrame, textStyleContext, nsnull); + mTextFrame->SetInitialChildList(aPresContext, nsnull, nsnull); + + /*nsCOMPtr frameManager; + rv = shell->GetFrameManager(getter_AddRefs(frameManager)); + if (NS_FAILED(rv)) { return rv; } + if (!frameManager) { return NS_ERROR_NULL_POINTER; } + frameManager->SetPrimaryFrameFor(content, mTextFrame); + */ + + rv = mDisplayFrame->Init(aPresContext, content, this, styleContext, nsnull); + if (NS_FAILED(rv)) { return rv; } + + mDisplayFrame->SetInitialChildList(aPresContext, nsnull, mTextFrame); + *aFrame = mDisplayFrame; + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + + + + NS_IMETHODIMP nsComboboxControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight) { @@ -2137,13 +2237,13 @@ nsComboboxControlFrame::Destroy(nsIPresContext* aPresContext) // Cleanup frames in popup child list mPopupFrames.DestroyFrames(aPresContext); - if (mDisplayFrame) { + /*if (mDisplayFrame) { mFrameConstructor->RemoveMappingsForFrameSubtree(aPresContext, mDisplayFrame, nsnull); mDisplayFrame->Destroy(aPresContext); mDisplayFrame=nsnull; - } + }*/ - if (mDisplayContent) { + /*if (mDisplayContent) { nsCOMPtr content(do_QueryInterface(mDisplayContent)); if (content) { PRInt32 index; @@ -2151,7 +2251,7 @@ nsComboboxControlFrame::Destroy(nsIPresContext* aPresContext) mContent->RemoveChildAt(index, PR_FALSE); } } - } + }*/ return nsAreaFrame::Destroy(aPresContext); } @@ -2181,6 +2281,17 @@ nsComboboxControlFrame::SetInitialChildList(nsIPresContext* aPresContext, } else { rv = nsAreaFrame::SetInitialChildList(aPresContext, aListName, aChildList); InitTextStr(aPresContext, PR_FALSE); + + nsIFrame * child = aChildList; + while (child != nsnull) { + nsIFormControlFrame* fcFrame = nsnull; + nsresult rv = child->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + if (NS_FAILED(rv) && fcFrame == nsnull) { + mDisplayFrame = child; + break; + } + child->GetNextSibling(&child); + } } return rv; } @@ -2282,6 +2393,10 @@ nsComboboxControlFrame::Paint(nsIPresContext* aPresContext, #endif nsAreaFrame::Paint(aPresContext,aRenderingContext,aDirtyRect,aWhichLayer); + if (kGoodToGo) { + return NS_OK; + } + if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { if (mDisplayFrame) { aRenderingContext.PushState(); @@ -2293,12 +2408,38 @@ nsComboboxControlFrame::Paint(nsIPresContext* aPresContext, mDisplayFrame, NS_FRAME_PAINT_LAYER_BACKGROUND); PaintChild(aPresContext, aRenderingContext, aDirtyRect, mDisplayFrame, NS_FRAME_PAINT_LAYER_FOREGROUND); + + ///////////////////// + // draw focus + // XXX This is only temporary + nsCOMPtr stateManager; + nsresult rv = mPresContext->GetEventStateManager(getter_AddRefs(stateManager)); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr content; + rv = stateManager->GetFocusedContent(getter_AddRefs(content)); + if (NS_SUCCEEDED(rv) && content && content.get() == mContent) { + aRenderingContext.SetLineStyle(nsLineStyle_kDotted); + aRenderingContext.SetColor(0); + //aRenderingContext.DrawRect(clipRect); + float p2t; + aPresContext->GetPixelsToTwips(&p2t); + nscoord onePixel = NSIntPixelsToTwips(1, p2t); + clipRect.width -= onePixel; + clipRect.height -= onePixel; + aRenderingContext.DrawLine(clipRect.x, clipRect.y, + clipRect.x+clipRect.width, clipRect.y); + aRenderingContext.DrawLine(clipRect.x+clipRect.width, clipRect.y, + clipRect.x+clipRect.width, clipRect.y+clipRect.height); + aRenderingContext.DrawLine(clipRect.x+clipRect.width, clipRect.y+clipRect.height, + clipRect.x, clipRect.y+clipRect.height); + aRenderingContext.DrawLine(clipRect.x, clipRect.y+clipRect.height, + clipRect.x, clipRect.y); + } + } + ///////////////////// aRenderingContext.PopState(clipEmpty); } } - //nsRect rect(0, 0, 50000, 50000); - //aRenderingContext.SetColor(NS_RGB(255, 0, 0)); - //aRenderingContext.FillRect(rect); return NS_OK; } diff --git a/layout/html/forms/src/nsComboboxControlFrame.h b/layout/html/forms/src/nsComboboxControlFrame.h index 7ed74554b699..a2f772dbbf00 100644 --- a/layout/html/forms/src/nsComboboxControlFrame.h +++ b/layout/html/forms/src/nsComboboxControlFrame.h @@ -28,8 +28,8 @@ #endif #ifdef DEBUG_rods -//#define DO_REFLOW_DEBUG -//#define DO_REFLOW_COUNTER +#define DO_REFLOW_DEBUG +#define DO_REFLOW_COUNTER //#define DO_UNCONSTRAINED_CHECK //#define DO_PIXELS //#define DO_NEW_REFLOW @@ -79,6 +79,9 @@ public: // nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aChildList); + NS_IMETHOD CreateFrameFor(nsIPresContext* aPresContext, + nsIContent * aContent, + nsIFrame** aFrame); // nsIFrame NS_IMETHOD Init(nsIPresContext* aPresContext, @@ -174,7 +177,10 @@ public: NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); //nsIRollupListener + // NS_DECL_NSIROLLUPLISTENER NS_IMETHOD Rollup(); + NS_IMETHOD ShouldRollupOnMouseWheelEvent(nsIWidget *aWidget, PRBool *aShouldRollup) + { *aShouldRollup = PR_FALSE; return NS_OK;} NS_IMETHOD SetFrameConstructor(nsCSSFrameConstructor *aConstructor) { mFrameConstructor = aConstructor; return NS_OK;} // not owner - do not addref! diff --git a/layout/html/forms/src/nsFileControlFrame.h b/layout/html/forms/src/nsFileControlFrame.h index fbd1f293aeba..4f7b4ed42a28 100644 --- a/layout/html/forms/src/nsFileControlFrame.h +++ b/layout/html/forms/src/nsFileControlFrame.h @@ -116,6 +116,9 @@ public: // from nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aChildList); + NS_IMETHOD CreateFrameFor(nsIPresContext* aPresContext, + nsIContent * aContent, + nsIFrame** aFrame) { if (aFrame) *aFrame = nsnull; return NS_ERROR_FAILURE; } // mouse events when out browse button is pressed diff --git a/layout/html/forms/src/nsGfxButtonControlFrame.h b/layout/html/forms/src/nsGfxButtonControlFrame.h index 7290ca219f1a..a5063ab07c39 100644 --- a/layout/html/forms/src/nsGfxButtonControlFrame.h +++ b/layout/html/forms/src/nsGfxButtonControlFrame.h @@ -68,6 +68,9 @@ public: // nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aChildList); + NS_IMETHOD CreateFrameFor(nsIPresContext* aPresContext, + nsIContent * aContent, + nsIFrame** aFrame) { if (aFrame) *aFrame = nsnull; return NS_ERROR_FAILURE; } protected: NS_IMETHOD AddComputedBorderPaddingToDesiredSize(nsHTMLReflowMetrics& aDesiredSize, diff --git a/layout/html/forms/src/nsGfxListControlFrame.cpp b/layout/html/forms/src/nsGfxListControlFrame.cpp index 0cad9cac7a3f..226c8ade8df3 100644 --- a/layout/html/forms/src/nsGfxListControlFrame.cpp +++ b/layout/html/forms/src/nsGfxListControlFrame.cpp @@ -58,6 +58,8 @@ #include "nsVoidArray.h" #include "nsISelectElement.h" +#include "nsIScrollableFrame.h" + // included for view scrolling #include "nsIViewManager.h" @@ -236,7 +238,10 @@ nsGfxListControlFrame::nsGfxListControlFrame() mIsCapturingMouseEvents = PR_FALSE; mSelectionCache = new nsVoidArray(); - mSelectionCacheLength = 0; + mSelectionCacheLength = 0; + + mDelayedIndexSetting = kNothingSelected; + mDelayedValueSetting = PR_FALSE; mIsAllContentHere = PR_FALSE; mIsAllFramesHere = PR_FALSE; @@ -353,6 +358,8 @@ nsGfxListControlFrame::Reflow(nsIPresContext* aPresContext, { REFLOW_COUNTER_REQUEST(); + aStatus = NS_FRAME_COMPLETE; + #ifdef DO_REFLOW_DEBUG printf("%p ** Id: %d nsLCF::Reflow %d R: ", this, mReflowId, myCounter++); switch (aReflowState.reason) { @@ -374,6 +381,18 @@ nsGfxListControlFrame::Reflow(nsIPresContext* aPresContext, printSize("CW", aReflowState.mComputedWidth); printSize("CH", aReflowState.mComputedHeight); printf("\n"); +#if 0 + { + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display); + printf("+++++++++++++++++++++++++++++++++ "); + switch (display->mVisible) { + case NS_STYLE_VISIBILITY_COLLAPSE: printf("NS_STYLE_VISIBILITY_COLLAPSE\n");break; + case NS_STYLE_VISIBILITY_HIDDEN: printf("NS_STYLE_VISIBILITY_HIDDEN\n");break; + case NS_STYLE_VISIBILITY_VISIBLE: printf("NS_STYLE_VISIBILITY_VISIBLE\n");break; + } + } +#endif #endif // DEBUG_rodsXXX @@ -436,21 +455,128 @@ nsGfxListControlFrame::Reflow(nsIPresContext* aPresContext, bailOnWidth = PR_FALSE; bailOnHeight = PR_FALSE; #endif + if (mDelayedIndexSetting != kNothingSelected) { + SetOptionSelected(mDelayedIndexSetting, mDelayedValueSetting); + mDelayedIndexSetting = kNothingSelected; + } + + nsIFrame * firstChildFrame = nsnull; + FirstChild(aPresContext, nsnull, &firstChildFrame); + // XXX So this may do it too often // the side effect of this is if the user has scrolled to some other place in the list and // an incremental reflow comes through the list gets scrolled to the first selected item // I haven't been able to make it do it, but it will do it // basically the real solution is to know when all the reframes are there. if (aReflowState.reason == eReflowReason_Incremental) { - nsCOMPtr content = getter_AddRefs(GetOptionContent(mSelectedIndex)); - if (content) { - ScrollToFrame(content); + nsIFrame* targetFrame; + aReflowState.reflowCommand->GetTarget(targetFrame); + if (targetFrame == this) { +#if 0 + nsresult res = nsHTMLContainerFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + nsRect r; + firstChildFrame->GetRect(r); + firstChildFrame->SetRect(aPresContext, r); + + aDesiredSize.width = mCacheSize.width; + aDesiredSize.height = mCacheSize.height; + + if (aDesiredSize.maxElementSize != nsnull) { + aDesiredSize.maxElementSize->width = mCachedMaxElementSize.width; + aDesiredSize.maxElementSize->height = mCachedMaxElementSize.height; + } + aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.descent = 0; + printf("Bottom# DW: %d DH: %d\n", aDesiredSize.width, aDesiredSize.height); + + nsIView * view; + GetView(aPresContext, &view); + + if (view) { + nsIViewManager *vm; + view->GetViewManager(vm); + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display); + + // See if the view should be hidden or visible + PRBool viewIsVisible = PR_TRUE; + if (NS_STYLE_VISIBILITY_COLLAPSE == display->mVisible) { + viewIsVisible = PR_FALSE; + } else if (NS_STYLE_VISIBILITY_HIDDEN == display->mVisible) { + // If it has a widget, hide the view because the widget can't deal with it + nsIWidget* widget = nsnull; + view->GetWidget(widget); + if (widget) { + viewIsVisible = PR_FALSE; + NS_RELEASE(widget); + } else { + } + viewIsVisible = PR_TRUE; + } + + // Make sure visibility is correct + vm->SetViewVisibility(view, viewIsVisible ? nsViewVisibility_kShow : + nsViewVisibility_kHide); + + NS_RELEASE(vm); + } + return NS_OK; +#else + nsCOMPtr content = getter_AddRefs(GetOptionContent(mSelectedIndex)); + if (content) { + ScrollToFrame(content); + } +#endif + } else if (targetFrame == firstChildFrame) { + nsRect rect; + firstChildFrame->GetRect(rect); + const nsStyleSpacing* scrollSpacing; + firstChildFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)scrollSpacing); + nsMargin scrollBorderPadding; + scrollBorderPadding.SizeTo(0, 0, 0, 0); + scrollSpacing->CalcBorderPaddingFor(firstChildFrame, scrollBorderPadding); + rect.width -= (scrollBorderPadding.left + scrollBorderPadding.right); + rect.height -= (scrollBorderPadding.top + scrollBorderPadding.bottom)*2; + printf("Inc Pass CW: %d CH: %d\n", rect.width, rect.height); + nsHTMLReflowState childReflowState(aPresContext, aReflowState, + firstChildFrame, + nsSize(rect.width, rect.height)); + childReflowState.mComputedWidth = rect.width; + childReflowState.mComputedHeight = rect.height; + firstChildFrame->WillReflow(aPresContext); + firstChildFrame->MoveTo(aPresContext, aReflowState.mComputedBorderPadding.left, aReflowState.mComputedBorderPadding.top); + nsIView* view; + firstChildFrame->GetView(aPresContext, &view); + NS_ASSERTION(view == nsnull, "Hmmmm, fix this!"); + if (view) { + //nsAreaFrame::PositionFrameView(aPresContext, aDisplayFrame, view); + } +#if 1 // this causes infinite reflows + firstChildFrame->Reflow(aPresContext, + aDesiredSize, + childReflowState, + aStatus); +#endif + printf("AfterInc DW: %d CH: %d\n", aDesiredSize.width, aDesiredSize.height); + aDesiredSize.width = mCacheSize.width; + aDesiredSize.height = mCacheSize.height; + + if (aDesiredSize.maxElementSize != nsnull) { + aDesiredSize.maxElementSize->width = mCachedMaxElementSize.width; + aDesiredSize.maxElementSize->height = mCachedMaxElementSize.height; + } + aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.descent = 0; + printf("Bottom* DW: %d DH: %d\n", aDesiredSize.width, aDesiredSize.height); + return NS_OK; + } else { + nsCOMPtr content = getter_AddRefs(GetOptionContent(mSelectedIndex)); + if (content) { + ScrollToFrame(content); + } } } - nsIFrame * firstChildFrame = nsnull; - FirstChild(aPresContext, nsnull, &firstChildFrame); - // Strategy: Let the inherited reflow happen as though the width and height of the // ScrollFrame are big enough to allow the listbox to // shrink to fit the longest option element line in the list. @@ -507,47 +633,25 @@ nsGfxListControlFrame::Reflow(nsIPresContext* aPresContext, nsSize scrolledAreaSize(0,0); nsHTMLReflowMetrics scrolledAreaDesiredSize(&scrolledAreaSize); + printf("1st Pass CW: %d CH: %d\n", childReflowState.mComputedWidth, childReflowState.mComputedHeight); firstChildFrame->Reflow(aPresContext, scrolledAreaDesiredSize, childReflowState, aStatus); -#if 0 - /*if (childReflowState.mComputedHeight == NS_INTRINSICSIZE) { - PRInt32 numRows = 1; - GetSizeAttribute(&numRows); - printf("Num Row : %d\n", numRows); + printf("After1st DW: %d DH: %d\n", scrolledAreaDesiredSize.width, scrolledAreaDesiredSize.height); - if (numRows == kNoSizeSpecified) { - nsIDOMNode* node; - nsresult rv = mContent->QueryInterface(nsCOMTypeInfo::GetIID(),(void**) &node); - if (node && NS_SUCCEEDED(rv)) { - numRows = 0; - NS_RELEASE(node); - } - } - - if (numRows > 1) { - PRInt32 heightOfARow = scrolledAreaDesiredSize.maxElementSize->height; - nscoord visibleHeight; - - if (isInDropDownMode) { - visibleHeight = childReflowState.mComputedHeight; - - if (visibleHeight > (kMaxDropDownRows * heightOfARow)) { - visibleHeight = (kMaxDropDownRows * heightOfARow); - } - } else { - visibleHeight = numRows * heightOfARow; - } - - printf("Row height: %d\n", heightOfARow); - - nsHTMLReflowState secondPassState(aPresContext, aReflowState, firstChildFrame, nsSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE)); - secondPassState.mComputedHeight = visibleHeight; - secondPassState.mComputedWidth = childReflowState.mComputedWidth; - */ -#else - // The nsScrollFrame::REflow adds in the scrollbar width and border dimensions + nsIScrollableFrame * scrollableFrame = nsnull; + nsRect scrolledRect; + if (NS_SUCCEEDED(firstChildFrame->QueryInterface(NS_GET_IID(nsIScrollableFrame), (void**)&scrollableFrame))) { + nsIFrame * scrolledFrame; + scrollableFrame->GetScrolledFrame(aPresContext, scrolledFrame); + NS_ASSERTION(scrolledFrame != nsnull, "Must have scrollable frame"); + scrolledFrame->GetRect(scrolledRect); + } else { + NS_ASSERTION(scrollableFrame != nsnull, "Must have scrollableFrame frame"); + } + + // The nsScrollFrame::REflow adds in the scrollbar width and border dimensions // to the maxElementSize, so these need to be subtracted nscoord scrolledAreaWidth = scrolledAreaDesiredSize.maxElementSize->width; nscoord scrolledAreaHeight = scrolledAreaDesiredSize.height; @@ -567,6 +671,7 @@ nsGfxListControlFrame::Reflow(nsIPresContext* aPresContext, dc->GetScrollBarDimensions(sbWidth, sbHeight); // Convert to nscoord's by rounding nscoord scrollbarWidth = NSToCoordRound(sbWidth); + //nscoord scrollbarHeight = NSToCoordRound(sbHeight); // Subtract out the borders @@ -602,19 +707,17 @@ nsGfxListControlFrame::Reflow(nsIPresContext* aPresContext, if (isInDropDownMode) { if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { visibleWidth = scrolledAreaWidth; - } else { - visibleWidth = aReflowState.mComputedWidth; - visibleWidth -= (scrollBorderPadding.left + scrollBorderPadding.right); - //scrolledAreaHeight -= (border.top + border.bottom + padding.top + padding.bottom); - } - } else { - if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { - visibleWidth = scrolledAreaWidth;// + 15*15; visibleWidth += scrollbarWidth; } else { visibleWidth = aReflowState.mComputedWidth; - // XXX rods - this hould not be subtracted in - //visibleWidth -= (border.left + border.right + padding.left + padding.right); + visibleWidth -= (scrollBorderPadding.left + scrollBorderPadding.right); + } + } else { + if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { + visibleWidth = scrolledAreaWidth; + //visibleWidth += scrollbarWidth; + } else { + visibleWidth = aReflowState.mComputedWidth; } } @@ -775,13 +878,29 @@ nsGfxListControlFrame::Reflow(nsIPresContext* aPresContext, secondPassState.mComputedHeight = visibleHeight; secondPassState.reason = eReflowReason_Resize; -#endif + + printf("2nd Pass CW: %d CH: %d\n", visibleWidth, visibleHeight); + mCachedScrollFrameSize.width = visibleWidth; + mCachedScrollFrameSize.height = visibleHeight; + // Reflow + firstChildFrame->WillReflow(aPresContext); + firstChildFrame->MoveTo(aPresContext, aReflowState.mComputedBorderPadding.left, aReflowState.mComputedBorderPadding.top); + nsIView* view; + firstChildFrame->GetView(aPresContext, &view); + NS_ASSERTION(view == nsnull, "Hmmmm, fix this!"); + if (view) { + nsContainerFrame::PositionFrameView(aPresContext, firstChildFrame, view); + } firstChildFrame->Reflow(aPresContext, scrolledAreaDesiredSize, secondPassState, aStatus); - //} - //} + nsRect rr; + firstChildFrame->GetRect(rr); + + printf("After2nd DW: %d DH: %d\n", scrolledAreaDesiredSize.width, scrolledAreaDesiredSize.height); + //mCachedScrollFrameSize.width = scrolledAreaDesiredSize.width; + //mCachedScrollFrameSize.height = scrolledAreaDesiredSize.height; nsMargin b = aReflowState.mComputedBorderPadding - aReflowState.mComputedPadding; @@ -818,9 +937,8 @@ nsGfxListControlFrame::Reflow(nsIPresContext* aPresContext, aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; - aStatus = NS_FRAME_COMPLETE; -#ifdef DEBUG_rods +#ifdef DEBUG_rodsX if (!isInDropDownMode) { PRInt32 numRows = 1; GetSizeAttribute(&numRows); @@ -836,417 +954,15 @@ nsGfxListControlFrame::Reflow(nsIPresContext* aPresContext, } } #endif - - nsFormControlFrame::SetupCachedSizes(mCacheSize, mCachedMaxElementSize, aDesiredSize); - - return NS_OK; -} - -#if 0 -//----------------------------------------------------------------- -// Main Reflow for ListBox/Dropdown -//----------------------------------------------------------------- -NS_IMETHODIMP -nsGfxListControlFrame::Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) -{ - REFLOW_COUNTER_REQUEST(); - -#ifdef DO_REFLOW_DEBUG - printf("%p ** Id: %d nsLCF::Reflow %d R: ", this, mReflowId, myCounter++); - switch (aReflowState.reason) { - case eReflowReason_Initial: - printf("Initia");break; - case eReflowReason_Incremental: - printf("Increm");break; - case eReflowReason_Resize: - printf("Resize");break; - case eReflowReason_StyleChange: - printf("StyleC");break; - case eReflowReason_Dirty: - printf("Dirty ");break; - default:printf("%d", aReflowState.reason);break; - } - - printSize("AW", aReflowState.availableWidth); - printSize("AH", aReflowState.availableHeight); - printSize("CW", aReflowState.mComputedWidth); - printSize("CH", aReflowState.mComputedHeight); - printf("\n"); -#endif // DEBUG_rodsXXX - - PRBool bailOnWidth; - PRBool bailOnHeight; - // This ifdef is for turning off the optimization - // so we can check timings against the old version -#if 0 - - nsFormControlFrame::SkipResizeReflow(mCacheSize, - mCachedMaxElementSize, - mCachedAvailableSize, - aDesiredSize, aReflowState, - aStatus, - bailOnWidth, bailOnHeight); - - // Here we bail if both the height and the width haven't changed - // also we see if we should override the optimization - // - // The optimization can get overridden by the combobox - // sometime the combobox knows that the list MUST do a full reflow - // no matter what - if (!mOverrideReflowOpt && bailOnWidth && bailOnHeight) { - REFLOW_DEBUG_MSG3("*** Done nsLCF - Bailing on DW: %d DH: %d ", PX(aDesiredSize.width), PX(aDesiredSize.height)); - REFLOW_DEBUG_MSG3("bailOnWidth %d bailOnHeight %d\n", PX(bailOnWidth), PX(bailOnHeight)); - return NS_OK; - } else if (mOverrideReflowOpt) { - mOverrideReflowOpt = PR_FALSE; - } - -#else - bailOnWidth = PR_FALSE; - bailOnHeight = PR_FALSE; -#endif - -#ifdef DEBUG_rodsXXX - // Lists out all the options - { - nsresult rv = NS_ERROR_FAILURE; - nsCOMPtr options = getter_AddRefs(GetOptions(mContent)); - if (options) { - PRUint32 numOptions; - options->GetLength(&numOptions); - printf("--- Num of Items %d ---\n", numOptions); - for (PRUint32 i=0;i optionElement = getter_AddRefs(GetOption(*options, i)); - if (optionElement) { - nsAutoString text; - rv = optionElement->GetLabel(text); - if (NS_CONTENT_ATTR_HAS_VALUE != rv || 0 == text.Length()) { - if (NS_OK != optionElement->GetText(text)) { - text = "No Value"; - } - } else { - text = "No Value"; - } - printf("[%d] - %s\n", i, text.ToNewCString()); - } - } - } - } -#endif // DEBUG_rodsXXX - - - // If all the content and frames are here - // then initialize it before reflow - if (mIsAllContentHere && !mHasBeenInitialized) { - if (PR_FALSE == mIsAllFramesHere) { - CheckIfAllFramesHere(); - } - if (mIsAllFramesHere && !mHasBeenInitialized) { - mHasBeenInitialized = PR_TRUE; - Reset(aPresContext); - } - } - - - if (eReflowReason_Incremental == aReflowState.reason) { - nsIFrame* targetFrame; - aReflowState.reflowCommand->GetTarget(targetFrame); - if (targetFrame == this) { - // XXX So this may do it too often - // the side effect of this is if the user has scrolled to some other place in the list and - // an incremental reflow comes through the list gets scrolled to the first selected item - // I haven't been able to make it do it, but it will do it - // basically the real solution is to know when all the reframes are there. - nsCOMPtr content = getter_AddRefs(GetOptionContent(mSelectedIndex)); - if (content) { - ScrollToFrame(content); - } - } - } - - // Strategy: Let the inherited reflow happen as though the width and height of the - // ScrollFrame are big enough to allow the listbox to - // shrink to fit the longest option element line in the list. - // The desired width and height returned by the inherited reflow is returned, - // unless one of the following has been specified. - // 1. A css width has been specified. - // 2. The size has been specified. - // 3. The css height has been specified, but the number of rows has not. - // The size attribute overrides the height setting but the height setting - // should be honored if there isn't a size specified. - - // Determine the desired width + height for the listbox + - aDesiredSize.width = 0; - aDesiredSize.height = 0; - - // Add the list frame as a child of the form - if (eReflowReason_Initial == aReflowState.reason) { - if (mPresState) { - RestoreState(aPresContext, mPresState); - mPresState = do_QueryInterface(nsnull); - } - if (IsInDropDownMode() == PR_FALSE && !mFormFrame) { - nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); - nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); - } - } - - //--Calculate a width just big enough for the scrollframe to shrink around the - //longest element in the list - nsHTMLReflowState secondPassState(aReflowState); - nsHTMLReflowState firstPassState(aReflowState); - - //nsHTMLReflowState firstPassState(aPresContext, nsnull, - // this, aDesiredSize); - - // Get the size of option elements inside the listbox - // Compute the width based on the longest line in the listbox. - - firstPassState.mComputedWidth = NS_UNCONSTRAINEDSIZE; - firstPassState.mComputedHeight = NS_UNCONSTRAINEDSIZE; - firstPassState.availableWidth = NS_UNCONSTRAINEDSIZE; - firstPassState.availableHeight = NS_UNCONSTRAINEDSIZE; - - nsSize scrolledAreaSize(0,0); - nsHTMLReflowMetrics scrolledAreaDesiredSize(&scrolledAreaSize); - - - if (eReflowReason_Incremental == aReflowState.reason) { - nsIFrame* targetFrame; - firstPassState.reflowCommand->GetTarget(targetFrame); - if (this == targetFrame) { - nsIReflowCommand::ReflowType type; - aReflowState.reflowCommand->GetType(type); - firstPassState.reason = eReflowReason_StyleChange; - firstPassState.reflowCommand = nsnull; - } - } - - nsresult res = nsScrollFrame::Reflow(aPresContext, - scrolledAreaDesiredSize, - firstPassState, - aStatus); - if (NS_FAILED(res)) { - return res; - } - - // Compute the bounding box of the contents of the list using the area - // calculated by the first reflow as a starting point. - // - // The nsScrollFrame::REflow adds in the scrollbar width and border dimensions - // to the maxElementSize, so these need to be subtracted - nscoord scrolledAreaWidth = scrolledAreaDesiredSize.maxElementSize->width; - nscoord scrolledAreaHeight = scrolledAreaDesiredSize.height; - - // Keep the oringal values - mMaxWidth = scrolledAreaWidth; - mMaxHeight = scrolledAreaDesiredSize.maxElementSize->height; - - // The first reflow produces a box with the scrollbar width and borders - // added in so we need to subtract them out. - - // Retrieve the scrollbar's width and height - float sbWidth = 0.0; - float sbHeight = 0.0;; - nsCOMPtr dc; - aPresContext->GetDeviceContext(getter_AddRefs(dc)); - dc->GetScrollBarDimensions(sbWidth, sbHeight); - // Convert to nscoord's by rounding - nscoord scrollbarWidth = NSToCoordRound(sbWidth); - //nscoord scrollbarHeight = NSToCoordRound(sbHeight); - - // Subtract out the borders - nsMargin border; - if (!aReflowState.mStyleSpacing->GetBorder(border)) { - NS_NOTYETIMPLEMENTED("percentage border"); - border.SizeTo(0, 0, 0, 0); - } - - nsMargin padding; - if (!aReflowState.mStyleSpacing->GetPadding(padding)) { - NS_NOTYETIMPLEMENTED("percentage padding"); - padding.SizeTo(0, 0, 0, 0); - } - - mMaxWidth -= (border.left + border.right + padding.left + padding.right); - mMaxHeight -= (border.top + border.bottom + padding.top + padding.bottom); - - // Now the scrolledAreaWidth and scrolledAreaHeight are exactly - // wide and high enough to enclose their contents - - PRBool isInDropDownMode = IsInDropDownMode(); - - scrolledAreaWidth -= (border.left + border.right + padding.left + padding.right); - scrolledAreaHeight -= (border.top + border.bottom + padding.top + padding.bottom); - - nscoord visibleWidth = 0; - if (isInDropDownMode) { - if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { - visibleWidth = scrolledAreaWidth; - } else { - visibleWidth = aReflowState.mComputedWidth; - visibleWidth -= (border.left + border.right + padding.left + padding.right); - //scrolledAreaHeight -= (border.top + border.bottom + padding.top + padding.bottom); - } - } else { - if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { - visibleWidth = scrolledAreaWidth; - } else { - visibleWidth = aReflowState.mComputedWidth - scrollbarWidth; - // XXX rods - this hould not be subtracted in - //visibleWidth -= (border.left + border.right + padding.left + padding.right); - } - } - - // Determine if a scrollbar will be needed, If so we need to add - // enough the width to allow for the scrollbar. - // The scrollbar will be needed under two conditions: - // (size * heightOfaRow) < scrolledAreaHeight or - // the height set through Style < scrolledAreaHeight. - - // Calculate the height of a single row in the listbox or dropdown list - // Note: It is calculated based on what layout returns for the maxElement - // size, rather than trying to take the scrolledAreaHeight and dividing by the number - // of option elements. The reason is that their may be option groups in addition to - // option elements. Either of which may be visible or invisible. - PRInt32 heightOfARow = scrolledAreaDesiredSize.maxElementSize->height; - heightOfARow -= (border.top + border.bottom + padding.top + padding.bottom); - - // Check to see if we have zero item and - // whether we have no width and height - // The following code measures the width and height - // of a bogus string so the list actually displays - PRInt32 length = 0; - GetNumberOfOptions(&length); - - nscoord visibleHeight = 0; - if (isInDropDownMode) { - // Compute the visible height of the drop-down list - // The dropdown list height is the smaller of it's height setting or the height - // of the smallest box that can drawn around it's contents. - visibleHeight = scrolledAreaHeight; - - if (visibleHeight > (kMaxDropDownRows * heightOfARow)) { - visibleHeight = (kMaxDropDownRows * heightOfARow); - } - - } else { - // Calculate the visible height of the listbox - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { - visibleHeight = aReflowState.mComputedHeight; - visibleHeight -= (border.top + border.bottom + padding.top + padding.bottom); - } else { - PRInt32 numRows = 1; - GetSizeAttribute(&numRows); - // because we are not a drop down - // we will always have 2 or more rows - if (numRows >= 1) { - visibleHeight = numRows * heightOfARow; - } else { - PRBool multipleSelections = PR_FALSE; - GetMultiple(&multipleSelections); - if (multipleSelections) { - visibleHeight = PR_MIN(length, kMaxDropDownRows) * heightOfARow; - } else { - visibleHeight = 2 * heightOfARow; - } - } - } - } - - // There are no items in the list - // but we want to include space for the scrollbars - // So fake like we will need scrollbars also - if (!isInDropDownMode && 0 == length) { - scrolledAreaHeight = visibleHeight+1; - } - - PRBool needsVerticalScrollbar = PR_FALSE; - if (visibleHeight < scrolledAreaHeight) { - needsVerticalScrollbar = PR_TRUE; - } - - if (needsVerticalScrollbar) { - mIsScrollbarVisible = PR_TRUE; // XXX temp code - } else { - mIsScrollbarVisible = PR_FALSE; // XXX temp code - } - - // The visible height is zero, this could be a select with no options - // or a select with a single option that has no content or no label - // - // So this may not be the best solution, but we get the height of the font - // for the list frame and use that as the max/minimum size for the contents - if (visibleHeight == 0) { - nsCOMPtr fontMet; - nsresult res = nsFormControlHelper::GetFrameFontFM(aPresContext, this, getter_AddRefs(fontMet)); - if (NS_SUCCEEDED(res) && fontMet) { - aReflowState.rendContext->SetFont(fontMet); - fontMet->GetHeight(visibleHeight); - mMaxHeight = visibleHeight; - } - } - - if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { - visibleWidth += (border.left + border.right + padding.left + padding.right); - } - - // Do a second reflow with the adjusted width and height settings - // This sets up all of the frames with the correct width and height. - secondPassState.mComputedWidth = visibleWidth; - secondPassState.mComputedHeight = visibleHeight; - secondPassState.reason = eReflowReason_Resize; - - nsScrollFrame::Reflow(aPresContext, aDesiredSize, secondPassState, aStatus); - - // Set the max element size to be the same as the desired element size. - if (nsnull != aDesiredSize.maxElementSize) { - aDesiredSize.maxElementSize->width = aDesiredSize.width; - aDesiredSize.maxElementSize->height = aDesiredSize.height; - } - - aStatus = NS_FRAME_COMPLETE; - -#ifdef DEBUG_rodsXXX if (!isInDropDownMode) { - PRInt32 numRows = 1; - GetSizeAttribute(&numRows); - printf("%d ", numRows); - if (numRows == 2) { - COMPARE_QUIRK_SIZE("nsGfxListControlFrame", 56, 38) - } if (numRows == 3) { - COMPARE_QUIRK_SIZE("nsGfxListControlFrame", 56, 54) - } if (numRows == 4) { - COMPARE_QUIRK_SIZE("nsGfxListControlFrame", 56, 70) - } + COMPARE_QUIRK_SIZE("nsGfxListControlFrame", 56, 86) } -#endif - - - mCachedAvailableSize.width = aDesiredSize.width - (border.left + border.right + padding.left + padding.right); - mCachedAvailableSize.height = aDesiredSize.height - (border.top + border.bottom + padding.top + padding.bottom); - - REFLOW_DEBUG_MSG3("** nsLCF Caching AW: %d AH: %d\n", PX(mCachedAvailableSize.width), PX(mCachedAvailableSize.height)); nsFormControlFrame::SetupCachedSizes(mCacheSize, mCachedMaxElementSize, aDesiredSize); - - REFLOW_DEBUG_MSG3("** Done nsLCF DW: %d DH: %d\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); - - REFLOW_COUNTER(); - -#ifdef DO_REFLOW_COUNTER - if (gReflowControlCnt[mReflowId] > 50) { - REFLOW_DEBUG_MSG3("** Id: %d Cnt: %d ", mReflowId, gReflowControlCnt[mReflowId]); - REFLOW_DEBUG_MSG3("Done nsLCF DW: %d DH: %d\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); - } -#endif - + printf("Bottom DW: %d DH: %d\n", aDesiredSize.width, aDesiredSize.height); return NS_OK; } -#endif + //--------------------------------------------------------- NS_IMETHODIMP @@ -1615,6 +1331,7 @@ nsGfxListControlFrame::HasSameContent(nsIFrame* aFrame1, nsIFrame* aFrame2) NS_IMETHODIMP nsGfxListControlFrame::CaptureMouseEvents(nsIPresContext* aPresContext, PRBool aGrabMouseEvents) { + printf("}}}}}}}}}}}}}}}}}}}} Setting Capture to %s\n", aGrabMouseEvents?"On":"Off"); nsIFrame * firstChildFrame = nsnull; FirstChild(mPresContext, nsnull, &firstChildFrame); @@ -1648,7 +1365,7 @@ nsGfxListControlFrame::CaptureMouseEvents(nsIPresContext* aPresContext, PRBool a nsIWidget * widget; view->GetWidget(widget); if (nsnull != widget) { - printf("}}}}}}}}}}}}}}}}}}}} Caputing is %s\n", aGrabMouseEvents?"On":"Off"); + printf("Capture is set on widget to %s\n", aGrabMouseEvents?"On":"Off"); widget->CaptureMouse(aGrabMouseEvents); NS_RELEASE(widget); } @@ -2073,16 +1790,26 @@ nsGfxListControlFrame::SetContentSelected(PRInt32 aIndex, PRBool aSelected) return; } nsIContent* content = GetOptionContent(aIndex); - //NS_ASSERTION(nsnull != content && aIndex == 0, "Failed to retrieve option content"); - if (nsnull != content) { - if (aSelected) { - DisplaySelected(content); - // Now that it is selected scroll to it - ScrollToFrame(content); - } else { - DisplayDeselected(content); + + nsCOMPtr presShell; + mPresContext->GetShell(getter_AddRefs(presShell)); + nsIFrame * childframe; + nsresult result = presShell->GetPrimaryFrameFor(content, &childframe); + if (NS_SUCCEEDED(result) && childframe != nsnull) { + //NS_ASSERTION(nsnull != content && aIndex == 0, "Failed to retrieve option content"); + if (nsnull != content) { + if (aSelected) { + DisplaySelected(content); + // Now that it is selected scroll to it + ScrollToFrame(content); + } else { + DisplayDeselected(content); + } + NS_RELEASE(content); } - NS_RELEASE(content); + } else { + mDelayedIndexSetting = aIndex; + mDelayedValueSetting = aSelected; } } @@ -3227,7 +2954,7 @@ nsGfxListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent) mComboboxFrame->ListWasSelected(mPresContext); } } - } else { + } else if (mButtonDown) { mButtonDown = PR_FALSE; CaptureMouseEvents(mPresContext, PR_FALSE); UpdateSelection(PR_TRUE, PR_FALSE, mContent); @@ -3588,8 +3315,6 @@ nsGfxListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent) return NS_OK; } -#include "nsIScrollableFrame.h" - nsresult nsGfxListControlFrame::ScrollToFrame(nsIContent* aOptElement) { diff --git a/layout/html/forms/src/nsGfxListControlFrame.h b/layout/html/forms/src/nsGfxListControlFrame.h index 07f04a539bac..7b76718ee410 100644 --- a/layout/html/forms/src/nsGfxListControlFrame.h +++ b/layout/html/forms/src/nsGfxListControlFrame.h @@ -31,7 +31,7 @@ #define DO_REFLOW_COUNTER //#define DO_UNCONSTRAINED_CHECK //#define DO_PIXELS -//#define DO_DRAGGING +#define DO_DRAGGING #endif #include "nsHTMLContainerFrame.h" @@ -371,6 +371,9 @@ protected: PRBool mOverrideReflowOpt; + PRInt32 mDelayedIndexSetting; + PRBool mDelayedValueSetting; + nsIPresContext* mPresContext; // XXX: Remove the need to cache the pres context. nsCOMPtr mPresState; // Need cache state when list is null @@ -387,6 +390,8 @@ protected: nsSize mCachedUnconstrainedSize; nsSize mCachedAvailableSize; + nsSize mCachedScrollFrameSize; + // timer for autoscrolling. #ifdef DO_DRAGGING nsSelectAutoScrollTimer *mAutoScrollTimer; diff --git a/layout/html/forms/src/nsListControlFrame.cpp b/layout/html/forms/src/nsListControlFrame.cpp index 785e4b447af4..14b4f521020e 100644 --- a/layout/html/forms/src/nsListControlFrame.cpp +++ b/layout/html/forms/src/nsListControlFrame.cpp @@ -56,6 +56,7 @@ #include "nsLayoutAtoms.h" #include "nsIFontMetrics.h" #include "nsVoidArray.h" +#include "nsIScrollableFrame.h" #include "nsISelectElement.h" @@ -225,6 +226,8 @@ nsListControlFrame::nsListControlFrame() mEndExtendedIndex = kNothingSelected; mStartExtendedIndex = kNothingSelected; mIsCapturingMouseEvents = PR_FALSE; + mDelayedIndexSetting = kNothingSelected; + mDelayedValueSetting = PR_FALSE; mSelectionCache = new nsVoidArray(); mSelectionCacheLength = 0; @@ -367,6 +370,18 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, printSize("CW", aReflowState.mComputedWidth); printSize("CH", aReflowState.mComputedHeight); printf("\n"); +#if 0 + { + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display); + printf("+++++++++++++++++++++++++++++++++ "); + switch (display->mVisible) { + case NS_STYLE_VISIBILITY_COLLAPSE: printf("NS_STYLE_VISIBILITY_COLLAPSE\n");break; + case NS_STYLE_VISIBILITY_HIDDEN: printf("NS_STYLE_VISIBILITY_HIDDEN\n");break; + case NS_STYLE_VISIBILITY_VISIBLE: printf("NS_STYLE_VISIBILITY_VISIBLE\n");break; + } + } +#endif #endif // DEBUG_rodsXXX PRBool bailOnWidth; @@ -430,6 +445,11 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, #endif // DEBUG_rodsXXX + if (mDelayedIndexSetting != kNothingSelected) { + SetOptionSelected(mDelayedIndexSetting, mDelayedValueSetting); + mDelayedIndexSetting = kNothingSelected; + } + // If all the content and frames are here // then initialize it before reflow if (mIsAllContentHere && !mHasBeenInitialized) { @@ -537,6 +557,16 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, return res; } + nsIScrollableFrame * scrollableFrame = nsnull; + nsRect scrolledRect; + if (NS_SUCCEEDED(QueryInterface(NS_GET_IID(nsIScrollableFrame), (void**)&scrollableFrame))) { + nsIFrame * scrolledFrame; + scrollableFrame->GetScrolledFrame(aPresContext, scrolledFrame); + NS_ASSERTION(scrolledFrame != nsnull, "Must have scrollable frame"); + scrolledFrame->GetRect(scrolledRect); + } else { + NS_ASSERTION(scrollableFrame != nsnull, "Must have scrollableFrame frame"); + } // Compute the bounding box of the contents of the list using the area // calculated by the first reflow as a starting point. // @@ -1614,17 +1644,28 @@ nsListControlFrame::SetContentSelected(PRInt32 aIndex, PRBool aSelected) return; } nsIContent* content = GetOptionContent(aIndex); - //NS_ASSERTION(nsnull != content && aIndex == 0, "Failed to retrieve option content"); - if (nsnull != content) { - if (aSelected) { - DisplaySelected(content); - // Now that it is selected scroll to it - ScrollToFrame(content); - } else { - DisplayDeselected(content); + + nsCOMPtr presShell; + mPresContext->GetShell(getter_AddRefs(presShell)); + nsIFrame * childframe; + nsresult result = presShell->GetPrimaryFrameFor(content, &childframe); + if (NS_SUCCEEDED(result) && childframe != nsnull) { + //NS_ASSERTION(nsnull != content && aIndex == 0, "Failed to retrieve option content"); + if (nsnull != content) { + if (aSelected) { + DisplaySelected(content); + // Now that it is selected scroll to it + ScrollToFrame(content); + } else { + DisplayDeselected(content); + } + NS_RELEASE(content); } - NS_RELEASE(content); + } else { + mDelayedIndexSetting = aIndex; + mDelayedValueSetting = aSelected; } + } //--------------------------------------------------------- diff --git a/layout/html/forms/src/nsListControlFrame.h b/layout/html/forms/src/nsListControlFrame.h index 90679599cf08..85990a820b88 100644 --- a/layout/html/forms/src/nsListControlFrame.h +++ b/layout/html/forms/src/nsListControlFrame.h @@ -265,6 +265,9 @@ protected: PRBool mOverrideReflowOpt; + PRInt32 mDelayedIndexSetting; + PRBool mDelayedValueSetting; + nsIPresContext* mPresContext; // XXX: Remove the need to cache the pres context. nsCOMPtr mPresState; // Need cache state when list is null diff --git a/layout/html/style/src/nsCSSFrameConstructor.cpp b/layout/html/style/src/nsCSSFrameConstructor.cpp index 6dd7ba2731bf..664380b7a8ae 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -4569,15 +4569,16 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsIPresShell* aPresShell, const nsStyleDisplay* styleDisplay; newFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) styleDisplay); - nsIFrame * blkFrame; - NS_NewBlockFrame(shell, &blkFrame, flags); + nsIFrame * areaFrame; + //NS_NewBlockFrame(shell, &areaFrame, flags); + NS_NewAreaFrame(shell, &areaFrame, flags | NS_BLOCK_SHRINK_WRAP);// | NS_BLOCK_MARGIN_ROOT); // Resolve style and initialize the frame nsIStyleContext* styleContext; aPresContext->ResolvePseudoStyleContextFor(aContent, nsHTMLAtoms::fieldsetContentPseudo, aStyleContext, PR_FALSE, &styleContext); InitAndRestoreFrame(aPresContext, aState, aContent, - newFrame, styleContext, nsnull, blkFrame); + newFrame, styleContext, nsnull, areaFrame); NS_RELEASE(styleContext); @@ -4587,7 +4588,7 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsIPresShell* aPresShell, HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, &haveFirstLetterStyle, &haveFirstLineStyle); nsFrameConstructorSaveState floaterSaveState; - aState.PushFloaterContainingBlock(blkFrame, floaterSaveState, + aState.PushFloaterContainingBlock(areaFrame, floaterSaveState, haveFirstLetterStyle, haveFirstLineStyle); @@ -4600,10 +4601,10 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsIPresShell* aPresShell, if (isPositionedContainingBlock) { // The area frame becomes a container for child frames that are // absolutely positioned - aState.PushAbsoluteContainingBlock(blkFrame, absoluteSaveState); + aState.PushAbsoluteContainingBlock(areaFrame, absoluteSaveState); } - ProcessChildren(aPresShell, aPresContext, aState, aContent, blkFrame, PR_FALSE, + ProcessChildren(aPresShell, aPresContext, aState, aContent, areaFrame, PR_FALSE, childItems, PR_TRUE); static NS_DEFINE_IID(kLegendFrameCID, NS_LEGEND_FRAME_CID); @@ -4617,7 +4618,7 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsIPresShell* aPresShell, nsIFrame * nxt; legendFrame->GetNextSibling(&nxt); previous->SetNextSibling(nxt); - blkFrame->SetNextSibling(legendFrame); + areaFrame->SetNextSibling(legendFrame); legendFrame->SetParent(newFrame); legendFrame->SetNextSibling(nsnull); break; @@ -4625,7 +4626,7 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsIPresShell* aPresShell, nsIFrame * nxt; legendFrame->GetNextSibling(&nxt); childItems.childList = nxt; - blkFrame->SetNextSibling(legendFrame); + areaFrame->SetNextSibling(legendFrame); legendFrame->SetParent(newFrame); legendFrame->SetNextSibling(nsnull); break; @@ -4636,21 +4637,21 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsIPresShell* aPresShell, } // Set the scrolled frame's initial child lists - blkFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); + areaFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); if (isPositionedContainingBlock && aState.mAbsoluteItems.childList) { - blkFrame->SetInitialChildList(aPresContext, + areaFrame->SetInitialChildList(aPresContext, nsLayoutAtoms::absoluteList, aState.mAbsoluteItems.childList); } if (aState.mFloatedItems.childList) { - blkFrame->SetInitialChildList(aPresContext, + areaFrame->SetInitialChildList(aPresContext, nsLayoutAtoms::floaterList, aState.mFloatedItems.childList); } // Set the scroll frame's initial child list - newFrame->SetInitialChildList(aPresContext, nsnull, blkFrame); + newFrame->SetInitialChildList(aPresContext, nsnull, areaFrame); // our new frame retured is the top frame which is the list frame. aNewFrame = newFrame; @@ -5152,11 +5153,11 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell, nsFrameConstructorState& aState, nsIContent* aParent, nsIDocument* aDocument, - nsIFrame* aNewFrame, + nsIFrame* aParentFrame, nsFrameItems& aChildItems) { - nsCOMPtr creator(do_QueryInterface(aNewFrame)); + nsCOMPtr creator(do_QueryInterface(aParentFrame)); if (!creator) return NS_OK; @@ -5180,8 +5181,14 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell, content->SetParent(aParent); content->SetDocument(aDocument, PR_TRUE); - // create the frame and attach it to our frame - ConstructFrame(aPresShell, aPresContext, aState, content, aNewFrame, aChildItems); + nsIFrame * newFrame = nsnull; + nsresult rv = creator->CreateFrameFor(aPresContext, content, &newFrame); + if (NS_SUCCEEDED(rv) && newFrame != nsnull) { + aChildItems.AddChild(newFrame); + } else { + // create the frame and attach it to our frame + ConstructFrame(aPresShell, aPresContext, aState, content, aParentFrame, aChildItems); + } } return NS_OK; diff --git a/layout/xul/base/src/nsSplitterFrame.h b/layout/xul/base/src/nsSplitterFrame.h index 3b9f4500cf5b..2bafd4756762 100644 --- a/layout/xul/base/src/nsSplitterFrame.h +++ b/layout/xul/base/src/nsSplitterFrame.h @@ -71,6 +71,10 @@ public: // nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aAnonymousItems); + NS_IMETHOD CreateFrameFor(nsIPresContext* aPresContext, + nsIContent * aContent, + nsIFrame** aFrame) { if (aFrame) *aFrame = nsnull; return NS_ERROR_FAILURE; } + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); NS_IMETHOD_(nsrefcnt) AddRef(void) { return NS_OK; } NS_IMETHOD_(nsrefcnt) Release(void) { return NS_OK; }