diff --git a/mozilla/layout/forms/nsComboboxControlFrame.cpp b/mozilla/layout/forms/nsComboboxControlFrame.cpp index b56db0d06ce..56dedbe5143 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.cpp +++ b/mozilla/layout/forms/nsComboboxControlFrame.cpp @@ -22,7 +22,6 @@ */ #include "nsCOMPtr.h" #include "nsComboboxControlFrame.h" -#include "nsIFrameManager.h" #include "nsFormFrame.h" #include "nsFormControlFrame.h" #include "nsIHTMLContent.h" @@ -33,11 +32,11 @@ #include "nsINameSpaceManager.h" #include "nsLayoutAtoms.h" #include "nsIDOMElement.h" +#include "nsListControlFrame.h" #include "nsIListControlFrame.h" #include "nsIDOMHTMLCollection.h" #include "nsIDOMHTMLSelectElement.h" #include "nsIDOMHTMLOptionElement.h" -#include "nsIDOMNSHTMLOptionCollection.h" #include "nsIPresShell.h" #include "nsIPresState.h" #include "nsISupportsArray.h" @@ -52,16 +51,6 @@ #include "nsISelectControlFrame.h" #include "nsISupportsPrimitives.h" #include "nsIComponentManager.h" -#include "nsIDOMMouseListener.h" -#include "nsITextContent.h" -#include "nsTextFragment.h" -#include "nsCSSFrameConstructor.h" -#include "nsIDocument.h" - -#ifdef DO_NEW_REFLOW -#include "nsIFontMetrics.h" -#endif - static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); static NS_DEFINE_IID(kIComboboxControlFrameIID, NS_ICOMBOBOXCONTROLFRAME_IID); @@ -73,7 +62,8 @@ static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID); static NS_DEFINE_IID(kIPrivateDOMEventIID, NS_IPRIVATEDOMEVENT_IID); // Drop down list event management. -// The combo box uses the following strategy for managing the drop-down list. +// The combo box uses the following strategy for managing the +// drop-down list. // If the combo box or it's arrow button is clicked on the drop-down list is displayed // If mouse exit's the combo box with the drop-down list displayed the drop-down list // is asked to capture events @@ -88,8 +78,6 @@ static NS_DEFINE_IID(kIPrivateDOMEventIID, NS_IPRIVATEDOMEVENT_IID); const char * kMozDropdownActive = "-moz-dropdown-active"; -const PRInt32 kSizeNotSet = -1; - nsresult NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aStateFlags) { @@ -110,113 +98,6 @@ NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUin return NS_OK; } -//----------------------------------------------------------- -// Reflow Debugging Macros -// These let us "see" how many reflow counts are happening -//----------------------------------------------------------- -#ifdef DO_REFLOW_COUNTER - -#define MAX_REFLOW_CNT 1024 -static PRInt32 gTotalReqs = 0;; -static PRInt32 gTotalReflows = 0;; -static PRInt32 gReflowControlCntRQ[MAX_REFLOW_CNT]; -static PRInt32 gReflowControlCnt[MAX_REFLOW_CNT]; -static PRInt32 gReflowInx = -1; - -#define REFLOW_COUNTER() \ - if (mReflowId > -1) \ - gReflowControlCnt[mReflowId]++; - -#define REFLOW_COUNTER_REQUEST() \ - if (mReflowId > -1) \ - gReflowControlCntRQ[mReflowId]++; - -#define REFLOW_COUNTER_DUMP(__desc) \ - if (mReflowId > -1) {\ - gTotalReqs += gReflowControlCntRQ[mReflowId];\ - gTotalReflows += gReflowControlCnt[mReflowId];\ - printf("** Id:%5d %s RF: %d RQ: %d %d/%d %5.2f\n", \ - mReflowId, (__desc), \ - gReflowControlCnt[mReflowId], \ - gReflowControlCntRQ[mReflowId],\ - gTotalReflows, gTotalReqs, float(gTotalReflows)/float(gTotalReqs)*100.0f);\ - } - -#define REFLOW_COUNTER_INIT() \ - if (gReflowInx < MAX_REFLOW_CNT) { \ - gReflowInx++; \ - mReflowId = gReflowInx; \ - gReflowControlCnt[mReflowId] = 0; \ - gReflowControlCntRQ[mReflowId] = 0; \ - } else { \ - mReflowId = -1; \ - } - -// reflow messages -#define REFLOW_DEBUG_MSG(_msg1) printf((_msg1)) -#define REFLOW_DEBUG_MSG2(_msg1, _msg2) printf((_msg1), (_msg2)) -#define REFLOW_DEBUG_MSG3(_msg1, _msg2, _msg3) printf((_msg1), (_msg2), (_msg3)) -#define REFLOW_DEBUG_MSG4(_msg1, _msg2, _msg3, _msg4) printf((_msg1), (_msg2), (_msg3), (_msg4)) - -#else //------------- - -#define REFLOW_COUNTER_REQUEST() -#define REFLOW_COUNTER() -#define REFLOW_COUNTER_DUMP(__desc) -#define REFLOW_COUNTER_INIT() - -#define REFLOW_DEBUG_MSG(_msg) -#define REFLOW_DEBUG_MSG2(_msg1, _msg2) -#define REFLOW_DEBUG_MSG3(_msg1, _msg2, _msg3) -#define REFLOW_DEBUG_MSG4(_msg1, _msg2, _msg3, _msg4) - - -#endif - -//------------------------------------------ -// This is for being VERY noisy -//------------------------------------------ -#ifdef DO_VERY_NOISY -#define REFLOW_NOISY_MSG(_msg1) printf((_msg1)) -#define REFLOW_NOISY_MSG2(_msg1, _msg2) printf((_msg1), (_msg2)) -#define REFLOW_NOISY_MSG3(_msg1, _msg2, _msg3) printf((_msg1), (_msg2), (_msg3)) -#define REFLOW_NOISY_MSG4(_msg1, _msg2, _msg3, _msg4) printf((_msg1), (_msg2), (_msg3), (_msg4)) -#else -#define REFLOW_NOISY_MSG(_msg) -#define REFLOW_NOISY_MSG2(_msg1, _msg2) -#define REFLOW_NOISY_MSG3(_msg1, _msg2, _msg3) -#define REFLOW_NOISY_MSG4(_msg1, _msg2, _msg3, _msg4) -#endif - -//------------------------------------------ -// Displays value in pixels or twips -//------------------------------------------ -#ifdef DO_PIXELS -#define PX(__v) __v / 15 -#else -#define PX(__v) __v -#endif - -//------------------------------------------ -// Asserts if we return a desired size that -// doesn't correctly match the mComputedWidth -//------------------------------------------ -#ifdef DO_UNCONSTRAINED_CHECK -#define UNCONSTRAINED_CHECK() \ -if (aReflowState.mComputedWidth != NS_UNCONSTRAINEDSIZE) { \ - nscoord width = aDesiredSize.width - borderPadding.left - borderPadding.right; \ - if (width != aReflowState.mComputedWidth) { \ - printf("aDesiredSize.width %d %d != aReflowState.mComputedWidth %d\n", aDesiredSize.width, width, aReflowState.mComputedWidth); \ - } \ - NS_ASSERTION(width == aReflowState.mComputedWidth, "Returning bad value when constrained!"); \ -} -#else -#define UNCONSTRAINED_CHECK() -#endif -//------------------------------------------------------ -//-- Done with macros -//------------------------------------------------------ - nsComboboxControlFrame::nsComboboxControlFrame() : nsAreaFrame() { @@ -224,6 +105,7 @@ nsComboboxControlFrame::nsComboboxControlFrame() mFormFrame = nsnull; mListControlFrame = nsnull; mTextStr = ""; + mDisplayContent = nsnull; mButtonContent = nsnull; mDroppedDown = PR_FALSE; mDisplayFrame = nsnull; @@ -232,33 +114,23 @@ nsComboboxControlFrame::nsComboboxControlFrame() mIgnoreFocus = PR_FALSE; mSelectedIndex = -1; - mCacheSize.width = kSizeNotSet; - mCacheSize.height = kSizeNotSet; - mCachedMaxElementSize.width = kSizeNotSet; - mCachedMaxElementSize.height = kSizeNotSet; - mCachedAvailableSize.width = kSizeNotSet; - mCachedAvailableSize.height = kSizeNotSet; - mCachedUncDropdownSize.width = kSizeNotSet; - mCachedUncDropdownSize.height = kSizeNotSet; - mCachedUncComboSize.width = kSizeNotSet; - mCachedUncComboSize.height = kSizeNotSet; - mItemDisplayWidth = 0; + mCacheSize.width = -1; + mCacheSize.height = -1; + mCachedMaxElementSize.width = -1; + mCachedMaxElementSize.height = -1; //Shrink the area around it's contents //SetFlags(NS_BLOCK_SHRINK_WRAP); - - REFLOW_COUNTER_INIT() } //-------------------------------------------------------------- nsComboboxControlFrame::~nsComboboxControlFrame() { - REFLOW_COUNTER_DUMP("nsCCF"); - if (mFormFrame) { mFormFrame->RemoveFormControlFrame(*this); mFormFrame = nsnull; } NS_IF_RELEASE(mPresContext); + NS_IF_RELEASE(mDisplayContent); NS_IF_RELEASE(mButtonContent); nsFormControlFrame::RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); @@ -339,9 +211,8 @@ nsComboboxControlFrame::MakeSureSomethingIsSelected(nsIPresContext* aPresContext // Set listbox selection to first item in the list box rv = fcFrame->SetProperty(aPresContext, nsHTMLAtoms::selectedindex, "0"); mSelectedIndex = 0; - } else { - UpdateSelection(PR_FALSE, PR_TRUE, mSelectedIndex); // Needed to reflow when removing last option } + UpdateSelection(PR_FALSE, PR_TRUE, mSelectedIndex); // Needed to reflow when removing last option } // Don't NS_RELEASE fcFrame here as it isn't addRef'd in the QI (???) @@ -360,7 +231,9 @@ nsComboboxControlFrame::InitTextStr(nsIPresContext* aPresContext, PRBool aUpdate mListControlFrame->GetSelectedItem(mTextStr); // Update the display by setting the value attribute - mDisplayContent->SetText(mTextStr.GetUnicode(), mTextStr.Length(), aUpdate); + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, mTextStr, aUpdate); + //nsIFrame* buttonFrame = GetDisplayFrame(aPresContext); + //nsFormControlHelper::ForceDrawFrame(buttonFrame); } //-------------------------------------------------------------- @@ -554,12 +427,12 @@ nsComboboxControlFrame::MouseClicked(nsIPresContext* aPresContext) nsresult nsComboboxControlFrame::ReflowComboChildFrame(nsIFrame* aFrame, - nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nscoord aAvailableWidth, - nscoord aAvailableHeight) + nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus, + nscoord aAvailableWidth, + nscoord aAvailableHeight) { // Constrain the child's width and height to aAvailableWidth and aAvailableHeight nsSize availSize(aAvailableWidth, aAvailableHeight); @@ -617,6 +490,17 @@ nsComboboxControlFrame::GetButtonFrame(nsIPresContext* aPresContext) return mButtonFrame; } +nsIFrame* +nsComboboxControlFrame::GetDisplayFrame(nsIPresContext* aPresContext) +{ + if (mDisplayFrame == nsnull) { + NS_ASSERTION(mDisplayContent != nsnull, "nsComboboxControlFrame mDisplayContent is null"); + GetPrimaryComboFrame(aPresContext, mDisplayContent, &mDisplayFrame); + } + + return mDisplayFrame; +} + nsIFrame* nsComboboxControlFrame::GetDropdownFrame() { @@ -694,10 +578,12 @@ nsComboboxControlFrame::PositionDropdown(nsIPresContext* aPresContext, nsRect currentRect; dropdownFrame->GetRect(currentRect); - dropdownFrame->SetRect(aPresContext, dropdownRect); + //if (currentRect != dropdownRect) { + dropdownFrame->SetRect(aPresContext, dropdownRect); #ifdef DEBUG_rodsXXXXXX - printf("%d Position Dropdown at: %d %d %d %d\n", counter++, dropdownRect.x, dropdownRect.y, dropdownRect.width, dropdownRect.height); + printf("%d Position Dropdown at: %d %d %d %d\n", counter++, dropdownRect.x, dropdownRect.y, dropdownRect.width, dropdownRect.height); #endif + //} return rv; } @@ -781,435 +667,55 @@ nsComboboxControlFrame::GetAbsoluteFramePosition(nsIPresContext* aPresContext, return rv; } -//////////////////////////////////////////////////////////////// -// Experimental Reflow -//////////////////////////////////////////////////////////////// -#if defined(DO_NEW_REFLOW) || defined(DO_REFLOW_COUNTER) -//--------------------------------------------------------- -// Returns the nsIDOMHTMLOptionElement for a given index -// in the select's collection -//--------------------------------------------------------- -static nsIDOMHTMLOptionElement* -GetOption(nsIDOMHTMLCollection& aCollection, PRInt32 aIndex) -{ - nsIDOMNode* node = nsnull; - if (NS_SUCCEEDED(aCollection.Item(aIndex, &node))) { - if (nsnull != node) { - nsIDOMHTMLOptionElement* option = nsnull; - node->QueryInterface(NS_GET_IID(nsIDOMHTMLOptionElement), (void**)&option); - NS_RELEASE(node); - return option; - } - } - return nsnull; -} -//--------------------------------------------------------- -// for a given piece of content it returns nsIDOMHTMLSelectElement object -// or null -//--------------------------------------------------------- -static nsIDOMHTMLSelectElement* -GetSelect(nsIContent * aContent) -{ - nsIDOMHTMLSelectElement* selectElement = nsnull; - nsresult result = aContent->QueryInterface(NS_GET_IID(nsIDOMHTMLSelectElement), - (void**)&selectElement); - if (NS_SUCCEEDED(result) && selectElement) { - return selectElement; - } else { - return nsnull; - } -} -//--------------------------------------------------------- -//--------------------------------------------------------- -// This returns the collection for nsIDOMHTMLSelectElement or -// the nsIContent object is the select is null (AddRefs) -//--------------------------------------------------------- -static nsIDOMHTMLCollection* -GetOptions(nsIContent * aContent, nsIDOMHTMLSelectElement* aSelect = nsnull) -{ - nsIDOMNSHTMLOptionCollection* optCol = nsnull; - nsIDOMHTMLCollection* options = nsnull; - if (!aSelect) { - nsCOMPtr selectElement = getter_AddRefs(GetSelect(aContent)); - if (selectElement) { - selectElement->GetOptions(&optCol); // AddRefs (1) - } - } else { - aSelect->GetOptions(&optCol); // AddRefs (1) - } - if (optCol) { - nsresult res = optCol->QueryInterface(NS_GET_IID(nsIDOMHTMLCollection), (void **)&options); // AddRefs (2) - NS_RELEASE(optCol); // Release (1) - } - return options; -} +//------------------------------------------------------------------------------- +//------------------------------------------------------------------------------- +// Old/Current Way of Doing Reflow +//------------------------------------------------------------------------------- +//------------------------------------------------------------------------------- +#define DO_OLD_REFLOW -#ifdef DO_NEW_REFLOW -NS_IMETHODIMP -nsComboboxControlFrame::ReflowItems(nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - nsHTMLReflowMetrics& aDesiredSize) -{ - //printf("*****************\n"); - const nsStyleFont* dspFont; - mDisplayFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)dspFont); - nsCOMPtr deviceContext; - aPresContext->GetDeviceContext(getter_AddRefs(deviceContext)); - NS_ASSERTION(deviceContext, "Couldn't get the device context"); - nsIFontMetrics * fontMet; - deviceContext->GetMetricsFor(dspFont->mFont, fontMet); +#ifdef DO_OLD_REFLOW - nscoord visibleHeight; - //nsCOMPtr fontMet; - //nsresult res = nsFormControlHelper::GetFrameFontFM(aPresContext, this, getter_AddRefs(fontMet)); - if (fontMet) { - fontMet->GetHeight(visibleHeight); - } - - nsAutoString maxStr; - nscoord maxWidth = 0; - //nsIRenderingContext * rc = aReflowState.rendContext; - 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)) { - nscoord width; - aReflowState.rendContext->GetWidth(text, width); - if (width > maxWidth) { - maxStr = text; - maxWidth = width; - } - //maxWidth = PR_MAX(width, maxWidth); - //printf("[%d] - %d %s \n", i, width, text.ToNewCString()); - } - } - } - } - } - if (maxWidth == 0) { - maxWidth = 11 * 15; - } - char * str = maxStr.ToNewCString(); - printf("id: %d maxWidth %d [%s]\n", mReflowId, maxWidth, str); - delete [] str; - - // get the borderPadding for the display area - const nsStyleSpacing* dspSpacing; - mDisplayFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dspSpacing); - nsMargin dspBorderPadding; - dspBorderPadding.SizeTo(0, 0, 0, 0); - dspSpacing->CalcBorderPaddingFor(mDisplayFrame, dspBorderPadding); - - nscoord frmWidth = maxWidth+dspBorderPadding.left+dspBorderPadding.right+ - aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; - nscoord frmHeight = visibleHeight+dspBorderPadding.top+dspBorderPadding.bottom+ - aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; - -#if 1 - aDesiredSize.width = frmWidth; - aDesiredSize.height = frmHeight; -#else - printf("Size %d,%d %d,%d %d,%d %d,%d\n", - frmWidth, frmHeight, - aDesiredSize.width, aDesiredSize.height, - frmWidth-aDesiredSize.width, frmHeight-aDesiredSize.height, - (frmWidth-aDesiredSize.width)/15, (frmHeight-aDesiredSize.height)/15); -#endif - NS_RELEASE(fontMet); - return NS_OK; -} -#endif - -#endif - -//------------------------------------------------------------------ -// This Method reflow just the contents of the ComboBox -// The contents are a Block frame containing a Text Frame - This is the display area -// and then the GfxButton - The dropdown button -//-------------------------------------------------------------------------- -void -nsComboboxControlFrame::ReflowCombobox(nsIPresContext * aPresContext, - const nsHTMLReflowState& aReflowState, - nsHTMLReflowMetrics& aDesiredSize, - nsReflowStatus& aStatus, - nsIFrame * aDisplayFrame, - nsIFrame * aDropDownBtn, - nscoord& aDisplayWidth, - nscoord aBtnWidth, - const nsMargin& aBorderPadding, - nscoord aFallBackHgt, - PRBool aCheckHeight) -{ - // start out by using the cached height - // XXX later this will change when we better handle constrained height - nscoord dispHeight = mCacheSize.height - aBorderPadding.top - aBorderPadding.bottom; - nscoord dispWidth = aDisplayWidth; - - REFLOW_NOISY_MSG3("+++1 AdjustCombo DW:%d DH:%d ", PX(dispWidth), PX(dispHeight)); - REFLOW_NOISY_MSG3("BW:%d BH:%d ", PX(aBtnWidth), PX(dispHeight)); - REFLOW_NOISY_MSG3("mCacheSize.height:%d - %d\n", PX(mCacheSize.height), PX((aBorderPadding.top + aBorderPadding.bottom))); - - // get the border and padding for the DisplayArea (block frame & textframe) - const nsStyleSpacing* dspSpacing; - aDisplayFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dspSpacing); - nsMargin dspBorderPadding; - dspBorderPadding.SizeTo(0, 0, 0, 0); - dspSpacing->CalcBorderPaddingFor(aDisplayFrame, dspBorderPadding); - - // adjust the height - if (mCacheSize.height == kSizeNotSet) { - if (aFallBackHgt == kSizeNotSet) { - NS_ASSERTION(aFallBackHgt != kSizeNotSet, "Fallback can't be kSizeNotSet when mCacheSize.height == kSizeNotSet"); - } else { - dispHeight = aFallBackHgt; - REFLOW_NOISY_MSG2("+++3 Adding (dspBorderPadding.top + dspBorderPadding.bottom): %d\n", (dspBorderPadding.top + dspBorderPadding.bottom)); - dispHeight += (dspBorderPadding.top + dspBorderPadding.bottom); - } - } - - //////////////////////////////////////////////////////////////////////////// - // XXX - This is really bad, but at the moment I am NOT adding in the left padding - // we need to be able to find out what the left padding is on an option - // and subtract that out before we can add in our padding. - REFLOW_NOISY_MSG2("+++3 Adding: %d\n", dspBorderPadding.right); - dispWidth += dspBorderPadding.left + dspBorderPadding.right; - - REFLOW_NOISY_MSG3("+++2 AdjustCombo DW:%d DH:%d ", PX(dispWidth), PX(dispHeight)); - REFLOW_NOISY_MSG3(" BW:%d BH:%d\n", PX(aBtnWidth), PX(dispHeight)); - - // This sets the button to be a specific size - // so no matter what it reflows at these values - SetChildFrameSize(aDropDownBtn, aBtnWidth, dispHeight); - - // now that we know what the overall display width & height will be - // set up a new reflow state and reflow the area frame at that size - nsSize availSize(dispWidth + aBorderPadding.left + aBorderPadding.right, - dispHeight + aBorderPadding.top + aBorderPadding.bottom); - nsHTMLReflowState kidReflowState(aPresContext, aReflowState, this, availSize); - kidReflowState.mComputedWidth = dispWidth; - kidReflowState.mComputedHeight = dispHeight; - - // do reflow - nsAreaFrame::Reflow(aPresContext, aDesiredSize, kidReflowState, aStatus); - - ///////////////////////////////////////////////////////// - // The DisplayFrame is a Block frame containing a TextFrame - // and it is completely anonymous, so we must manually reflow it - nsSize txtAvailSize(dispWidth - aBtnWidth, dispHeight); - nsHTMLReflowMetrics txtKidSize(&txtAvailSize); - nsHTMLReflowState txtKidReflowState(aPresContext, aReflowState, aDisplayFrame, txtAvailSize); - - aDisplayFrame->WillReflow(aPresContext); - aDisplayFrame->MoveTo(aPresContext, aBorderPadding.left, aBorderPadding.top); - nsIView* view; - aDisplayFrame->GetView(aPresContext, &view); - if (view) { - nsAreaFrame::PositionFrameView(aPresContext, aDisplayFrame, view); - } - nsReflowStatus status; - nsresult rv = aDisplayFrame->Reflow(aPresContext, txtKidSize, txtKidReflowState, status); - - ///////////////////////////////////////////////////////// - // If we are Constrained then the AreaFrame Reflow is the correct size - // if we are unconstrained then - //if (aReflowState.mComputedWidth == NS_UNCONSTRAINEDSIZE) { - // aDesiredSize.width += txtKidSize.width; - //} - - // Apparently, XUL lays out differently than HTML - // (the code above works for HTML and not XUL), - // so instead of using the above calculation - // I just set it to what it should be. - aDesiredSize.width = availSize.width; - //aDesiredSize.height = availSize.height; - - // now we need to adjust layout, because the AreaFrame - // doesn't position things exactly where we want them - nscoord insideWidth = dispWidth; - nscoord insideHeight = aDesiredSize.height - aBorderPadding.top - aBorderPadding.bottom; - - // the gets for the Display "block" frame and for the button - // make adjustments - nsRect buttonRect; - nsRect displayRect; - aDisplayFrame->GetRect(displayRect); - aDropDownBtn->GetRect(buttonRect); - // 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.height = insideHeight; - displayRect.width = dispWidth - aBtnWidth; - aDisplayFrame->SetRect(aPresContext, displayRect); - x += displayRect.width; - - // right justify the button - buttonRect.x = x; - buttonRect.y = aBorderPadding.top; - buttonRect.height = insideHeight; - buttonRect.width = aBtnWidth; - aDropDownBtn->SetRect(aPresContext, buttonRect); - - // since we have changed the height of the button - // make sure it has these new values - // XXX this may not be needed anymore - SetChildFrameSize(aDropDownBtn, aBtnWidth, aDesiredSize.height); - - - REFLOW_NOISY_MSG3("**AdjustCombobox - Reflow: WW: %d HH: %d\n", aDesiredSize.width, aDesiredSize.height); - - // Now cache the available height as our height without border and padding - // This sets up the optimization for if a new available width comes in and we are equal or - // less than it we can bail - if (aDesiredSize.width != mCacheSize.width || aDesiredSize.height != mCacheSize.height) { - if (aReflowState.availableWidth != NS_UNCONSTRAINEDSIZE) { - mCachedAvailableSize.width = aDesiredSize.width - (aBorderPadding.left + aBorderPadding.right); - } - if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) { - mCachedAvailableSize.height = aDesiredSize.height - (aBorderPadding.top + aBorderPadding.bottom); - } - nsFormControlFrame::SetupCachedSizes(mCacheSize, mCachedMaxElementSize, aDesiredSize); - } - - /////////////////////////////////////////////////////////////////// - // This is an experimental reflow that is turned off in the build -#ifdef DO_NEW_REFLOW_X - ReflowItems(aPresContext, aReflowState, aDesiredSize); -#endif - /////////////////////////////////////////////////////////////////// -} - -//---------------------------------------------------------- -// -//---------------------------------------------------------- -#ifdef DO_REFLOW_DEBUG +#ifdef DEBUG_rodsXXX static int myCounter = 0; - -static void printSize(char * aDesc, nscoord aSize) -{ - printf(" %s: ", aDesc); - if (aSize == NS_UNCONSTRAINEDSIZE) { - printf("UC"); - } else { - printf("%d", PX(aSize)); - } -} #endif -//------------------------------------------------------------------- -//-- Main Reflow for the Combobox -//------------------------------------------------------------------- NS_IMETHODIMP nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - aStatus = NS_FRAME_COMPLETE; - - REFLOW_COUNTER_REQUEST(); - -#ifdef DO_REFLOW_DEBUG - printf("-------------Starting Combobox Reflow ----------------------------\n"); - printf("%p ** Id: %d nsCCF::Reflow %d R: ", this, mReflowId, myCounter++); +#ifdef DEBUG_rodsXXX + printf("****** nsComboboxControlFrame::Reflow %d Reason: ", myCounter++); switch (aReflowState.reason) { case eReflowReason_Initial: - printf("Ini");break; + printf("eReflowReason_Initial\n");break; case eReflowReason_Incremental: - printf("Inc");break; + printf("eReflowReason_Incremental\n");break; case eReflowReason_Resize: - printf("Rsz");break; - case eReflowReason_StyleChange: - printf("Sty");break; - case eReflowReason_Dirty: - printf("Drt "); + printf("eReflowReason_Resize\n"); break; - default:printf("%d", aReflowState.reason);break; + case eReflowReason_StyleChange:printf("eReflowReason_StyleChange\n");break; } - - printSize("AW", aReflowState.availableWidth); - printSize("AH", aReflowState.availableHeight); - printSize("CW", aReflowState.mComputedWidth); - printSize("CH", aReflowState.mComputedHeight); - - nsCOMPtr optionsTemp = getter_AddRefs(GetOptions(mContent)); - PRUint32 numOptions; - optionsTemp->GetLength(&numOptions); - printSize("NO", (nscoord)numOptions); - - printf(" *\n"); - #endif - - PRBool bailOnWidth; - PRBool bailOnHeight; - - // Do initial check to see if we can bail out - // If it is an Initial or Incremental Reflow we never bail out here - // XXX right now we only bail if the width meets the criteria - // - // We bail: - // if mComputedWidth == NS_UNCONSTRAINEDSIZE and - // availableWidth == NS_UNCONSTRAINEDSIZE and - // we have cached an available size - // - // We bail: - // if mComputedWidth == NS_UNCONSTRAINEDSIZE and - // availableWidth != NS_UNCONSTRAINEDSIZE and - // availableWidth minus its border equals our cached available size - // - // We bail: - // if mComputedWidth != NS_UNCONSTRAINEDSIZE and - // cached availableSize.width == aReflowState.mComputedWidth and - // cached AvailableSize.width == aCacheSize.width - // - // NOTE: this returns whether we are doing an Incremental reflow - nsFormControlFrame::SkipResizeReflow(mCacheSize, - mCachedMaxElementSize, - mCachedAvailableSize, - aDesiredSize, aReflowState, - aStatus, - bailOnWidth, bailOnHeight); - if (bailOnWidth) { -#ifdef DO_REFLOW_DEBUG // check or size - const nsStyleSpacing* spacing; - GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); - nsMargin borderPadding; - borderPadding.SizeTo(0, 0, 0, 0); - spacing->CalcBorderPaddingFor(this, borderPadding); - UNCONSTRAINED_CHECK(); +#if 0 + nsresult skiprv = nsFormControlFrame::SkipResizeReflow(mCacheSize, mCachedMaxElementSize, aPresContext, + aDesiredSize, aReflowState, aStatus); + if (NS_SUCCEEDED(skiprv)) { + return skiprv; + } #endif - REFLOW_DEBUG_MSG3("^** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); - return NS_OK; - } - // add ourself to the form control - if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { - nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*,this)); - if (NS_FAILED(CreateDisplayFrame(aPresContext))) { - return NS_ERROR_FAILURE; - } - } - - // Go get all of the important frame nsresult rv = NS_OK; nsIFrame* buttonFrame = GetButtonFrame(aPresContext); + nsIFrame* displayFrame = GetDisplayFrame(aPresContext); nsIFrame* dropdownFrame = GetDropdownFrame(); // Don't try to do any special sizing and positioning unless all of the frames // have been created. - if ((nsnull == mDisplayFrame) || + if ((nsnull == displayFrame) || (nsnull == buttonFrame) || (nsnull == dropdownFrame)) { @@ -1222,9 +728,12 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, nsRect buttonRect; nsRect dropdownRect; - // get our border and padding, - // XXX - should be the same mComputedBorderPadding? - // maybe we should use that? + + if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); + nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*,this)); + } + const nsStyleSpacing* spacing; GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); nsMargin borderPadding; @@ -1232,11 +741,39 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, spacing->CalcBorderPaddingFor(this, borderPadding); // Get the current sizes of the combo box child frames - mDisplayFrame->GetRect(displayRect); + displayFrame->GetRect(displayRect); buttonFrame->GetRect(buttonRect); dropdownFrame->GetRect(dropdownRect); - // We should cache this instead getting it everytime + nsHTMLReflowState firstPassState(aReflowState); + + // Only reflow the display and button if they are the target of + // the incremental reflow, unless they change size. If they do + // then everything needs to be reflowed. + if (eReflowReason_Incremental == firstPassState.reason) { + nsIFrame* targetFrame; + firstPassState.reflowCommand->GetTarget(targetFrame); + if ((targetFrame == buttonFrame) || (targetFrame == displayFrame)) { + nsRect oldDisplayRect = displayRect; + nsRect oldButtonRect = buttonRect; + rv = nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + // nsAreaFrame::Reflow adds in the border and padding so we need to remove it + if (NS_UNCONSTRAINEDSIZE != firstPassState.mComputedWidth) { + aDesiredSize.width -= borderPadding.left + borderPadding.right; + } + displayFrame->GetRect(displayRect); + buttonFrame->GetRect(buttonRect); + if ((oldDisplayRect == displayRect) && (oldButtonRect == buttonRect)) { + aStatus = NS_FRAME_COMPLETE; + return rv; + } + } + nsIReflowCommand::ReflowType type; + aReflowState.reflowCommand->GetType(type); + firstPassState.reason = eReflowReason_StyleChange; + firstPassState.reflowCommand = nsnull; + } + // the default size of the of scrollbar // that will be the default width of the dropdown button // the height will be the height of the text @@ -1257,382 +794,105 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, float scale; dx->GetCanonicalPixelScale(scale); scrollbarWidth = NSIntPixelsToTwips(info.mSize, p2t*scale); - } - - // set up a new reflow state for use throughout - nsHTMLReflowState firstPassState(aReflowState); - nsHTMLReflowMetrics dropdownDesiredSize(nsnull); - - // Check to see if this a fully unconstrained reflow - PRBool fullyUnconstrained = firstPassState.availableWidth == NS_UNCONSTRAINEDSIZE && - firstPassState.mComputedWidth == NS_UNCONSTRAINEDSIZE && - firstPassState.availableHeight == NS_UNCONSTRAINEDSIZE && - firstPassState.mComputedHeight == NS_UNCONSTRAINEDSIZE; - - PRBool forceReflow = PR_FALSE; - - // Only reflow the display and button - // if they are the target of the incremental reflow, unless they change size. - if (eReflowReason_Incremental == aReflowState.reason) { - nsIFrame* targetFrame; - firstPassState.reflowCommand->GetTarget(targetFrame); - // Check to see if we are the target of the Incremental Reflow - if (targetFrame == this) { - // We need to check here to see if we can get away with just reflowing - // the combobox and not the dropdown - REFLOW_DEBUG_MSG("-----------------Target is Combobox------------\n"); - - // If the mComputedWidth matches our cached display width - // then we get away with bailing out - PRBool doFullReflow = firstPassState.mComputedWidth != NS_UNCONSTRAINEDSIZE && - firstPassState.mComputedWidth != mItemDisplayWidth; - if (!doFullReflow) { - // OK, so we got lucky and the size didn't change - // so do a simple reflow and bail out - REFLOW_DEBUG_MSG("------------Reflowing AreaFrame and bailing----\n\n"); - ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, - mDisplayFrame, buttonFrame, mItemDisplayWidth, - scrollbarWidth, borderPadding); - REFLOW_COUNTER(); - UNCONSTRAINED_CHECK(); - REFLOW_DEBUG_MSG3("&** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); - return rv; - } - // Nope, something changed that affected our size - // so we need to do a full reflow and resize ourself - REFLOW_DEBUG_MSG("------------Do Full Reflow----\n\n"); - firstPassState.reason = eReflowReason_StyleChange; - firstPassState.reflowCommand = nsnull; - forceReflow = PR_TRUE; - - } else { - // Now, see if our target is the dropdown - // If so, maybe an items was added or some style changed etc. - // OR - // We get an Incremental reflow on the dropdown when it is being - // shown or hidden. - if (targetFrame == dropdownFrame) { - REFLOW_DEBUG_MSG("---------Target is Dropdown (Clearing Unc DD Size)---\n"); - PRBool bail = PR_FALSE; - - // Let's start by checking to see if this is a reflow ro showing or hiding. - nsIView * view; - dropdownFrame->GetView(aPresContext, &view); - nsViewVisibility vis = nsViewVisibility_kHide; - NS_ASSERTION(view != nsnull, "The dropdown frame doesn't have a view!"); - if (view != nsnull) { - view->GetVisibility(vis); - } - // If the view is hidden, but the combobox thinks the it is dropped down - // 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 - 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); - - } 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); - // cache the values here also, - // since we just did an unconstrained reflow - mCachedUncDropdownSize.width = dropdownDesiredSize.width; - mCachedUncDropdownSize.height = dropdownDesiredSize.height; - REFLOW_DEBUG_MSG3("---2 Caching mCachedUncDropdownSize %d,%d\n", PX(mCachedUncDropdownSize.width), PX(mCachedUncDropdownSize.height)); - } - - // Ok, we get to bail because it was either being shown or hidden - if (bail) { - if (fullyUnconstrained) { - aDesiredSize.width = mCachedUncComboSize.width; - aDesiredSize.height = mCachedUncComboSize.height; - } else { - 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; - REFLOW_DEBUG_MSG3("|** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); - REFLOW_DEBUG_MSG("---- Setting Cached values and then bailing out\n\n"); - UNCONSTRAINED_CHECK(); - return NS_OK; - } - // Nope, we were unlucky so now we do a full reflow - mCachedUncDropdownSize.width = kSizeNotSet; - mCachedUncDropdownSize.height = kSizeNotSet; - REFLOW_DEBUG_MSG("---- Doing Full Reflow\n"); - // This is an incremental reflow targeted at the dropdown list - // and it didn't have anything to do with being show or hidden. - // - // The incremental reflow will not get to the dropdown list - // because it is in the "popup" list - // when this flow of control drops out of this if it will do a reflow - // on the AreaFrame which SHOULD make it get tothe drop down - // except that it is in the popup list, so we have it reflowed as - // a StyleChange, this is not as effecient as doing an Incremental - // - // At this point we want to by pass the reflow optimization in the dropdown - // because we aren't why it is getting an incremental reflow, but we do - // know that it needs to be resized or restyled - //mListControlFrame->SetOverrideReflowOptimization(PR_TRUE); - - } else if (targetFrame == mDisplayFrame || targetFrame == buttonFrame) { - /*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")); - REFLOW_DEBUG_MSG("---- Doing AreaFrame Reflow and then bailing out\n"); - // Do simple reflow and bail out - ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, - mDisplayFrame, buttonFrame, - mItemDisplayWidth, scrollbarWidth, borderPadding, kSizeNotSet, PR_TRUE); - REFLOW_DEBUG_MSG3("+** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); - REFLOW_COUNTER(); - UNCONSTRAINED_CHECK(); - return rv; - } else { - // 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"); - REFLOW_DEBUG_MSG("---- Doing Reflow as StyleChange\n"); - } - firstPassState.reason = eReflowReason_StyleChange; - firstPassState.reflowCommand = nsnull; - mListControlFrame->SetOverrideReflowOptimization(PR_TRUE); - forceReflow = PR_TRUE; - } - } - - // This ifdef is for the new approach to reflow - // where we don't reflow the dropdown - // we just figure out or width from the list of items - // - // This next section is the Current implementation - // the else contains the new reflow code -#ifndef DO_NEW_REFLOW - - // Here is another special optimization - // Only reflow the dropdown if it has never been reflowed unconstrained - // - // Or someone up above here may want to force it to be reflowed - // by setting one or both of these to kSizeNotSet - if ((mCachedUncDropdownSize.width == kSizeNotSet && - mCachedUncDropdownSize.height == kSizeNotSet) || forceReflow) { - REFLOW_DEBUG_MSG3("---Re %d,%d\n", PX(mCachedUncDropdownSize.width), PX(mCachedUncDropdownSize.height)); - // A width has not been specified for the select so size the display area - // to match the width of the longest item in the drop-down list. The dropdown - // list has already been reflowed and sized to shrink around its contents above. - ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, - aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); - if (forceReflow) { - mCachedUncDropdownSize.width = dropdownDesiredSize.width; - mCachedUncDropdownSize.height = dropdownDesiredSize.height; - } - } else { - // Here we pretended we did an unconstrained reflow - // so we set the cached values and continue on - REFLOW_DEBUG_MSG3("--- Using Cached ListBox Size %d,%d\n", PX(mCachedUncDropdownSize.width), PX(mCachedUncDropdownSize.height)); - dropdownDesiredSize.width = mCachedUncDropdownSize.width; - dropdownDesiredSize.height = mCachedUncDropdownSize.height; - } - - ///////////////////////////////////////////////////////////////////////// - // XXX - I need to clean this nect part up a little it is very redundant - - // Check here to if this is a mComputed unconstrained reflow - PRBool computedUnconstrained = firstPassState.mComputedWidth == NS_UNCONSTRAINEDSIZE && - firstPassState.mComputedHeight == NS_UNCONSTRAINEDSIZE; - if (computedUnconstrained && !forceReflow) { - // Because Incremental reflows aren't actually getting to the dropdown - // we cache the size from when it did a fully unconstrained reflow - // we then check to see if the size changed at all, - // if not then bail out we don't need to worry - if (mCachedUncDropdownSize.width == kSizeNotSet && mCachedUncDropdownSize.height == kSizeNotSet) { - mCachedUncDropdownSize.width = dropdownDesiredSize.width; - mCachedUncDropdownSize.height = dropdownDesiredSize.height; - REFLOW_DEBUG_MSG3("---1 Caching mCachedUncDropdownSize %d,%d\n", PX(mCachedUncDropdownSize.width), PX(mCachedUncDropdownSize.height)); - - } else if (mCachedUncDropdownSize.width == dropdownDesiredSize.width && - mCachedUncDropdownSize.height == dropdownDesiredSize.height) { - - if (mCachedUncComboSize.width != kSizeNotSet && mCachedUncComboSize.height != kSizeNotSet) { - REFLOW_DEBUG_MSG3("--- Bailing because of mCachedUncDropdownSize %d,%d\n\n", PX(mCachedUncDropdownSize.width), PX(mCachedUncDropdownSize.height)); - aDesiredSize.width = mCachedUncComboSize.width; - aDesiredSize.height = mCachedUncComboSize.height; - - if (aDesiredSize.maxElementSize != nsnull) { - aDesiredSize.maxElementSize->width = mCachedMaxElementSize.width; - aDesiredSize.maxElementSize->height = mCachedMaxElementSize.height; - } - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; - UNCONSTRAINED_CHECK(); - REFLOW_DEBUG_MSG3("#** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); - return NS_OK; - } - } else { - mCachedUncDropdownSize.width = dropdownDesiredSize.width; - mCachedUncDropdownSize.height = dropdownDesiredSize.height; - } - } - // clean up stops here - ///////////////////////////////////////////////////////////////////////// - - // So this point we know we flowed the dropdown unconstrained - // now we get to figure out how big we need to be and - // - // We don't reflow the combobox here at the new size - // we cache its new size and reflow it on the dropdown - nsSize size; - PRInt32 length = 0; - mListControlFrame->GetNumberOfOptions(&length); - - // dropdownRect will hold the content size (minus border padding) - // for the display area - dropdownFrame->GetRect(dropdownRect); - - // Get maximum size of the largest item in the dropdown - // The height of the display frame will be that height - // the width will be the same as - // the dropdown width (minus its borderPadding) OR - // a caculation off the mComputedWidth from reflow - mListControlFrame->GetMaximumSize(size); - - // the variable "size" will now be - // the default size of the dropdown btn - if (scrollbarWidth > 0) { - size.width = scrollbarWidth; - } - - // Get the border and padding for the dropdown - const nsStyleSpacing* dropSpacing; - dropdownFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dropSpacing); - nsMargin dropBorderPadding; - dropBorderPadding.SizeTo(0, 0, 0, 0); - dropSpacing->CalcBorderPaddingFor(dropdownFrame, dropBorderPadding); - - // get the borderPadding for the display area - const nsStyleSpacing* dspSpacing; - mDisplayFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dspSpacing); - nsMargin dspBorderPadding; - dspBorderPadding.SizeTo(0, 0, 0, 0); - dspSpacing->CalcBorderPaddingFor(mDisplayFrame, dspBorderPadding); - - // Substract dropdown's borderPadding from the width of the dropdown rect - // to get the size of the content area - // - // the height will come from the mDisplayFrame's height - // declare a size for the item display frame + } //Set the desired size for the button and display frame if (NS_UNCONSTRAINEDSIZE == firstPassState.mComputedWidth) { - REFLOW_DEBUG_MSG("Unconstrained.....\n"); - REFLOW_DEBUG_MSG4("*B mItemDisplayWidth %d dropdownRect.width:%d dropdownRect.w+h %d\n", PX(mItemDisplayWidth), PX(dropdownRect.width), PX((dropBorderPadding.left + dropBorderPadding.right))); + // A width has not been specified for the select so size the display area to + // match the width of the longest item in the drop-down list. The dropdown + // list has already been reflowed and sized to shrink around its contents above. - // Start with the dropdown rect's width - mItemDisplayWidth = dropdownRect.width; - - REFLOW_DEBUG_MSG2("* mItemDisplayWidth %d\n", PX(mItemDisplayWidth)); - - // subtract off the display's BorderPadding - mItemDisplayWidth -= dspBorderPadding.left + dspBorderPadding.right; - - REFLOW_DEBUG_MSG2("*A mItemDisplayWidth %d\n", PX(mItemDisplayWidth)); - - } else { - REFLOW_DEBUG_MSG("Constrained.....\n"); - if (firstPassState.mComputedWidth > 0) { - // Compute the display item's width from reflow's mComputedWidth - // mComputedWidth has already excluded border and padding - // so subtract off the button's size - REFLOW_DEBUG_MSG3("B mItemDisplayWidth %d %d\n", PX(mItemDisplayWidth), PX(dspBorderPadding.right)); - mItemDisplayWidth = firstPassState.mComputedWidth - dspBorderPadding.left - dspBorderPadding.right; - REFLOW_DEBUG_MSG2("A mItemDisplayWidth %d\n", PX(mItemDisplayWidth)); - REFLOW_DEBUG_MSG4("firstPassState.mComputedWidth %d - size.width %d dspBorderPadding.right %d\n", PX(firstPassState.mComputedWidth), PX(size.width), PX(dspBorderPadding.right)); + // Reflow the dropdown shrink-wrapped. + PRBool saveMES = aDesiredSize.maxElementSize != nsnull; + nsSize * maxElementSize = nsnull; + if (saveMES) { + maxElementSize = new nsSize(); + //maxElementSize = new nsSize(*aDesiredSize.maxElementSize); } - } - // this reflows and makes and last minute adjustments - ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, - mDisplayFrame, buttonFrame, mItemDisplayWidth, scrollbarWidth, - borderPadding, size.height); + nsHTMLReflowMetrics dropdownDesiredSize(maxElementSize); + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); - // The dropdown was reflowed UNCONSTRAINED before, now we need to check to see - // if it needs to be resized. - // - // Optimization - The style (font, etc.) maybe different for the display item - // than for any particular item in the dropdown. So, if the new size of combobox - // is smaller than the dropdown, that is OK, The dropdown MUST always be either the same - //size as the combo or larger if necessary -#if 0 - if (aDesiredSize.width > dropdownDesiredSize.width) { - if (eReflowReason_Initial == firstPassState.reason) { - firstPassState.reason = eReflowReason_Resize; + nsSize size; + PRInt32 length = 0; + mListControlFrame->GetNumberOfOptions(&length); + dropdownFrame->GetRect(dropdownRect); + + const nsStyleSpacing* dropSpacing; + dropdownFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dropSpacing); + nsMargin dropBorderPadding; + dropBorderPadding.SizeTo(0, 0, 0, 0); + dropSpacing->CalcBorderPaddingFor(dropdownFrame, dropBorderPadding); + dropdownRect.width -= (dropBorderPadding.left + dropBorderPadding.right); + + // Get maximum size and height of a option in the dropdown + mListControlFrame->GetMaximumSize(size); + + if (scrollbarWidth > 0) { + size.width = scrollbarWidth; } - REFLOW_DEBUG_MSG3("*** Reflowing ListBox to width: %d it was %d\n", PX(aDesiredSize.width), PX(dropdownDesiredSize.width)); + const nsStyleSpacing* dspSpacing; + displayFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dspSpacing); + nsMargin dspBorderPadding; + dspBorderPadding.SizeTo(0, 0, 0, 0); + dspSpacing->CalcBorderPaddingFor(displayFrame, dspBorderPadding); + + // Set width of display to match width of the drop down + SetChildFrameSize(displayFrame, dropdownRect.width-size.width+dspBorderPadding.left+dspBorderPadding.right, + size.height+dspBorderPadding.top+dspBorderPadding.bottom); + + // Size the button + SetChildFrameSize(buttonFrame, size.width, size.height); + + // Reflow display + button + nsAreaFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); + + displayFrame->GetRect(displayRect); + buttonFrame->GetRect(buttonRect); + buttonRect.y = displayRect.y; + buttonRect.height = displayRect.height; + buttonFrame->SetRect(aPresContext, buttonRect); + // Reflow the dropdown list to match the width of the display + button - ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, - aDesiredSize.width, NS_UNCONSTRAINEDSIZE); - } -#endif - -#else // DO_NEW_REFLOW - - if (mCacheSize.width == kSizeNotSet) { - ReflowItems(aPresContext, aReflowState, aDesiredSize); - } else { - aDesiredSize.width = mCacheSize.width; - aDesiredSize.height = mCacheSize.height; - } - - // get the borderPadding for the display area - const nsStyleSpacing* dspSpacing; - mDisplayFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dspSpacing); - nsMargin dspBorderPadding; - dspBorderPadding.SizeTo(0, 0, 0, 0); - - dspSpacing->CalcBorderPaddingFor(mDisplayFrame, dspBorderPadding); - - if (NS_UNCONSTRAINEDSIZE == firstPassState.mComputedWidth) { - mItemDisplayWidth = aDesiredSize.width - (dspBorderPadding.left + dspBorderPadding.right); - mItemDisplayWidth -= borderPadding.left + borderPadding.right; - } else { - if (firstPassState.mComputedWidth > 0) { - // Compute the display item's width from reflow's mComputedWidth - // mComputedWidth has already excluded border and padding - // so subtract off the button's size - mItemDisplayWidth = firstPassState.mComputedWidth - dspBorderPadding.left - dspBorderPadding.right; + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, aDesiredSize.width, NS_UNCONSTRAINEDSIZE); + dropdownFrame->GetRect(dropdownRect); + + if (maxElementSize) { + delete maxElementSize; } - } - // this reflows and makes and last minute adjustments - ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, - mDisplayFrame, buttonFrame, mItemDisplayWidth, scrollbarWidth, - borderPadding, - aDesiredSize.height- borderPadding.top - borderPadding.bottom - - dspBorderPadding.top - dspBorderPadding.bottom); -#endif // DO_NEW_REFLOW + } else { + // A width has been specified for the select. + // Make the display frame's width + button frame width = the width specified. + nsHTMLReflowMetrics dropdownDesiredSize(aDesiredSize); + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + // Get unconstrained size of the dropdown list. + nsSize size; + mListControlFrame->GetMaximumSize(size); + + if (scrollbarWidth > 0) { + size.width = scrollbarWidth; + } + // Size the button to be the same as the scrollbar width + SetChildFrameSize(buttonFrame, size.width, size.height); + + // Compute display width + nscoord displayWidth = firstPassState.mComputedWidth - size.width; + // nsAreaFrame::Reflow adds in the border and padding so we need to remove it + //displayWidth -= borderPadding.left + borderPadding.right; + + // Set the displayFrame to match the displayWidth computed above + SetChildFrameSize(displayFrame, displayWidth, size.height); + + // Reflow again with the width of the display frame set. + nsAreaFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); + // nsAreaFrame::Reflow adds in the border and padding so we need to remove it + // XXX rods - this hould not be subtracted in + //aDesiredSize.width += borderPadding.left + borderPadding.right; + + // Reflow the dropdown list to match the width of the display + button + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, aDesiredSize.width, NS_UNCONSTRAINEDSIZE); + + } // Set the max element size to be the same as the desired element size. if (nsnull != aDesiredSize.maxElementSize) { @@ -1640,37 +900,330 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, aDesiredSize.maxElementSize->height = aDesiredSize.height; } + aStatus = NS_FRAME_COMPLETE; #if 0 COMPARE_QUIRK_SIZE("nsComboboxControlFrame", 127, 22) #endif - // cache the availabe size to be our desired size minus the borders - // this is so if our cached avilable size is ever equal to or less - // than the real avilable size we can bail out - if (aReflowState.availableWidth != NS_UNCONSTRAINEDSIZE) { - mCachedAvailableSize.width = aDesiredSize.width - (borderPadding.left + borderPadding.right); - } - if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) { - mCachedAvailableSize.height = aDesiredSize.height - (borderPadding.top + borderPadding.bottom); - } - nsFormControlFrame::SetupCachedSizes(mCacheSize, mCachedMaxElementSize, aDesiredSize); - - REFLOW_DEBUG_MSG3("** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); - REFLOW_COUNTER(); - UNCONSTRAINED_CHECK(); - - // If this was a fully unconstrained reflow we cache - // the combobox's unconstrained size - if (fullyUnconstrained) { - mCachedUncComboSize.width = aDesiredSize.width; - mCachedUncComboSize.height = aDesiredSize.height; - } - return rv; } + +//------------------------------------------------------------------------------- +//------------------------------------------------------------------------------- +// New Reflow +//------------------------------------------------------------------------------- +//------------------------------------------------------------------------------- +#else // DO_OLD_REFLOW + +#ifdef DEBUG_rods +nsComboboxControlFrame * pCB = nsnull; +static int myCounter = 0; +#endif + +NS_IMETHODIMP +nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ +#ifdef DEBUG_rods + //if (pCB) { + printf("%p ****** nsComboboxControlFrame::Reflow %d Reason: ", this, myCounter++); + switch (aReflowState.reason) { + case eReflowReason_Initial: + printf("eReflowReason_Initial\n");break; + case eReflowReason_Incremental: + printf("eReflowReason_Incremental\n");break; + case eReflowReason_Resize: + printf("eReflowReason_Resize\n"); + break; + case eReflowReason_StyleChange:printf("eReflowReason_StyleChange\n");break; + } + //} +#endif + +#if 0 + nsresult skiprv = nsFormControlFrame::SkipResizeReflow(mCacheSize, mCachedMaxElementSize, aPresContext, + aDesiredSize, aReflowState, aStatus); + if (NS_SUCCEEDED(skiprv)) { + return skiprv; + } +#endif + + nsresult rv = NS_OK; + nsIFrame* buttonFrame = GetButtonFrame(aPresContext); + nsIFrame* displayFrame = GetDisplayFrame(aPresContext); + nsIFrame* dropdownFrame = GetDropdownFrame(); + + // Don't try to do any special sizing and positioning unless all of the frames + // have been created. + if ((nsnull == displayFrame) || + (nsnull == buttonFrame) || + (nsnull == dropdownFrame)) + { + // Since combobox frames are missing just do a normal area frame reflow + return nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + } + + // size of each part of the combo box + nsRect displayRect; + nsRect buttonRect; + nsRect dropdownRect; + + + if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { + nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*,this)); + } + + const nsStyleSpacing* spacing; + GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + nsMargin borderPadding; + borderPadding.SizeTo(0, 0, 0, 0); + spacing->CalcBorderPaddingFor(this, borderPadding); + + // Get the current sizes of the combo box child frames + displayFrame->GetRect(displayRect); + buttonFrame->GetRect(buttonRect); + dropdownFrame->GetRect(dropdownRect); + + nsHTMLReflowState firstPassState(aReflowState); + + // Only reflow the display and button if they are the target of + // the incremental reflow, unless they change size. If they do + // then everything needs to be reflowed. + if (eReflowReason_Incremental == firstPassState.reason) { + nsIFrame* targetFrame; + firstPassState.reflowCommand->GetTarget(targetFrame); + if (targetFrame == this) { + // not sure what I should be doing here for an incremental reflow + // so I will let it just reflow as normal + // but it does seems to go into this code. + } else { + if (targetFrame != dropdownFrame) { +#ifdef DEBUG_rods + printf("+++++++++++++++++++++++\n"); +#endif + rv = nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + displayFrame->GetRect(displayRect); + buttonFrame->GetRect(buttonRect); + buttonRect.y = displayRect.y; + buttonRect.height = displayRect.height; + buttonFrame->SetRect(aPresContext, buttonRect); + aStatus = NS_FRAME_COMPLETE; +#ifdef DEBUG_rods + printf("--> W: %d H: %d\n", aDesiredSize.width, aDesiredSize.height); +#endif + return rv; + } else { +#if 0 + nsRect dropdownRect; + dropdownFrame->GetRect(dropdownRect); + nsHTMLReflowMetrics dropdownDesiredSize(aDesiredSize); + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, + aStatus, dropdownRect.width, dropdownRect.height); + nsCOMPtr context; + targetFrame->GetStyleContext(getter_AddRefs(context)); + const nsStyleDisplay* disp = (const nsStyleDisplay*)context->GetStyleData(eStyleStruct_Display); + printf("IsVisible %s\n", disp->mVisible == NS_STYLE_VISIBILITY_VISIBLE?"yes":"No"); + //if (disp->mVisible == NS_STYLE_VISIBILITY_VISIBLE) { + nsRect rect; + GetRect(rect); + aDesiredSize.width = rect.width;// + borderPadding.left + borderPadding.right; + aDesiredSize.height = rect.height;// + borderPadding.top + borderPadding.bottom; + aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.descent = 0; + dropdownRect.width = rect.width; + dropdownFrame->SetRect(aPresContext, dropdownRect); + printf("Skipping out.........................."); + aStatus = NS_FRAME_COMPLETE; + return NS_OK; + //} +#endif + } + } + } + + // the default size of the of scrollbar + // that will be the default width of the dropdown button + // the height will be the height of the text + nscoord scrollbarWidth = -1; + nsCOMPtr dx; + aPresContext->GetDeviceContext(getter_AddRefs(dx)); + if (dx) { + // Get the width in Device pixels (in this case screen) + SystemAttrStruct info; + dx->GetSystemAttribute(eSystemAttr_Size_ScrollbarWidth, &info); + // Get the pixels to twips conversion for the current device (screen or printer) + float p2t; + aPresContext->GetPixelsToTwips(&p2t); + // Get the scale factor for mapping from one device (screen) + // to another device (screen or printer) + // Typically when it is a screen the scale 1.0 + // when it is a printer is could be anything + float scale; + dx->GetCanonicalPixelScale(scale); + scrollbarWidth = NSIntPixelsToTwips(info.mSize, p2t*scale); + } +#ifdef DEBUG_rods + printf("UNC %d AV %d \n", firstPassState.mComputedWidth,firstPassState.availableWidth); +#endif + //Set the desired size for the button and display frame + if (NS_UNCONSTRAINEDSIZE == firstPassState.mComputedWidth) { +#ifdef DEBUG_rods + printf("=====================================\n"); +#endif + + // A width has not been specified for the select so size the display area to + // match the width of the longest item in the drop-down list. The dropdown + // list has already been reflowed and sized to shrink around its contents above. + + // Reflow the dropdown shrink-wrapped. + PRBool saveMES = aDesiredSize.maxElementSize != nsnull; + nsSize * maxElementSize = nsnull; + if (saveMES) { + maxElementSize = new nsSize(); + //maxElementSize = new nsSize(*aDesiredSize.maxElementSize); + } + nsHTMLReflowMetrics dropdownDesiredSize(maxElementSize); + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + + nsSize size; + PRInt32 length = 0; + mListControlFrame->GetNumberOfOptions(&length); + dropdownFrame->GetRect(dropdownRect); + + const nsStyleSpacing* dropSpacing; + dropdownFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dropSpacing); + nsMargin dropBorderPadding; + dropBorderPadding.SizeTo(0, 0, 0, 0); + dropSpacing->CalcBorderPaddingFor(dropdownFrame, dropBorderPadding); + dropdownRect.width -= (dropBorderPadding.left + dropBorderPadding.right); + + // Get maximum size and height of a option in the dropdown + mListControlFrame->GetMaximumSize(size); + + if (scrollbarWidth > 0) { + size.width = scrollbarWidth; + } + const nsStyleSpacing* dspSpacing; + displayFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dspSpacing); + nsMargin dspBorderPadding; + dspBorderPadding.SizeTo(0, 0, 0, 0); + dspSpacing->CalcBorderPaddingFor(displayFrame, dspBorderPadding); + +#ifdef DEBUG_rods + printf("W: %d\n", dropdownRect.width-size.width+dspBorderPadding.left+dspBorderPadding.right); +#endif + // Set width of display to match width of the drop down + SetChildFrameSize(displayFrame, dropdownRect.width-size.width+dspBorderPadding.left+dspBorderPadding.right, + size.height+dspBorderPadding.top+dspBorderPadding.bottom); + + // Size the button + SetChildFrameSize(buttonFrame, size.width, size.height); + + // Reflow display + button + nsAreaFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); + + displayFrame->GetRect(displayRect); + buttonFrame->GetRect(buttonRect); + buttonRect.y = displayRect.y; + buttonRect.height = displayRect.height; + buttonFrame->SetRect(aPresContext, buttonRect); + + // Reflow the dropdown list to match the width of the display + button + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, aDesiredSize.width, NS_UNCONSTRAINEDSIZE); + dropdownFrame->GetRect(dropdownRect); + + if (maxElementSize) { + delete maxElementSize; + } + + } else { +#ifdef DEBUG_rods + printf("*************************************\n"); +#endif + // for debug ------- + PRInt32 length = 0; + mListControlFrame->GetNumberOfOptions(&length); + //------ + + // A width has been specified for the select. + // Make the display frame's width + button frame width = the width specified. + nsHTMLReflowMetrics dropdownDesiredSize(aDesiredSize); + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + // Get unconstrained size of the dropdown list. + nsSize size; + mListControlFrame->GetMaximumSize(size); + + if (scrollbarWidth > 0) { + size.width = scrollbarWidth; + } + // Size the button to be the same as the scrollbar width + SetChildFrameSize(buttonFrame, size.width, size.height); + + if (firstPassState.mComputedWidth > 0) { + // Compute display width + nscoord displayWidth = firstPassState.mComputedWidth - size.width; + // nsAreaFrame::Reflow adds in the border and padding so we need to remove it + //displayWidth -= borderPadding.left + borderPadding.right; + +#ifdef DEBUG_rods + printf("WW: %d\n", displayWidth); +#endif + // Set the displayFrame to match the displayWidth computed above + if (displayWidth >= 0) { + SetChildFrameSize(displayFrame, displayWidth, size.height); + } + + // Reflow again with the width of the display frame set. + nsAreaFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); + + displayFrame->GetRect(displayRect); + displayRect.width = displayWidth; + buttonFrame->GetRect(buttonRect); + buttonRect.x = displayWidth+borderPadding.left; + buttonRect.y = displayRect.y; + buttonRect.height = displayRect.height; + buttonFrame->SetRect(aPresContext, buttonRect); + displayFrame->SetRect(aPresContext, displayRect); +#ifdef DEBUG_rods + printf("DW: %d\n", aDesiredSize.width); +#endif + // nsAreaFrame::Reflow adds in the border and padding so we need to remove it + // XXX rods - this hould not be subtracted in + //aDesiredSize.width += borderPadding.left + borderPadding.right; + + // Reflow the dropdown list to match the width of the display + button + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, aDesiredSize.width, NS_UNCONSTRAINEDSIZE); + } + aDesiredSize.width = firstPassState.mComputedWidth + borderPadding.left + borderPadding.right; + aDesiredSize.height = firstPassState.mComputedHeight + borderPadding.top + borderPadding.bottom; + aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.descent = 0; + } + + // 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; +#if 0 + COMPARE_QUIRK_SIZE("nsComboboxControlFrame", 127, 22) +#endif + + nsFormControlFrame::SetupCachedSizes(mCacheSize, mCachedMaxElementSize, aDesiredSize); +#ifdef DEBUG_rods + printf("--> W: %d H: %d\n", aDesiredSize.width, aDesiredSize.height); +#endif + return rv; + +} +#endif // DO_OLD_REFLOW //------------------------------------------------------------------------------- //------------------------------------------------------------------------------- // Done with New Reflow @@ -1808,15 +1361,10 @@ nsComboboxControlFrame::SetDropDown(nsIFrame* aDropDownFrame) return NS_ERROR_FAILURE; } - - // The ListControlFrame was just created and added to the comboxbox - // so provide it with a PresState so it can restore itself - // when it does its first "Reset" if (mPresState) { mListControlFrame->SetPresState(mPresState); mPresState = do_QueryInterface(nsnull); } - return NS_OK; } @@ -1865,13 +1413,7 @@ nsComboboxControlFrame::UpdateSelection(PRBool aDoDispatchEvent, PRBool aForceUp if (mListControlFrame) { // Check to see if the selection changed if (mSelectedIndex != aNewIndex || aForceUpdate) { - //???if (mSelectedIndex != aNewIndex || (aForceUpdate && aNewIndex != kSizeNotSet)) { mListControlFrame->GetSelectedItem(mTextStr); // Update text box -#ifdef DO_REFLOW_DEBUG - char * str = mTextStr.ToNewCString(); - REFLOW_DEBUG_MSG2("UpdateSelection %s\n", str); - delete [] str; -#endif mListControlFrame->UpdateSelection(aDoDispatchEvent, aForceUpdate, mContent); } mSelectedIndex = aNewIndex; @@ -1885,7 +1427,7 @@ nsComboboxControlFrame::AbsolutelyPositionDropDown() { nsRect absoluteTwips; nsRect absolutePixels; - +// XXX Not used nsIFrame* displayFrame = GetDisplayFrame(mPresContext); nsRect rect; this->GetRect(rect); GetAbsoluteFramePosition(mPresContext, this, absoluteTwips, absolutePixels); @@ -1912,30 +1454,49 @@ nsComboboxControlFrame::SelectionChanged() // Send reflow command because the new text maybe larger nsresult rv = NS_OK; if (mDisplayContent) { - nsAutoString value; - const nsTextFragment* fragment; - nsresult result = mDisplayContent->GetText(&fragment); - if (NS_SUCCEEDED(result)) { - fragment->AppendTo(value); - } - PRBool shouldSetValue = PR_FALSE; - if (NS_FAILED(result) || value.Length() == 0) { - shouldSetValue = PR_TRUE; - } else { - shouldSetValue = value != mTextStr; - } - if (shouldSetValue) { - rv = mDisplayContent->SetText(mTextStr.GetUnicode(), mTextStr.Length(), PR_TRUE); - nsFrameState 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 htmlContent(do_QueryInterface(mDisplayContent, &rv)); + if (NS_SUCCEEDED(rv) && htmlContent) { + nsHTMLValue value; + nsresult result = htmlContent->GetHTMLAttribute(nsHTMLAtoms::value, value); + + PRBool shouldSetValue = PR_FALSE; + if (NS_FAILED(result) || value.GetUnit() == eHTMLUnit_Empty) { + shouldSetValue = PR_TRUE; + } else if (NS_SUCCEEDED(result) && value.GetUnit() == eHTMLUnit_String) { + nsAutoString str; + value.GetStringValue(str); + shouldSetValue = str != mTextStr; + } + if (shouldSetValue) { + rv = htmlContent->SetHTMLAttribute(nsHTMLAtoms::value, mTextStr, PR_TRUE); +#if 1 + if (NS_SUCCEEDED(rv)) { + nsIFrame* displayFrame = GetDisplayFrame(mPresContext); + + nsIReflowCommand* cmd; + rv = NS_NewHTMLReflowCommand(&cmd, displayFrame, nsIReflowCommand::StyleChanged); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr shell; + rv = mPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(rv) && shell) { + if (NS_SUCCEEDED(shell->EnterReflowLock())) { + shell->AppendReflowCommand(cmd); + shell->ExitReflowLock(PR_TRUE); + } + } + NS_RELEASE(cmd); + } + } +#else + if (mParent) { + nsCOMPtr shell; + rv = mPresContext->GetShell(getter_AddRefs(shell)); + mState |= NS_FRAME_IS_DIRTY; + mParent->ReflowDirtyChild(shell, (nsIFrame*) this); + } + +#endif + } } } return rv; @@ -1965,18 +1526,19 @@ nsComboboxControlFrame::DoneAddingContent(PRBool aIsDone) NS_IMETHODIMP nsComboboxControlFrame::AddOption(nsIPresContext* aPresContext, PRInt32 aIndex) { -#ifdef DO_REFLOW_DEBUG - printf("**********\n*********AddOption: %d\n", aIndex); +#ifdef DEBUG_rodsXXX + if (!pCB) pCB = this; #endif + nsISelectControlFrame* listFrame = nsnull; nsIFrame* dropdownFrame = GetDropdownFrame(); nsresult rv = dropdownFrame->QueryInterface(NS_GET_IID(nsISelectControlFrame), (void**)&listFrame); if (NS_SUCCEEDED(rv) && listFrame) { rv = listFrame->AddOption(aPresContext, aIndex); - //PRInt32 index; - //mListControlFrame->GetSelectedIndex(&index); - //UpdateSelection(PR_FALSE, PR_TRUE, index); + PRInt32 index; + mListControlFrame->GetSelectedIndex(&index); + UpdateSelection(PR_FALSE, PR_TRUE, index); NS_RELEASE(listFrame); } // If we added the first option, we might need to select it. @@ -2083,60 +1645,6 @@ nsComboboxControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) } -NS_IMETHODIMP -nsComboboxControlFrame::CreateDisplayFrame(nsIPresContext* aPresContext) -{ - - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - 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 frame - nsCOMPtr styleContext; - rv = aPresContext->ResolvePseudoStyleContextFor(mContent, - 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(mContent, - nsHTMLAtoms::mozDisplayComboboxControlFrame, - styleContext, - PR_FALSE, - getter_AddRefs(textStyleContext)); - if (NS_FAILED(rv)) { return rv; } - if (!textStyleContext) { return NS_ERROR_NULL_POINTER; } - nsCOMPtr content(do_QueryInterface(mDisplayContent)); - mTextFrame->Init(aPresContext, content, mDisplayFrame, textStyleContext, nsnull); - mTextFrame->SetInitialChildList(aPresContext, nsnull, nsnull); - nsCOMPtr presShell; - rv = aPresContext->GetShell(getter_AddRefs(presShell)); - if (NS_FAILED(rv)) { return rv; } - if (!presShell) { return NS_ERROR_NULL_POINTER; } - nsCOMPtr frameManager; - rv = presShell->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); - - return NS_OK; -} - - NS_IMETHODIMP nsComboboxControlFrame::CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aChildList) @@ -2161,29 +1669,22 @@ nsComboboxControlFrame::CreateAnonymousContent(nsIPresContext* aPresContext, // create content used for display //nsIAtom* tag = NS_NewAtom("mozcombodisplay"); - // Add a child text content node for the label - nsCOMPtr labelContent; - nsresult result = NS_NewTextNode(getter_AddRefs(labelContent)); - nsAutoString value="X"; - if (NS_SUCCEEDED(result) && labelContent) { - // set the value of the text node - mDisplayContent = do_QueryInterface(labelContent); - mDisplayContent->SetText(value.GetUnicode(), value.Length(), PR_TRUE); + NS_NewHTMLInputElement(&mDisplayContent, nsHTMLAtoms::input); - nsIDocument* doc; - mContent->GetDocument(doc); - labelContent->SetDocument(doc, PR_FALSE); - NS_RELEASE(doc); - mContent->AppendChildTo(labelContent, PR_FALSE); + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, nsAutoString("button"), PR_FALSE); - // create button which drops the list down - result = NS_NewHTMLInputElement(&mButtonContent, nsHTMLAtoms::input); - //NS_ADDREF(mButtonContent); - if (NS_SUCCEEDED(result) && mButtonContent) { - mButtonContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, nsAutoString("button"), PR_FALSE); - aChildList.AppendElement(mButtonContent); - } - } + //XXX: Do not use nsHTMLAtoms::id use nsHTMLAtoms::kClass instead. There will end up being multiple + //ids set to the same value which is illegal. + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, nsAutoString("-moz-display"), PR_FALSE); + // This is + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, nsAutoString("X"), PR_TRUE); + aChildList.AppendElement(mDisplayContent); + + // create button which drops the list down + NS_NewHTMLInputElement(&mButtonContent, nsHTMLAtoms::input); + //NS_ADDREF(mButtonContent); + mButtonContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, nsAutoString("button"), PR_FALSE); + aChildList.AppendElement(mButtonContent); return NS_OK; } @@ -2201,22 +1702,6 @@ nsComboboxControlFrame::Destroy(nsIPresContext* aPresContext) { // Cleanup frames in popup child list mPopupFrames.DestroyFrames(aPresContext); - if (mDisplayFrame) { - mFrameConstructor->RemoveMappingsForFrameSubtree(aPresContext, mDisplayFrame, nsnull); - mDisplayFrame->Destroy(aPresContext); - mDisplayFrame=nsnull; - } - - if (mDisplayContent) { - nsCOMPtr content(do_QueryInterface(mDisplayContent)); - if (content) { - PRInt32 index; - if (NS_SUCCEEDED(mContent->IndexOf(content, index))) { - mContent->RemoveChildAt(index, PR_FALSE); - } - } - } - return nsAreaFrame::Destroy(aPresContext); } @@ -2244,7 +1729,7 @@ nsComboboxControlFrame::SetInitialChildList(nsIPresContext* aPresContext, mPopupFrames.SetFrames(aChildList); } else { rv = nsAreaFrame::SetInitialChildList(aPresContext, aListName, aChildList); - InitTextStr(aPresContext, PR_FALSE); + InitTextStr(aPresContext, PR_TRUE); } return rv; } @@ -2333,39 +1818,3 @@ nsComboboxControlFrame::RestoreState(nsIPresContext* aPresContext, nsIPresState* return mListControlFrame->RestoreStateInternal(aPresContext, aState); } - -NS_METHOD -nsComboboxControlFrame::Paint(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) -{ -#ifdef NOISY - printf("%p paint layer %d at (%d, %d, %d, %d)\n", this, aWhichLayer, - aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height); -#endif - nsAreaFrame::Paint(aPresContext,aRenderingContext,aDirtyRect,aWhichLayer); - - if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { - nsRect rect(0, 0, mRect.width, mRect.height); - if (mDisplayFrame) { - aRenderingContext.PushState(); - PRBool clipEmpty; - nsRect clipRect; - mDisplayFrame->GetRect(clipRect); - aRenderingContext.SetClipRect(clipRect, nsClipCombine_kReplace, clipEmpty); - PaintChild(aPresContext, aRenderingContext, aDirtyRect, - mDisplayFrame, NS_FRAME_PAINT_LAYER_BACKGROUND); - PaintChild(aPresContext, aRenderingContext, aDirtyRect, - mDisplayFrame, NS_FRAME_PAINT_LAYER_FOREGROUND); - 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/mozilla/layout/forms/nsComboboxControlFrame.h b/mozilla/layout/forms/nsComboboxControlFrame.h index 69f4edfc955..1813dab4fe5 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.h +++ b/mozilla/layout/forms/nsComboboxControlFrame.h @@ -23,17 +23,7 @@ #ifndef nsComboboxControlFrame_h___ #define nsComboboxControlFrame_h___ -#ifdef DEBUG_evaughan -//#define DEBUG_rods -#endif - -#ifdef DEBUG_rods -//#define DO_REFLOW_DEBUG -//#define DO_REFLOW_COUNTER -//#define DO_UNCONSTRAINED_CHECK -//#define DO_PIXELS -//#define DO_NEW_REFLOW -#endif +#define OPTIMIZE_RESIZE_RELOW #include "nsAreaFrame.h" #include "nsIFormControlFrame.h" @@ -44,8 +34,6 @@ #include "nsIStatefulFrame.h" #include "nsIRollupListener.h" #include "nsIPresState.h" -#include "nsCSSFrameConstructor.h" -#include "nsITextContent.h" class nsFormFrame; class nsIView; @@ -96,10 +84,6 @@ public: nsGUIEvent* aEvent, nsEventStatus* aEventStatus); - NS_IMETHOD Paint(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); #ifdef NS_DEBUG NS_IMETHOD GetFrameName(nsString& aResult) const; #endif @@ -160,6 +144,8 @@ public: NS_IMETHOD UpdateSelection(PRBool aDoDispatchEvent, PRBool aForceUpdate, PRInt32 aNewIndex); NS_IMETHOD AbsolutelyPositionDropDown(); NS_IMETHOD GetAbsoluteRect(nsRect* aRect); + NS_IMETHOD SetFrameConstructor(nsCSSFrameConstructor *aConstructor) + { return NS_OK;} // not owner - do not addref! // nsISelectControlFrame NS_IMETHOD AddOption(nsIPresContext* aPresContext, PRInt32 index); @@ -176,17 +162,8 @@ public: //nsIRollupListener NS_IMETHOD Rollup(); - NS_IMETHOD SetFrameConstructor(nsCSSFrameConstructor *aConstructor) - { mFrameConstructor = aConstructor; return NS_OK;} // not owner - do not addref! protected: - NS_IMETHOD CreateDisplayFrame(nsIPresContext* aPresContext); - -#ifdef DO_NEW_REFLOW - NS_IMETHOD ReflowItems(nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - nsHTMLReflowMetrics& aDesiredSize); -#endif // nsHTMLContainerFrame virtual PRIntn GetSkipSides() const; @@ -210,6 +187,7 @@ public: nsIFrame *aFrame, nsRect& aAbsoluteTwipsRect, nsRect& aAbsolutePixelRect); + nsIFrame* GetDisplayFrame(nsIPresContext* aPresContext); protected: void ShowPopup(PRBool aShowPopup); void ShowList(nsIPresContext* aPresContext, PRBool aShowList); @@ -221,32 +199,19 @@ protected: NS_IMETHOD ToggleList(nsIPresContext* aPresContext); NS_IMETHOD MakeSureSomethingIsSelected(nsIPresContext* aPresContext); // Default to option 0 - void ReflowCombobox(nsIPresContext * aPresContext, - const nsHTMLReflowState& aReflowState, - nsHTMLReflowMetrics& aDesiredSize, - nsReflowStatus& aStatus, - nsIFrame * aDisplayFrame, - nsIFrame * aDropDownBtn, - nscoord& aDisplayWidth, - nscoord aBtnWidth, - const nsMargin& aBorderPadding, - nscoord aFallBackHgt = -1, - PRBool aCheckHeight = PR_FALSE); - - nsFrameList mPopupFrames; // additional named child list - nsIPresContext* mPresContext; // XXX: Remove the need to cache the pres context. - nsFormFrame* mFormFrame; // Parent Form Frame - nsString mTextStr; // Current Combo box selection - PRInt32 mSelectedIndex; // current selected index - nsCOMPtr mDisplayContent; // Anonymous content used to display the current selection - nsIHTMLContent* mButtonContent; // Anonymous content used to popup the dropdown list - PRBool mDroppedDown; // Current state of the dropdown list, PR_TRUE is dropped down - nsIFrame* mDisplayFrame; // frame to display selection - nsIFrame* mButtonFrame; // button frame - nsIFrame* mDropdownFrame; // dropdown list frame - nsIFrame* mTextFrame; // display area frame - nsIListControlFrame * mListControlFrame; // ListControl Interface for the dropdown frame - PRBool mIgnoreFocus; // Tells the combo to ignore all focus notifications + nsFrameList mPopupFrames; // additional named child list + nsIPresContext* mPresContext; // XXX: Remove the need to cache the pres context. + nsFormFrame* mFormFrame; // Parent Form Frame + nsString mTextStr; // Current Combo box selection + PRInt32 mSelectedIndex; // current selected index + nsIHTMLContent* mDisplayContent; // Anonymous content used to display the current selection + nsIHTMLContent* mButtonContent; // Anonymous content used to popup the dropdown list + PRBool mDroppedDown; // Current state of the dropdown list, PR_TRUE is dropped down + nsIFrame* mDisplayFrame; // frame to display selection + nsIFrame* mButtonFrame; // button frame + nsIFrame* mDropdownFrame; // dropdown list frame + nsIListControlFrame * mListControlFrame; // ListControl Interface for the dropdown frame + PRBool mIgnoreFocus; // Tells the combo to ignore all focus notifications nsCOMPtr mPresState; // Need cache state when list is null @@ -254,18 +219,6 @@ protected: // Resize Reflow Optimization nsSize mCacheSize; nsSize mCachedMaxElementSize; - nsSize mCachedAvailableSize; - - nsSize mCachedUncDropdownSize; - nsSize mCachedUncComboSize; - - nscoord mItemDisplayWidth; - //nscoord mItemDisplayHeight; - nsCSSFrameConstructor* mFrameConstructor; - -#ifdef DO_REFLOW_COUNTER - PRInt32 mReflowId; -#endif private: NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } diff --git a/mozilla/layout/forms/nsListControlFrame.cpp b/mozilla/layout/forms/nsListControlFrame.cpp index 02501cfe657..7866ab948a7 100644 --- a/mozilla/layout/forms/nsListControlFrame.cpp +++ b/mozilla/layout/forms/nsListControlFrame.cpp @@ -381,7 +381,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, PRBool bailOnHeight; // This ifdef is for turning off the optimization // so we can check timings against the old version -#if 1 +#if 0 nsFormControlFrame::SkipResizeReflow(mCacheSize, mCachedMaxElementSize, diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp index b56db0d06ce..56dedbe5143 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp @@ -22,7 +22,6 @@ */ #include "nsCOMPtr.h" #include "nsComboboxControlFrame.h" -#include "nsIFrameManager.h" #include "nsFormFrame.h" #include "nsFormControlFrame.h" #include "nsIHTMLContent.h" @@ -33,11 +32,11 @@ #include "nsINameSpaceManager.h" #include "nsLayoutAtoms.h" #include "nsIDOMElement.h" +#include "nsListControlFrame.h" #include "nsIListControlFrame.h" #include "nsIDOMHTMLCollection.h" #include "nsIDOMHTMLSelectElement.h" #include "nsIDOMHTMLOptionElement.h" -#include "nsIDOMNSHTMLOptionCollection.h" #include "nsIPresShell.h" #include "nsIPresState.h" #include "nsISupportsArray.h" @@ -52,16 +51,6 @@ #include "nsISelectControlFrame.h" #include "nsISupportsPrimitives.h" #include "nsIComponentManager.h" -#include "nsIDOMMouseListener.h" -#include "nsITextContent.h" -#include "nsTextFragment.h" -#include "nsCSSFrameConstructor.h" -#include "nsIDocument.h" - -#ifdef DO_NEW_REFLOW -#include "nsIFontMetrics.h" -#endif - static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); static NS_DEFINE_IID(kIComboboxControlFrameIID, NS_ICOMBOBOXCONTROLFRAME_IID); @@ -73,7 +62,8 @@ static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID); static NS_DEFINE_IID(kIPrivateDOMEventIID, NS_IPRIVATEDOMEVENT_IID); // Drop down list event management. -// The combo box uses the following strategy for managing the drop-down list. +// The combo box uses the following strategy for managing the +// drop-down list. // If the combo box or it's arrow button is clicked on the drop-down list is displayed // If mouse exit's the combo box with the drop-down list displayed the drop-down list // is asked to capture events @@ -88,8 +78,6 @@ static NS_DEFINE_IID(kIPrivateDOMEventIID, NS_IPRIVATEDOMEVENT_IID); const char * kMozDropdownActive = "-moz-dropdown-active"; -const PRInt32 kSizeNotSet = -1; - nsresult NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aStateFlags) { @@ -110,113 +98,6 @@ NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUin return NS_OK; } -//----------------------------------------------------------- -// Reflow Debugging Macros -// These let us "see" how many reflow counts are happening -//----------------------------------------------------------- -#ifdef DO_REFLOW_COUNTER - -#define MAX_REFLOW_CNT 1024 -static PRInt32 gTotalReqs = 0;; -static PRInt32 gTotalReflows = 0;; -static PRInt32 gReflowControlCntRQ[MAX_REFLOW_CNT]; -static PRInt32 gReflowControlCnt[MAX_REFLOW_CNT]; -static PRInt32 gReflowInx = -1; - -#define REFLOW_COUNTER() \ - if (mReflowId > -1) \ - gReflowControlCnt[mReflowId]++; - -#define REFLOW_COUNTER_REQUEST() \ - if (mReflowId > -1) \ - gReflowControlCntRQ[mReflowId]++; - -#define REFLOW_COUNTER_DUMP(__desc) \ - if (mReflowId > -1) {\ - gTotalReqs += gReflowControlCntRQ[mReflowId];\ - gTotalReflows += gReflowControlCnt[mReflowId];\ - printf("** Id:%5d %s RF: %d RQ: %d %d/%d %5.2f\n", \ - mReflowId, (__desc), \ - gReflowControlCnt[mReflowId], \ - gReflowControlCntRQ[mReflowId],\ - gTotalReflows, gTotalReqs, float(gTotalReflows)/float(gTotalReqs)*100.0f);\ - } - -#define REFLOW_COUNTER_INIT() \ - if (gReflowInx < MAX_REFLOW_CNT) { \ - gReflowInx++; \ - mReflowId = gReflowInx; \ - gReflowControlCnt[mReflowId] = 0; \ - gReflowControlCntRQ[mReflowId] = 0; \ - } else { \ - mReflowId = -1; \ - } - -// reflow messages -#define REFLOW_DEBUG_MSG(_msg1) printf((_msg1)) -#define REFLOW_DEBUG_MSG2(_msg1, _msg2) printf((_msg1), (_msg2)) -#define REFLOW_DEBUG_MSG3(_msg1, _msg2, _msg3) printf((_msg1), (_msg2), (_msg3)) -#define REFLOW_DEBUG_MSG4(_msg1, _msg2, _msg3, _msg4) printf((_msg1), (_msg2), (_msg3), (_msg4)) - -#else //------------- - -#define REFLOW_COUNTER_REQUEST() -#define REFLOW_COUNTER() -#define REFLOW_COUNTER_DUMP(__desc) -#define REFLOW_COUNTER_INIT() - -#define REFLOW_DEBUG_MSG(_msg) -#define REFLOW_DEBUG_MSG2(_msg1, _msg2) -#define REFLOW_DEBUG_MSG3(_msg1, _msg2, _msg3) -#define REFLOW_DEBUG_MSG4(_msg1, _msg2, _msg3, _msg4) - - -#endif - -//------------------------------------------ -// This is for being VERY noisy -//------------------------------------------ -#ifdef DO_VERY_NOISY -#define REFLOW_NOISY_MSG(_msg1) printf((_msg1)) -#define REFLOW_NOISY_MSG2(_msg1, _msg2) printf((_msg1), (_msg2)) -#define REFLOW_NOISY_MSG3(_msg1, _msg2, _msg3) printf((_msg1), (_msg2), (_msg3)) -#define REFLOW_NOISY_MSG4(_msg1, _msg2, _msg3, _msg4) printf((_msg1), (_msg2), (_msg3), (_msg4)) -#else -#define REFLOW_NOISY_MSG(_msg) -#define REFLOW_NOISY_MSG2(_msg1, _msg2) -#define REFLOW_NOISY_MSG3(_msg1, _msg2, _msg3) -#define REFLOW_NOISY_MSG4(_msg1, _msg2, _msg3, _msg4) -#endif - -//------------------------------------------ -// Displays value in pixels or twips -//------------------------------------------ -#ifdef DO_PIXELS -#define PX(__v) __v / 15 -#else -#define PX(__v) __v -#endif - -//------------------------------------------ -// Asserts if we return a desired size that -// doesn't correctly match the mComputedWidth -//------------------------------------------ -#ifdef DO_UNCONSTRAINED_CHECK -#define UNCONSTRAINED_CHECK() \ -if (aReflowState.mComputedWidth != NS_UNCONSTRAINEDSIZE) { \ - nscoord width = aDesiredSize.width - borderPadding.left - borderPadding.right; \ - if (width != aReflowState.mComputedWidth) { \ - printf("aDesiredSize.width %d %d != aReflowState.mComputedWidth %d\n", aDesiredSize.width, width, aReflowState.mComputedWidth); \ - } \ - NS_ASSERTION(width == aReflowState.mComputedWidth, "Returning bad value when constrained!"); \ -} -#else -#define UNCONSTRAINED_CHECK() -#endif -//------------------------------------------------------ -//-- Done with macros -//------------------------------------------------------ - nsComboboxControlFrame::nsComboboxControlFrame() : nsAreaFrame() { @@ -224,6 +105,7 @@ nsComboboxControlFrame::nsComboboxControlFrame() mFormFrame = nsnull; mListControlFrame = nsnull; mTextStr = ""; + mDisplayContent = nsnull; mButtonContent = nsnull; mDroppedDown = PR_FALSE; mDisplayFrame = nsnull; @@ -232,33 +114,23 @@ nsComboboxControlFrame::nsComboboxControlFrame() mIgnoreFocus = PR_FALSE; mSelectedIndex = -1; - mCacheSize.width = kSizeNotSet; - mCacheSize.height = kSizeNotSet; - mCachedMaxElementSize.width = kSizeNotSet; - mCachedMaxElementSize.height = kSizeNotSet; - mCachedAvailableSize.width = kSizeNotSet; - mCachedAvailableSize.height = kSizeNotSet; - mCachedUncDropdownSize.width = kSizeNotSet; - mCachedUncDropdownSize.height = kSizeNotSet; - mCachedUncComboSize.width = kSizeNotSet; - mCachedUncComboSize.height = kSizeNotSet; - mItemDisplayWidth = 0; + mCacheSize.width = -1; + mCacheSize.height = -1; + mCachedMaxElementSize.width = -1; + mCachedMaxElementSize.height = -1; //Shrink the area around it's contents //SetFlags(NS_BLOCK_SHRINK_WRAP); - - REFLOW_COUNTER_INIT() } //-------------------------------------------------------------- nsComboboxControlFrame::~nsComboboxControlFrame() { - REFLOW_COUNTER_DUMP("nsCCF"); - if (mFormFrame) { mFormFrame->RemoveFormControlFrame(*this); mFormFrame = nsnull; } NS_IF_RELEASE(mPresContext); + NS_IF_RELEASE(mDisplayContent); NS_IF_RELEASE(mButtonContent); nsFormControlFrame::RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); @@ -339,9 +211,8 @@ nsComboboxControlFrame::MakeSureSomethingIsSelected(nsIPresContext* aPresContext // Set listbox selection to first item in the list box rv = fcFrame->SetProperty(aPresContext, nsHTMLAtoms::selectedindex, "0"); mSelectedIndex = 0; - } else { - UpdateSelection(PR_FALSE, PR_TRUE, mSelectedIndex); // Needed to reflow when removing last option } + UpdateSelection(PR_FALSE, PR_TRUE, mSelectedIndex); // Needed to reflow when removing last option } // Don't NS_RELEASE fcFrame here as it isn't addRef'd in the QI (???) @@ -360,7 +231,9 @@ nsComboboxControlFrame::InitTextStr(nsIPresContext* aPresContext, PRBool aUpdate mListControlFrame->GetSelectedItem(mTextStr); // Update the display by setting the value attribute - mDisplayContent->SetText(mTextStr.GetUnicode(), mTextStr.Length(), aUpdate); + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, mTextStr, aUpdate); + //nsIFrame* buttonFrame = GetDisplayFrame(aPresContext); + //nsFormControlHelper::ForceDrawFrame(buttonFrame); } //-------------------------------------------------------------- @@ -554,12 +427,12 @@ nsComboboxControlFrame::MouseClicked(nsIPresContext* aPresContext) nsresult nsComboboxControlFrame::ReflowComboChildFrame(nsIFrame* aFrame, - nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nscoord aAvailableWidth, - nscoord aAvailableHeight) + nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus, + nscoord aAvailableWidth, + nscoord aAvailableHeight) { // Constrain the child's width and height to aAvailableWidth and aAvailableHeight nsSize availSize(aAvailableWidth, aAvailableHeight); @@ -617,6 +490,17 @@ nsComboboxControlFrame::GetButtonFrame(nsIPresContext* aPresContext) return mButtonFrame; } +nsIFrame* +nsComboboxControlFrame::GetDisplayFrame(nsIPresContext* aPresContext) +{ + if (mDisplayFrame == nsnull) { + NS_ASSERTION(mDisplayContent != nsnull, "nsComboboxControlFrame mDisplayContent is null"); + GetPrimaryComboFrame(aPresContext, mDisplayContent, &mDisplayFrame); + } + + return mDisplayFrame; +} + nsIFrame* nsComboboxControlFrame::GetDropdownFrame() { @@ -694,10 +578,12 @@ nsComboboxControlFrame::PositionDropdown(nsIPresContext* aPresContext, nsRect currentRect; dropdownFrame->GetRect(currentRect); - dropdownFrame->SetRect(aPresContext, dropdownRect); + //if (currentRect != dropdownRect) { + dropdownFrame->SetRect(aPresContext, dropdownRect); #ifdef DEBUG_rodsXXXXXX - printf("%d Position Dropdown at: %d %d %d %d\n", counter++, dropdownRect.x, dropdownRect.y, dropdownRect.width, dropdownRect.height); + printf("%d Position Dropdown at: %d %d %d %d\n", counter++, dropdownRect.x, dropdownRect.y, dropdownRect.width, dropdownRect.height); #endif + //} return rv; } @@ -781,435 +667,55 @@ nsComboboxControlFrame::GetAbsoluteFramePosition(nsIPresContext* aPresContext, return rv; } -//////////////////////////////////////////////////////////////// -// Experimental Reflow -//////////////////////////////////////////////////////////////// -#if defined(DO_NEW_REFLOW) || defined(DO_REFLOW_COUNTER) -//--------------------------------------------------------- -// Returns the nsIDOMHTMLOptionElement for a given index -// in the select's collection -//--------------------------------------------------------- -static nsIDOMHTMLOptionElement* -GetOption(nsIDOMHTMLCollection& aCollection, PRInt32 aIndex) -{ - nsIDOMNode* node = nsnull; - if (NS_SUCCEEDED(aCollection.Item(aIndex, &node))) { - if (nsnull != node) { - nsIDOMHTMLOptionElement* option = nsnull; - node->QueryInterface(NS_GET_IID(nsIDOMHTMLOptionElement), (void**)&option); - NS_RELEASE(node); - return option; - } - } - return nsnull; -} -//--------------------------------------------------------- -// for a given piece of content it returns nsIDOMHTMLSelectElement object -// or null -//--------------------------------------------------------- -static nsIDOMHTMLSelectElement* -GetSelect(nsIContent * aContent) -{ - nsIDOMHTMLSelectElement* selectElement = nsnull; - nsresult result = aContent->QueryInterface(NS_GET_IID(nsIDOMHTMLSelectElement), - (void**)&selectElement); - if (NS_SUCCEEDED(result) && selectElement) { - return selectElement; - } else { - return nsnull; - } -} -//--------------------------------------------------------- -//--------------------------------------------------------- -// This returns the collection for nsIDOMHTMLSelectElement or -// the nsIContent object is the select is null (AddRefs) -//--------------------------------------------------------- -static nsIDOMHTMLCollection* -GetOptions(nsIContent * aContent, nsIDOMHTMLSelectElement* aSelect = nsnull) -{ - nsIDOMNSHTMLOptionCollection* optCol = nsnull; - nsIDOMHTMLCollection* options = nsnull; - if (!aSelect) { - nsCOMPtr selectElement = getter_AddRefs(GetSelect(aContent)); - if (selectElement) { - selectElement->GetOptions(&optCol); // AddRefs (1) - } - } else { - aSelect->GetOptions(&optCol); // AddRefs (1) - } - if (optCol) { - nsresult res = optCol->QueryInterface(NS_GET_IID(nsIDOMHTMLCollection), (void **)&options); // AddRefs (2) - NS_RELEASE(optCol); // Release (1) - } - return options; -} +//------------------------------------------------------------------------------- +//------------------------------------------------------------------------------- +// Old/Current Way of Doing Reflow +//------------------------------------------------------------------------------- +//------------------------------------------------------------------------------- +#define DO_OLD_REFLOW -#ifdef DO_NEW_REFLOW -NS_IMETHODIMP -nsComboboxControlFrame::ReflowItems(nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - nsHTMLReflowMetrics& aDesiredSize) -{ - //printf("*****************\n"); - const nsStyleFont* dspFont; - mDisplayFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)dspFont); - nsCOMPtr deviceContext; - aPresContext->GetDeviceContext(getter_AddRefs(deviceContext)); - NS_ASSERTION(deviceContext, "Couldn't get the device context"); - nsIFontMetrics * fontMet; - deviceContext->GetMetricsFor(dspFont->mFont, fontMet); +#ifdef DO_OLD_REFLOW - nscoord visibleHeight; - //nsCOMPtr fontMet; - //nsresult res = nsFormControlHelper::GetFrameFontFM(aPresContext, this, getter_AddRefs(fontMet)); - if (fontMet) { - fontMet->GetHeight(visibleHeight); - } - - nsAutoString maxStr; - nscoord maxWidth = 0; - //nsIRenderingContext * rc = aReflowState.rendContext; - 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)) { - nscoord width; - aReflowState.rendContext->GetWidth(text, width); - if (width > maxWidth) { - maxStr = text; - maxWidth = width; - } - //maxWidth = PR_MAX(width, maxWidth); - //printf("[%d] - %d %s \n", i, width, text.ToNewCString()); - } - } - } - } - } - if (maxWidth == 0) { - maxWidth = 11 * 15; - } - char * str = maxStr.ToNewCString(); - printf("id: %d maxWidth %d [%s]\n", mReflowId, maxWidth, str); - delete [] str; - - // get the borderPadding for the display area - const nsStyleSpacing* dspSpacing; - mDisplayFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dspSpacing); - nsMargin dspBorderPadding; - dspBorderPadding.SizeTo(0, 0, 0, 0); - dspSpacing->CalcBorderPaddingFor(mDisplayFrame, dspBorderPadding); - - nscoord frmWidth = maxWidth+dspBorderPadding.left+dspBorderPadding.right+ - aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; - nscoord frmHeight = visibleHeight+dspBorderPadding.top+dspBorderPadding.bottom+ - aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; - -#if 1 - aDesiredSize.width = frmWidth; - aDesiredSize.height = frmHeight; -#else - printf("Size %d,%d %d,%d %d,%d %d,%d\n", - frmWidth, frmHeight, - aDesiredSize.width, aDesiredSize.height, - frmWidth-aDesiredSize.width, frmHeight-aDesiredSize.height, - (frmWidth-aDesiredSize.width)/15, (frmHeight-aDesiredSize.height)/15); -#endif - NS_RELEASE(fontMet); - return NS_OK; -} -#endif - -#endif - -//------------------------------------------------------------------ -// This Method reflow just the contents of the ComboBox -// The contents are a Block frame containing a Text Frame - This is the display area -// and then the GfxButton - The dropdown button -//-------------------------------------------------------------------------- -void -nsComboboxControlFrame::ReflowCombobox(nsIPresContext * aPresContext, - const nsHTMLReflowState& aReflowState, - nsHTMLReflowMetrics& aDesiredSize, - nsReflowStatus& aStatus, - nsIFrame * aDisplayFrame, - nsIFrame * aDropDownBtn, - nscoord& aDisplayWidth, - nscoord aBtnWidth, - const nsMargin& aBorderPadding, - nscoord aFallBackHgt, - PRBool aCheckHeight) -{ - // start out by using the cached height - // XXX later this will change when we better handle constrained height - nscoord dispHeight = mCacheSize.height - aBorderPadding.top - aBorderPadding.bottom; - nscoord dispWidth = aDisplayWidth; - - REFLOW_NOISY_MSG3("+++1 AdjustCombo DW:%d DH:%d ", PX(dispWidth), PX(dispHeight)); - REFLOW_NOISY_MSG3("BW:%d BH:%d ", PX(aBtnWidth), PX(dispHeight)); - REFLOW_NOISY_MSG3("mCacheSize.height:%d - %d\n", PX(mCacheSize.height), PX((aBorderPadding.top + aBorderPadding.bottom))); - - // get the border and padding for the DisplayArea (block frame & textframe) - const nsStyleSpacing* dspSpacing; - aDisplayFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dspSpacing); - nsMargin dspBorderPadding; - dspBorderPadding.SizeTo(0, 0, 0, 0); - dspSpacing->CalcBorderPaddingFor(aDisplayFrame, dspBorderPadding); - - // adjust the height - if (mCacheSize.height == kSizeNotSet) { - if (aFallBackHgt == kSizeNotSet) { - NS_ASSERTION(aFallBackHgt != kSizeNotSet, "Fallback can't be kSizeNotSet when mCacheSize.height == kSizeNotSet"); - } else { - dispHeight = aFallBackHgt; - REFLOW_NOISY_MSG2("+++3 Adding (dspBorderPadding.top + dspBorderPadding.bottom): %d\n", (dspBorderPadding.top + dspBorderPadding.bottom)); - dispHeight += (dspBorderPadding.top + dspBorderPadding.bottom); - } - } - - //////////////////////////////////////////////////////////////////////////// - // XXX - This is really bad, but at the moment I am NOT adding in the left padding - // we need to be able to find out what the left padding is on an option - // and subtract that out before we can add in our padding. - REFLOW_NOISY_MSG2("+++3 Adding: %d\n", dspBorderPadding.right); - dispWidth += dspBorderPadding.left + dspBorderPadding.right; - - REFLOW_NOISY_MSG3("+++2 AdjustCombo DW:%d DH:%d ", PX(dispWidth), PX(dispHeight)); - REFLOW_NOISY_MSG3(" BW:%d BH:%d\n", PX(aBtnWidth), PX(dispHeight)); - - // This sets the button to be a specific size - // so no matter what it reflows at these values - SetChildFrameSize(aDropDownBtn, aBtnWidth, dispHeight); - - // now that we know what the overall display width & height will be - // set up a new reflow state and reflow the area frame at that size - nsSize availSize(dispWidth + aBorderPadding.left + aBorderPadding.right, - dispHeight + aBorderPadding.top + aBorderPadding.bottom); - nsHTMLReflowState kidReflowState(aPresContext, aReflowState, this, availSize); - kidReflowState.mComputedWidth = dispWidth; - kidReflowState.mComputedHeight = dispHeight; - - // do reflow - nsAreaFrame::Reflow(aPresContext, aDesiredSize, kidReflowState, aStatus); - - ///////////////////////////////////////////////////////// - // The DisplayFrame is a Block frame containing a TextFrame - // and it is completely anonymous, so we must manually reflow it - nsSize txtAvailSize(dispWidth - aBtnWidth, dispHeight); - nsHTMLReflowMetrics txtKidSize(&txtAvailSize); - nsHTMLReflowState txtKidReflowState(aPresContext, aReflowState, aDisplayFrame, txtAvailSize); - - aDisplayFrame->WillReflow(aPresContext); - aDisplayFrame->MoveTo(aPresContext, aBorderPadding.left, aBorderPadding.top); - nsIView* view; - aDisplayFrame->GetView(aPresContext, &view); - if (view) { - nsAreaFrame::PositionFrameView(aPresContext, aDisplayFrame, view); - } - nsReflowStatus status; - nsresult rv = aDisplayFrame->Reflow(aPresContext, txtKidSize, txtKidReflowState, status); - - ///////////////////////////////////////////////////////// - // If we are Constrained then the AreaFrame Reflow is the correct size - // if we are unconstrained then - //if (aReflowState.mComputedWidth == NS_UNCONSTRAINEDSIZE) { - // aDesiredSize.width += txtKidSize.width; - //} - - // Apparently, XUL lays out differently than HTML - // (the code above works for HTML and not XUL), - // so instead of using the above calculation - // I just set it to what it should be. - aDesiredSize.width = availSize.width; - //aDesiredSize.height = availSize.height; - - // now we need to adjust layout, because the AreaFrame - // doesn't position things exactly where we want them - nscoord insideWidth = dispWidth; - nscoord insideHeight = aDesiredSize.height - aBorderPadding.top - aBorderPadding.bottom; - - // the gets for the Display "block" frame and for the button - // make adjustments - nsRect buttonRect; - nsRect displayRect; - aDisplayFrame->GetRect(displayRect); - aDropDownBtn->GetRect(buttonRect); - // 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.height = insideHeight; - displayRect.width = dispWidth - aBtnWidth; - aDisplayFrame->SetRect(aPresContext, displayRect); - x += displayRect.width; - - // right justify the button - buttonRect.x = x; - buttonRect.y = aBorderPadding.top; - buttonRect.height = insideHeight; - buttonRect.width = aBtnWidth; - aDropDownBtn->SetRect(aPresContext, buttonRect); - - // since we have changed the height of the button - // make sure it has these new values - // XXX this may not be needed anymore - SetChildFrameSize(aDropDownBtn, aBtnWidth, aDesiredSize.height); - - - REFLOW_NOISY_MSG3("**AdjustCombobox - Reflow: WW: %d HH: %d\n", aDesiredSize.width, aDesiredSize.height); - - // Now cache the available height as our height without border and padding - // This sets up the optimization for if a new available width comes in and we are equal or - // less than it we can bail - if (aDesiredSize.width != mCacheSize.width || aDesiredSize.height != mCacheSize.height) { - if (aReflowState.availableWidth != NS_UNCONSTRAINEDSIZE) { - mCachedAvailableSize.width = aDesiredSize.width - (aBorderPadding.left + aBorderPadding.right); - } - if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) { - mCachedAvailableSize.height = aDesiredSize.height - (aBorderPadding.top + aBorderPadding.bottom); - } - nsFormControlFrame::SetupCachedSizes(mCacheSize, mCachedMaxElementSize, aDesiredSize); - } - - /////////////////////////////////////////////////////////////////// - // This is an experimental reflow that is turned off in the build -#ifdef DO_NEW_REFLOW_X - ReflowItems(aPresContext, aReflowState, aDesiredSize); -#endif - /////////////////////////////////////////////////////////////////// -} - -//---------------------------------------------------------- -// -//---------------------------------------------------------- -#ifdef DO_REFLOW_DEBUG +#ifdef DEBUG_rodsXXX static int myCounter = 0; - -static void printSize(char * aDesc, nscoord aSize) -{ - printf(" %s: ", aDesc); - if (aSize == NS_UNCONSTRAINEDSIZE) { - printf("UC"); - } else { - printf("%d", PX(aSize)); - } -} #endif -//------------------------------------------------------------------- -//-- Main Reflow for the Combobox -//------------------------------------------------------------------- NS_IMETHODIMP nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - aStatus = NS_FRAME_COMPLETE; - - REFLOW_COUNTER_REQUEST(); - -#ifdef DO_REFLOW_DEBUG - printf("-------------Starting Combobox Reflow ----------------------------\n"); - printf("%p ** Id: %d nsCCF::Reflow %d R: ", this, mReflowId, myCounter++); +#ifdef DEBUG_rodsXXX + printf("****** nsComboboxControlFrame::Reflow %d Reason: ", myCounter++); switch (aReflowState.reason) { case eReflowReason_Initial: - printf("Ini");break; + printf("eReflowReason_Initial\n");break; case eReflowReason_Incremental: - printf("Inc");break; + printf("eReflowReason_Incremental\n");break; case eReflowReason_Resize: - printf("Rsz");break; - case eReflowReason_StyleChange: - printf("Sty");break; - case eReflowReason_Dirty: - printf("Drt "); + printf("eReflowReason_Resize\n"); break; - default:printf("%d", aReflowState.reason);break; + case eReflowReason_StyleChange:printf("eReflowReason_StyleChange\n");break; } - - printSize("AW", aReflowState.availableWidth); - printSize("AH", aReflowState.availableHeight); - printSize("CW", aReflowState.mComputedWidth); - printSize("CH", aReflowState.mComputedHeight); - - nsCOMPtr optionsTemp = getter_AddRefs(GetOptions(mContent)); - PRUint32 numOptions; - optionsTemp->GetLength(&numOptions); - printSize("NO", (nscoord)numOptions); - - printf(" *\n"); - #endif - - PRBool bailOnWidth; - PRBool bailOnHeight; - - // Do initial check to see if we can bail out - // If it is an Initial or Incremental Reflow we never bail out here - // XXX right now we only bail if the width meets the criteria - // - // We bail: - // if mComputedWidth == NS_UNCONSTRAINEDSIZE and - // availableWidth == NS_UNCONSTRAINEDSIZE and - // we have cached an available size - // - // We bail: - // if mComputedWidth == NS_UNCONSTRAINEDSIZE and - // availableWidth != NS_UNCONSTRAINEDSIZE and - // availableWidth minus its border equals our cached available size - // - // We bail: - // if mComputedWidth != NS_UNCONSTRAINEDSIZE and - // cached availableSize.width == aReflowState.mComputedWidth and - // cached AvailableSize.width == aCacheSize.width - // - // NOTE: this returns whether we are doing an Incremental reflow - nsFormControlFrame::SkipResizeReflow(mCacheSize, - mCachedMaxElementSize, - mCachedAvailableSize, - aDesiredSize, aReflowState, - aStatus, - bailOnWidth, bailOnHeight); - if (bailOnWidth) { -#ifdef DO_REFLOW_DEBUG // check or size - const nsStyleSpacing* spacing; - GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); - nsMargin borderPadding; - borderPadding.SizeTo(0, 0, 0, 0); - spacing->CalcBorderPaddingFor(this, borderPadding); - UNCONSTRAINED_CHECK(); +#if 0 + nsresult skiprv = nsFormControlFrame::SkipResizeReflow(mCacheSize, mCachedMaxElementSize, aPresContext, + aDesiredSize, aReflowState, aStatus); + if (NS_SUCCEEDED(skiprv)) { + return skiprv; + } #endif - REFLOW_DEBUG_MSG3("^** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); - return NS_OK; - } - // add ourself to the form control - if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { - nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*,this)); - if (NS_FAILED(CreateDisplayFrame(aPresContext))) { - return NS_ERROR_FAILURE; - } - } - - // Go get all of the important frame nsresult rv = NS_OK; nsIFrame* buttonFrame = GetButtonFrame(aPresContext); + nsIFrame* displayFrame = GetDisplayFrame(aPresContext); nsIFrame* dropdownFrame = GetDropdownFrame(); // Don't try to do any special sizing and positioning unless all of the frames // have been created. - if ((nsnull == mDisplayFrame) || + if ((nsnull == displayFrame) || (nsnull == buttonFrame) || (nsnull == dropdownFrame)) { @@ -1222,9 +728,12 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, nsRect buttonRect; nsRect dropdownRect; - // get our border and padding, - // XXX - should be the same mComputedBorderPadding? - // maybe we should use that? + + if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); + nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*,this)); + } + const nsStyleSpacing* spacing; GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); nsMargin borderPadding; @@ -1232,11 +741,39 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, spacing->CalcBorderPaddingFor(this, borderPadding); // Get the current sizes of the combo box child frames - mDisplayFrame->GetRect(displayRect); + displayFrame->GetRect(displayRect); buttonFrame->GetRect(buttonRect); dropdownFrame->GetRect(dropdownRect); - // We should cache this instead getting it everytime + nsHTMLReflowState firstPassState(aReflowState); + + // Only reflow the display and button if they are the target of + // the incremental reflow, unless they change size. If they do + // then everything needs to be reflowed. + if (eReflowReason_Incremental == firstPassState.reason) { + nsIFrame* targetFrame; + firstPassState.reflowCommand->GetTarget(targetFrame); + if ((targetFrame == buttonFrame) || (targetFrame == displayFrame)) { + nsRect oldDisplayRect = displayRect; + nsRect oldButtonRect = buttonRect; + rv = nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + // nsAreaFrame::Reflow adds in the border and padding so we need to remove it + if (NS_UNCONSTRAINEDSIZE != firstPassState.mComputedWidth) { + aDesiredSize.width -= borderPadding.left + borderPadding.right; + } + displayFrame->GetRect(displayRect); + buttonFrame->GetRect(buttonRect); + if ((oldDisplayRect == displayRect) && (oldButtonRect == buttonRect)) { + aStatus = NS_FRAME_COMPLETE; + return rv; + } + } + nsIReflowCommand::ReflowType type; + aReflowState.reflowCommand->GetType(type); + firstPassState.reason = eReflowReason_StyleChange; + firstPassState.reflowCommand = nsnull; + } + // the default size of the of scrollbar // that will be the default width of the dropdown button // the height will be the height of the text @@ -1257,382 +794,105 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, float scale; dx->GetCanonicalPixelScale(scale); scrollbarWidth = NSIntPixelsToTwips(info.mSize, p2t*scale); - } - - // set up a new reflow state for use throughout - nsHTMLReflowState firstPassState(aReflowState); - nsHTMLReflowMetrics dropdownDesiredSize(nsnull); - - // Check to see if this a fully unconstrained reflow - PRBool fullyUnconstrained = firstPassState.availableWidth == NS_UNCONSTRAINEDSIZE && - firstPassState.mComputedWidth == NS_UNCONSTRAINEDSIZE && - firstPassState.availableHeight == NS_UNCONSTRAINEDSIZE && - firstPassState.mComputedHeight == NS_UNCONSTRAINEDSIZE; - - PRBool forceReflow = PR_FALSE; - - // Only reflow the display and button - // if they are the target of the incremental reflow, unless they change size. - if (eReflowReason_Incremental == aReflowState.reason) { - nsIFrame* targetFrame; - firstPassState.reflowCommand->GetTarget(targetFrame); - // Check to see if we are the target of the Incremental Reflow - if (targetFrame == this) { - // We need to check here to see if we can get away with just reflowing - // the combobox and not the dropdown - REFLOW_DEBUG_MSG("-----------------Target is Combobox------------\n"); - - // If the mComputedWidth matches our cached display width - // then we get away with bailing out - PRBool doFullReflow = firstPassState.mComputedWidth != NS_UNCONSTRAINEDSIZE && - firstPassState.mComputedWidth != mItemDisplayWidth; - if (!doFullReflow) { - // OK, so we got lucky and the size didn't change - // so do a simple reflow and bail out - REFLOW_DEBUG_MSG("------------Reflowing AreaFrame and bailing----\n\n"); - ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, - mDisplayFrame, buttonFrame, mItemDisplayWidth, - scrollbarWidth, borderPadding); - REFLOW_COUNTER(); - UNCONSTRAINED_CHECK(); - REFLOW_DEBUG_MSG3("&** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); - return rv; - } - // Nope, something changed that affected our size - // so we need to do a full reflow and resize ourself - REFLOW_DEBUG_MSG("------------Do Full Reflow----\n\n"); - firstPassState.reason = eReflowReason_StyleChange; - firstPassState.reflowCommand = nsnull; - forceReflow = PR_TRUE; - - } else { - // Now, see if our target is the dropdown - // If so, maybe an items was added or some style changed etc. - // OR - // We get an Incremental reflow on the dropdown when it is being - // shown or hidden. - if (targetFrame == dropdownFrame) { - REFLOW_DEBUG_MSG("---------Target is Dropdown (Clearing Unc DD Size)---\n"); - PRBool bail = PR_FALSE; - - // Let's start by checking to see if this is a reflow ro showing or hiding. - nsIView * view; - dropdownFrame->GetView(aPresContext, &view); - nsViewVisibility vis = nsViewVisibility_kHide; - NS_ASSERTION(view != nsnull, "The dropdown frame doesn't have a view!"); - if (view != nsnull) { - view->GetVisibility(vis); - } - // If the view is hidden, but the combobox thinks the it is dropped down - // 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 - 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); - - } 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); - // cache the values here also, - // since we just did an unconstrained reflow - mCachedUncDropdownSize.width = dropdownDesiredSize.width; - mCachedUncDropdownSize.height = dropdownDesiredSize.height; - REFLOW_DEBUG_MSG3("---2 Caching mCachedUncDropdownSize %d,%d\n", PX(mCachedUncDropdownSize.width), PX(mCachedUncDropdownSize.height)); - } - - // Ok, we get to bail because it was either being shown or hidden - if (bail) { - if (fullyUnconstrained) { - aDesiredSize.width = mCachedUncComboSize.width; - aDesiredSize.height = mCachedUncComboSize.height; - } else { - 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; - REFLOW_DEBUG_MSG3("|** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); - REFLOW_DEBUG_MSG("---- Setting Cached values and then bailing out\n\n"); - UNCONSTRAINED_CHECK(); - return NS_OK; - } - // Nope, we were unlucky so now we do a full reflow - mCachedUncDropdownSize.width = kSizeNotSet; - mCachedUncDropdownSize.height = kSizeNotSet; - REFLOW_DEBUG_MSG("---- Doing Full Reflow\n"); - // This is an incremental reflow targeted at the dropdown list - // and it didn't have anything to do with being show or hidden. - // - // The incremental reflow will not get to the dropdown list - // because it is in the "popup" list - // when this flow of control drops out of this if it will do a reflow - // on the AreaFrame which SHOULD make it get tothe drop down - // except that it is in the popup list, so we have it reflowed as - // a StyleChange, this is not as effecient as doing an Incremental - // - // At this point we want to by pass the reflow optimization in the dropdown - // because we aren't why it is getting an incremental reflow, but we do - // know that it needs to be resized or restyled - //mListControlFrame->SetOverrideReflowOptimization(PR_TRUE); - - } else if (targetFrame == mDisplayFrame || targetFrame == buttonFrame) { - /*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")); - REFLOW_DEBUG_MSG("---- Doing AreaFrame Reflow and then bailing out\n"); - // Do simple reflow and bail out - ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, - mDisplayFrame, buttonFrame, - mItemDisplayWidth, scrollbarWidth, borderPadding, kSizeNotSet, PR_TRUE); - REFLOW_DEBUG_MSG3("+** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); - REFLOW_COUNTER(); - UNCONSTRAINED_CHECK(); - return rv; - } else { - // 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"); - REFLOW_DEBUG_MSG("---- Doing Reflow as StyleChange\n"); - } - firstPassState.reason = eReflowReason_StyleChange; - firstPassState.reflowCommand = nsnull; - mListControlFrame->SetOverrideReflowOptimization(PR_TRUE); - forceReflow = PR_TRUE; - } - } - - // This ifdef is for the new approach to reflow - // where we don't reflow the dropdown - // we just figure out or width from the list of items - // - // This next section is the Current implementation - // the else contains the new reflow code -#ifndef DO_NEW_REFLOW - - // Here is another special optimization - // Only reflow the dropdown if it has never been reflowed unconstrained - // - // Or someone up above here may want to force it to be reflowed - // by setting one or both of these to kSizeNotSet - if ((mCachedUncDropdownSize.width == kSizeNotSet && - mCachedUncDropdownSize.height == kSizeNotSet) || forceReflow) { - REFLOW_DEBUG_MSG3("---Re %d,%d\n", PX(mCachedUncDropdownSize.width), PX(mCachedUncDropdownSize.height)); - // A width has not been specified for the select so size the display area - // to match the width of the longest item in the drop-down list. The dropdown - // list has already been reflowed and sized to shrink around its contents above. - ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, - aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); - if (forceReflow) { - mCachedUncDropdownSize.width = dropdownDesiredSize.width; - mCachedUncDropdownSize.height = dropdownDesiredSize.height; - } - } else { - // Here we pretended we did an unconstrained reflow - // so we set the cached values and continue on - REFLOW_DEBUG_MSG3("--- Using Cached ListBox Size %d,%d\n", PX(mCachedUncDropdownSize.width), PX(mCachedUncDropdownSize.height)); - dropdownDesiredSize.width = mCachedUncDropdownSize.width; - dropdownDesiredSize.height = mCachedUncDropdownSize.height; - } - - ///////////////////////////////////////////////////////////////////////// - // XXX - I need to clean this nect part up a little it is very redundant - - // Check here to if this is a mComputed unconstrained reflow - PRBool computedUnconstrained = firstPassState.mComputedWidth == NS_UNCONSTRAINEDSIZE && - firstPassState.mComputedHeight == NS_UNCONSTRAINEDSIZE; - if (computedUnconstrained && !forceReflow) { - // Because Incremental reflows aren't actually getting to the dropdown - // we cache the size from when it did a fully unconstrained reflow - // we then check to see if the size changed at all, - // if not then bail out we don't need to worry - if (mCachedUncDropdownSize.width == kSizeNotSet && mCachedUncDropdownSize.height == kSizeNotSet) { - mCachedUncDropdownSize.width = dropdownDesiredSize.width; - mCachedUncDropdownSize.height = dropdownDesiredSize.height; - REFLOW_DEBUG_MSG3("---1 Caching mCachedUncDropdownSize %d,%d\n", PX(mCachedUncDropdownSize.width), PX(mCachedUncDropdownSize.height)); - - } else if (mCachedUncDropdownSize.width == dropdownDesiredSize.width && - mCachedUncDropdownSize.height == dropdownDesiredSize.height) { - - if (mCachedUncComboSize.width != kSizeNotSet && mCachedUncComboSize.height != kSizeNotSet) { - REFLOW_DEBUG_MSG3("--- Bailing because of mCachedUncDropdownSize %d,%d\n\n", PX(mCachedUncDropdownSize.width), PX(mCachedUncDropdownSize.height)); - aDesiredSize.width = mCachedUncComboSize.width; - aDesiredSize.height = mCachedUncComboSize.height; - - if (aDesiredSize.maxElementSize != nsnull) { - aDesiredSize.maxElementSize->width = mCachedMaxElementSize.width; - aDesiredSize.maxElementSize->height = mCachedMaxElementSize.height; - } - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; - UNCONSTRAINED_CHECK(); - REFLOW_DEBUG_MSG3("#** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); - return NS_OK; - } - } else { - mCachedUncDropdownSize.width = dropdownDesiredSize.width; - mCachedUncDropdownSize.height = dropdownDesiredSize.height; - } - } - // clean up stops here - ///////////////////////////////////////////////////////////////////////// - - // So this point we know we flowed the dropdown unconstrained - // now we get to figure out how big we need to be and - // - // We don't reflow the combobox here at the new size - // we cache its new size and reflow it on the dropdown - nsSize size; - PRInt32 length = 0; - mListControlFrame->GetNumberOfOptions(&length); - - // dropdownRect will hold the content size (minus border padding) - // for the display area - dropdownFrame->GetRect(dropdownRect); - - // Get maximum size of the largest item in the dropdown - // The height of the display frame will be that height - // the width will be the same as - // the dropdown width (minus its borderPadding) OR - // a caculation off the mComputedWidth from reflow - mListControlFrame->GetMaximumSize(size); - - // the variable "size" will now be - // the default size of the dropdown btn - if (scrollbarWidth > 0) { - size.width = scrollbarWidth; - } - - // Get the border and padding for the dropdown - const nsStyleSpacing* dropSpacing; - dropdownFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dropSpacing); - nsMargin dropBorderPadding; - dropBorderPadding.SizeTo(0, 0, 0, 0); - dropSpacing->CalcBorderPaddingFor(dropdownFrame, dropBorderPadding); - - // get the borderPadding for the display area - const nsStyleSpacing* dspSpacing; - mDisplayFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dspSpacing); - nsMargin dspBorderPadding; - dspBorderPadding.SizeTo(0, 0, 0, 0); - dspSpacing->CalcBorderPaddingFor(mDisplayFrame, dspBorderPadding); - - // Substract dropdown's borderPadding from the width of the dropdown rect - // to get the size of the content area - // - // the height will come from the mDisplayFrame's height - // declare a size for the item display frame + } //Set the desired size for the button and display frame if (NS_UNCONSTRAINEDSIZE == firstPassState.mComputedWidth) { - REFLOW_DEBUG_MSG("Unconstrained.....\n"); - REFLOW_DEBUG_MSG4("*B mItemDisplayWidth %d dropdownRect.width:%d dropdownRect.w+h %d\n", PX(mItemDisplayWidth), PX(dropdownRect.width), PX((dropBorderPadding.left + dropBorderPadding.right))); + // A width has not been specified for the select so size the display area to + // match the width of the longest item in the drop-down list. The dropdown + // list has already been reflowed and sized to shrink around its contents above. - // Start with the dropdown rect's width - mItemDisplayWidth = dropdownRect.width; - - REFLOW_DEBUG_MSG2("* mItemDisplayWidth %d\n", PX(mItemDisplayWidth)); - - // subtract off the display's BorderPadding - mItemDisplayWidth -= dspBorderPadding.left + dspBorderPadding.right; - - REFLOW_DEBUG_MSG2("*A mItemDisplayWidth %d\n", PX(mItemDisplayWidth)); - - } else { - REFLOW_DEBUG_MSG("Constrained.....\n"); - if (firstPassState.mComputedWidth > 0) { - // Compute the display item's width from reflow's mComputedWidth - // mComputedWidth has already excluded border and padding - // so subtract off the button's size - REFLOW_DEBUG_MSG3("B mItemDisplayWidth %d %d\n", PX(mItemDisplayWidth), PX(dspBorderPadding.right)); - mItemDisplayWidth = firstPassState.mComputedWidth - dspBorderPadding.left - dspBorderPadding.right; - REFLOW_DEBUG_MSG2("A mItemDisplayWidth %d\n", PX(mItemDisplayWidth)); - REFLOW_DEBUG_MSG4("firstPassState.mComputedWidth %d - size.width %d dspBorderPadding.right %d\n", PX(firstPassState.mComputedWidth), PX(size.width), PX(dspBorderPadding.right)); + // Reflow the dropdown shrink-wrapped. + PRBool saveMES = aDesiredSize.maxElementSize != nsnull; + nsSize * maxElementSize = nsnull; + if (saveMES) { + maxElementSize = new nsSize(); + //maxElementSize = new nsSize(*aDesiredSize.maxElementSize); } - } - // this reflows and makes and last minute adjustments - ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, - mDisplayFrame, buttonFrame, mItemDisplayWidth, scrollbarWidth, - borderPadding, size.height); + nsHTMLReflowMetrics dropdownDesiredSize(maxElementSize); + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); - // The dropdown was reflowed UNCONSTRAINED before, now we need to check to see - // if it needs to be resized. - // - // Optimization - The style (font, etc.) maybe different for the display item - // than for any particular item in the dropdown. So, if the new size of combobox - // is smaller than the dropdown, that is OK, The dropdown MUST always be either the same - //size as the combo or larger if necessary -#if 0 - if (aDesiredSize.width > dropdownDesiredSize.width) { - if (eReflowReason_Initial == firstPassState.reason) { - firstPassState.reason = eReflowReason_Resize; + nsSize size; + PRInt32 length = 0; + mListControlFrame->GetNumberOfOptions(&length); + dropdownFrame->GetRect(dropdownRect); + + const nsStyleSpacing* dropSpacing; + dropdownFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dropSpacing); + nsMargin dropBorderPadding; + dropBorderPadding.SizeTo(0, 0, 0, 0); + dropSpacing->CalcBorderPaddingFor(dropdownFrame, dropBorderPadding); + dropdownRect.width -= (dropBorderPadding.left + dropBorderPadding.right); + + // Get maximum size and height of a option in the dropdown + mListControlFrame->GetMaximumSize(size); + + if (scrollbarWidth > 0) { + size.width = scrollbarWidth; } - REFLOW_DEBUG_MSG3("*** Reflowing ListBox to width: %d it was %d\n", PX(aDesiredSize.width), PX(dropdownDesiredSize.width)); + const nsStyleSpacing* dspSpacing; + displayFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dspSpacing); + nsMargin dspBorderPadding; + dspBorderPadding.SizeTo(0, 0, 0, 0); + dspSpacing->CalcBorderPaddingFor(displayFrame, dspBorderPadding); + + // Set width of display to match width of the drop down + SetChildFrameSize(displayFrame, dropdownRect.width-size.width+dspBorderPadding.left+dspBorderPadding.right, + size.height+dspBorderPadding.top+dspBorderPadding.bottom); + + // Size the button + SetChildFrameSize(buttonFrame, size.width, size.height); + + // Reflow display + button + nsAreaFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); + + displayFrame->GetRect(displayRect); + buttonFrame->GetRect(buttonRect); + buttonRect.y = displayRect.y; + buttonRect.height = displayRect.height; + buttonFrame->SetRect(aPresContext, buttonRect); + // Reflow the dropdown list to match the width of the display + button - ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, - aDesiredSize.width, NS_UNCONSTRAINEDSIZE); - } -#endif - -#else // DO_NEW_REFLOW - - if (mCacheSize.width == kSizeNotSet) { - ReflowItems(aPresContext, aReflowState, aDesiredSize); - } else { - aDesiredSize.width = mCacheSize.width; - aDesiredSize.height = mCacheSize.height; - } - - // get the borderPadding for the display area - const nsStyleSpacing* dspSpacing; - mDisplayFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dspSpacing); - nsMargin dspBorderPadding; - dspBorderPadding.SizeTo(0, 0, 0, 0); - - dspSpacing->CalcBorderPaddingFor(mDisplayFrame, dspBorderPadding); - - if (NS_UNCONSTRAINEDSIZE == firstPassState.mComputedWidth) { - mItemDisplayWidth = aDesiredSize.width - (dspBorderPadding.left + dspBorderPadding.right); - mItemDisplayWidth -= borderPadding.left + borderPadding.right; - } else { - if (firstPassState.mComputedWidth > 0) { - // Compute the display item's width from reflow's mComputedWidth - // mComputedWidth has already excluded border and padding - // so subtract off the button's size - mItemDisplayWidth = firstPassState.mComputedWidth - dspBorderPadding.left - dspBorderPadding.right; + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, aDesiredSize.width, NS_UNCONSTRAINEDSIZE); + dropdownFrame->GetRect(dropdownRect); + + if (maxElementSize) { + delete maxElementSize; } - } - // this reflows and makes and last minute adjustments - ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, - mDisplayFrame, buttonFrame, mItemDisplayWidth, scrollbarWidth, - borderPadding, - aDesiredSize.height- borderPadding.top - borderPadding.bottom - - dspBorderPadding.top - dspBorderPadding.bottom); -#endif // DO_NEW_REFLOW + } else { + // A width has been specified for the select. + // Make the display frame's width + button frame width = the width specified. + nsHTMLReflowMetrics dropdownDesiredSize(aDesiredSize); + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + // Get unconstrained size of the dropdown list. + nsSize size; + mListControlFrame->GetMaximumSize(size); + + if (scrollbarWidth > 0) { + size.width = scrollbarWidth; + } + // Size the button to be the same as the scrollbar width + SetChildFrameSize(buttonFrame, size.width, size.height); + + // Compute display width + nscoord displayWidth = firstPassState.mComputedWidth - size.width; + // nsAreaFrame::Reflow adds in the border and padding so we need to remove it + //displayWidth -= borderPadding.left + borderPadding.right; + + // Set the displayFrame to match the displayWidth computed above + SetChildFrameSize(displayFrame, displayWidth, size.height); + + // Reflow again with the width of the display frame set. + nsAreaFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); + // nsAreaFrame::Reflow adds in the border and padding so we need to remove it + // XXX rods - this hould not be subtracted in + //aDesiredSize.width += borderPadding.left + borderPadding.right; + + // Reflow the dropdown list to match the width of the display + button + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, aDesiredSize.width, NS_UNCONSTRAINEDSIZE); + + } // Set the max element size to be the same as the desired element size. if (nsnull != aDesiredSize.maxElementSize) { @@ -1640,37 +900,330 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, aDesiredSize.maxElementSize->height = aDesiredSize.height; } + aStatus = NS_FRAME_COMPLETE; #if 0 COMPARE_QUIRK_SIZE("nsComboboxControlFrame", 127, 22) #endif - // cache the availabe size to be our desired size minus the borders - // this is so if our cached avilable size is ever equal to or less - // than the real avilable size we can bail out - if (aReflowState.availableWidth != NS_UNCONSTRAINEDSIZE) { - mCachedAvailableSize.width = aDesiredSize.width - (borderPadding.left + borderPadding.right); - } - if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) { - mCachedAvailableSize.height = aDesiredSize.height - (borderPadding.top + borderPadding.bottom); - } - nsFormControlFrame::SetupCachedSizes(mCacheSize, mCachedMaxElementSize, aDesiredSize); - - REFLOW_DEBUG_MSG3("** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); - REFLOW_COUNTER(); - UNCONSTRAINED_CHECK(); - - // If this was a fully unconstrained reflow we cache - // the combobox's unconstrained size - if (fullyUnconstrained) { - mCachedUncComboSize.width = aDesiredSize.width; - mCachedUncComboSize.height = aDesiredSize.height; - } - return rv; } + +//------------------------------------------------------------------------------- +//------------------------------------------------------------------------------- +// New Reflow +//------------------------------------------------------------------------------- +//------------------------------------------------------------------------------- +#else // DO_OLD_REFLOW + +#ifdef DEBUG_rods +nsComboboxControlFrame * pCB = nsnull; +static int myCounter = 0; +#endif + +NS_IMETHODIMP +nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ +#ifdef DEBUG_rods + //if (pCB) { + printf("%p ****** nsComboboxControlFrame::Reflow %d Reason: ", this, myCounter++); + switch (aReflowState.reason) { + case eReflowReason_Initial: + printf("eReflowReason_Initial\n");break; + case eReflowReason_Incremental: + printf("eReflowReason_Incremental\n");break; + case eReflowReason_Resize: + printf("eReflowReason_Resize\n"); + break; + case eReflowReason_StyleChange:printf("eReflowReason_StyleChange\n");break; + } + //} +#endif + +#if 0 + nsresult skiprv = nsFormControlFrame::SkipResizeReflow(mCacheSize, mCachedMaxElementSize, aPresContext, + aDesiredSize, aReflowState, aStatus); + if (NS_SUCCEEDED(skiprv)) { + return skiprv; + } +#endif + + nsresult rv = NS_OK; + nsIFrame* buttonFrame = GetButtonFrame(aPresContext); + nsIFrame* displayFrame = GetDisplayFrame(aPresContext); + nsIFrame* dropdownFrame = GetDropdownFrame(); + + // Don't try to do any special sizing and positioning unless all of the frames + // have been created. + if ((nsnull == displayFrame) || + (nsnull == buttonFrame) || + (nsnull == dropdownFrame)) + { + // Since combobox frames are missing just do a normal area frame reflow + return nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + } + + // size of each part of the combo box + nsRect displayRect; + nsRect buttonRect; + nsRect dropdownRect; + + + if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { + nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*,this)); + } + + const nsStyleSpacing* spacing; + GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + nsMargin borderPadding; + borderPadding.SizeTo(0, 0, 0, 0); + spacing->CalcBorderPaddingFor(this, borderPadding); + + // Get the current sizes of the combo box child frames + displayFrame->GetRect(displayRect); + buttonFrame->GetRect(buttonRect); + dropdownFrame->GetRect(dropdownRect); + + nsHTMLReflowState firstPassState(aReflowState); + + // Only reflow the display and button if they are the target of + // the incremental reflow, unless they change size. If they do + // then everything needs to be reflowed. + if (eReflowReason_Incremental == firstPassState.reason) { + nsIFrame* targetFrame; + firstPassState.reflowCommand->GetTarget(targetFrame); + if (targetFrame == this) { + // not sure what I should be doing here for an incremental reflow + // so I will let it just reflow as normal + // but it does seems to go into this code. + } else { + if (targetFrame != dropdownFrame) { +#ifdef DEBUG_rods + printf("+++++++++++++++++++++++\n"); +#endif + rv = nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + displayFrame->GetRect(displayRect); + buttonFrame->GetRect(buttonRect); + buttonRect.y = displayRect.y; + buttonRect.height = displayRect.height; + buttonFrame->SetRect(aPresContext, buttonRect); + aStatus = NS_FRAME_COMPLETE; +#ifdef DEBUG_rods + printf("--> W: %d H: %d\n", aDesiredSize.width, aDesiredSize.height); +#endif + return rv; + } else { +#if 0 + nsRect dropdownRect; + dropdownFrame->GetRect(dropdownRect); + nsHTMLReflowMetrics dropdownDesiredSize(aDesiredSize); + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, + aStatus, dropdownRect.width, dropdownRect.height); + nsCOMPtr context; + targetFrame->GetStyleContext(getter_AddRefs(context)); + const nsStyleDisplay* disp = (const nsStyleDisplay*)context->GetStyleData(eStyleStruct_Display); + printf("IsVisible %s\n", disp->mVisible == NS_STYLE_VISIBILITY_VISIBLE?"yes":"No"); + //if (disp->mVisible == NS_STYLE_VISIBILITY_VISIBLE) { + nsRect rect; + GetRect(rect); + aDesiredSize.width = rect.width;// + borderPadding.left + borderPadding.right; + aDesiredSize.height = rect.height;// + borderPadding.top + borderPadding.bottom; + aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.descent = 0; + dropdownRect.width = rect.width; + dropdownFrame->SetRect(aPresContext, dropdownRect); + printf("Skipping out.........................."); + aStatus = NS_FRAME_COMPLETE; + return NS_OK; + //} +#endif + } + } + } + + // the default size of the of scrollbar + // that will be the default width of the dropdown button + // the height will be the height of the text + nscoord scrollbarWidth = -1; + nsCOMPtr dx; + aPresContext->GetDeviceContext(getter_AddRefs(dx)); + if (dx) { + // Get the width in Device pixels (in this case screen) + SystemAttrStruct info; + dx->GetSystemAttribute(eSystemAttr_Size_ScrollbarWidth, &info); + // Get the pixels to twips conversion for the current device (screen or printer) + float p2t; + aPresContext->GetPixelsToTwips(&p2t); + // Get the scale factor for mapping from one device (screen) + // to another device (screen or printer) + // Typically when it is a screen the scale 1.0 + // when it is a printer is could be anything + float scale; + dx->GetCanonicalPixelScale(scale); + scrollbarWidth = NSIntPixelsToTwips(info.mSize, p2t*scale); + } +#ifdef DEBUG_rods + printf("UNC %d AV %d \n", firstPassState.mComputedWidth,firstPassState.availableWidth); +#endif + //Set the desired size for the button and display frame + if (NS_UNCONSTRAINEDSIZE == firstPassState.mComputedWidth) { +#ifdef DEBUG_rods + printf("=====================================\n"); +#endif + + // A width has not been specified for the select so size the display area to + // match the width of the longest item in the drop-down list. The dropdown + // list has already been reflowed and sized to shrink around its contents above. + + // Reflow the dropdown shrink-wrapped. + PRBool saveMES = aDesiredSize.maxElementSize != nsnull; + nsSize * maxElementSize = nsnull; + if (saveMES) { + maxElementSize = new nsSize(); + //maxElementSize = new nsSize(*aDesiredSize.maxElementSize); + } + nsHTMLReflowMetrics dropdownDesiredSize(maxElementSize); + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + + nsSize size; + PRInt32 length = 0; + mListControlFrame->GetNumberOfOptions(&length); + dropdownFrame->GetRect(dropdownRect); + + const nsStyleSpacing* dropSpacing; + dropdownFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dropSpacing); + nsMargin dropBorderPadding; + dropBorderPadding.SizeTo(0, 0, 0, 0); + dropSpacing->CalcBorderPaddingFor(dropdownFrame, dropBorderPadding); + dropdownRect.width -= (dropBorderPadding.left + dropBorderPadding.right); + + // Get maximum size and height of a option in the dropdown + mListControlFrame->GetMaximumSize(size); + + if (scrollbarWidth > 0) { + size.width = scrollbarWidth; + } + const nsStyleSpacing* dspSpacing; + displayFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)dspSpacing); + nsMargin dspBorderPadding; + dspBorderPadding.SizeTo(0, 0, 0, 0); + dspSpacing->CalcBorderPaddingFor(displayFrame, dspBorderPadding); + +#ifdef DEBUG_rods + printf("W: %d\n", dropdownRect.width-size.width+dspBorderPadding.left+dspBorderPadding.right); +#endif + // Set width of display to match width of the drop down + SetChildFrameSize(displayFrame, dropdownRect.width-size.width+dspBorderPadding.left+dspBorderPadding.right, + size.height+dspBorderPadding.top+dspBorderPadding.bottom); + + // Size the button + SetChildFrameSize(buttonFrame, size.width, size.height); + + // Reflow display + button + nsAreaFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); + + displayFrame->GetRect(displayRect); + buttonFrame->GetRect(buttonRect); + buttonRect.y = displayRect.y; + buttonRect.height = displayRect.height; + buttonFrame->SetRect(aPresContext, buttonRect); + + // Reflow the dropdown list to match the width of the display + button + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, aDesiredSize.width, NS_UNCONSTRAINEDSIZE); + dropdownFrame->GetRect(dropdownRect); + + if (maxElementSize) { + delete maxElementSize; + } + + } else { +#ifdef DEBUG_rods + printf("*************************************\n"); +#endif + // for debug ------- + PRInt32 length = 0; + mListControlFrame->GetNumberOfOptions(&length); + //------ + + // A width has been specified for the select. + // Make the display frame's width + button frame width = the width specified. + nsHTMLReflowMetrics dropdownDesiredSize(aDesiredSize); + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + // Get unconstrained size of the dropdown list. + nsSize size; + mListControlFrame->GetMaximumSize(size); + + if (scrollbarWidth > 0) { + size.width = scrollbarWidth; + } + // Size the button to be the same as the scrollbar width + SetChildFrameSize(buttonFrame, size.width, size.height); + + if (firstPassState.mComputedWidth > 0) { + // Compute display width + nscoord displayWidth = firstPassState.mComputedWidth - size.width; + // nsAreaFrame::Reflow adds in the border and padding so we need to remove it + //displayWidth -= borderPadding.left + borderPadding.right; + +#ifdef DEBUG_rods + printf("WW: %d\n", displayWidth); +#endif + // Set the displayFrame to match the displayWidth computed above + if (displayWidth >= 0) { + SetChildFrameSize(displayFrame, displayWidth, size.height); + } + + // Reflow again with the width of the display frame set. + nsAreaFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); + + displayFrame->GetRect(displayRect); + displayRect.width = displayWidth; + buttonFrame->GetRect(buttonRect); + buttonRect.x = displayWidth+borderPadding.left; + buttonRect.y = displayRect.y; + buttonRect.height = displayRect.height; + buttonFrame->SetRect(aPresContext, buttonRect); + displayFrame->SetRect(aPresContext, displayRect); +#ifdef DEBUG_rods + printf("DW: %d\n", aDesiredSize.width); +#endif + // nsAreaFrame::Reflow adds in the border and padding so we need to remove it + // XXX rods - this hould not be subtracted in + //aDesiredSize.width += borderPadding.left + borderPadding.right; + + // Reflow the dropdown list to match the width of the display + button + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, aDesiredSize.width, NS_UNCONSTRAINEDSIZE); + } + aDesiredSize.width = firstPassState.mComputedWidth + borderPadding.left + borderPadding.right; + aDesiredSize.height = firstPassState.mComputedHeight + borderPadding.top + borderPadding.bottom; + aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.descent = 0; + } + + // 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; +#if 0 + COMPARE_QUIRK_SIZE("nsComboboxControlFrame", 127, 22) +#endif + + nsFormControlFrame::SetupCachedSizes(mCacheSize, mCachedMaxElementSize, aDesiredSize); +#ifdef DEBUG_rods + printf("--> W: %d H: %d\n", aDesiredSize.width, aDesiredSize.height); +#endif + return rv; + +} +#endif // DO_OLD_REFLOW //------------------------------------------------------------------------------- //------------------------------------------------------------------------------- // Done with New Reflow @@ -1808,15 +1361,10 @@ nsComboboxControlFrame::SetDropDown(nsIFrame* aDropDownFrame) return NS_ERROR_FAILURE; } - - // The ListControlFrame was just created and added to the comboxbox - // so provide it with a PresState so it can restore itself - // when it does its first "Reset" if (mPresState) { mListControlFrame->SetPresState(mPresState); mPresState = do_QueryInterface(nsnull); } - return NS_OK; } @@ -1865,13 +1413,7 @@ nsComboboxControlFrame::UpdateSelection(PRBool aDoDispatchEvent, PRBool aForceUp if (mListControlFrame) { // Check to see if the selection changed if (mSelectedIndex != aNewIndex || aForceUpdate) { - //???if (mSelectedIndex != aNewIndex || (aForceUpdate && aNewIndex != kSizeNotSet)) { mListControlFrame->GetSelectedItem(mTextStr); // Update text box -#ifdef DO_REFLOW_DEBUG - char * str = mTextStr.ToNewCString(); - REFLOW_DEBUG_MSG2("UpdateSelection %s\n", str); - delete [] str; -#endif mListControlFrame->UpdateSelection(aDoDispatchEvent, aForceUpdate, mContent); } mSelectedIndex = aNewIndex; @@ -1885,7 +1427,7 @@ nsComboboxControlFrame::AbsolutelyPositionDropDown() { nsRect absoluteTwips; nsRect absolutePixels; - +// XXX Not used nsIFrame* displayFrame = GetDisplayFrame(mPresContext); nsRect rect; this->GetRect(rect); GetAbsoluteFramePosition(mPresContext, this, absoluteTwips, absolutePixels); @@ -1912,30 +1454,49 @@ nsComboboxControlFrame::SelectionChanged() // Send reflow command because the new text maybe larger nsresult rv = NS_OK; if (mDisplayContent) { - nsAutoString value; - const nsTextFragment* fragment; - nsresult result = mDisplayContent->GetText(&fragment); - if (NS_SUCCEEDED(result)) { - fragment->AppendTo(value); - } - PRBool shouldSetValue = PR_FALSE; - if (NS_FAILED(result) || value.Length() == 0) { - shouldSetValue = PR_TRUE; - } else { - shouldSetValue = value != mTextStr; - } - if (shouldSetValue) { - rv = mDisplayContent->SetText(mTextStr.GetUnicode(), mTextStr.Length(), PR_TRUE); - nsFrameState 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 htmlContent(do_QueryInterface(mDisplayContent, &rv)); + if (NS_SUCCEEDED(rv) && htmlContent) { + nsHTMLValue value; + nsresult result = htmlContent->GetHTMLAttribute(nsHTMLAtoms::value, value); + + PRBool shouldSetValue = PR_FALSE; + if (NS_FAILED(result) || value.GetUnit() == eHTMLUnit_Empty) { + shouldSetValue = PR_TRUE; + } else if (NS_SUCCEEDED(result) && value.GetUnit() == eHTMLUnit_String) { + nsAutoString str; + value.GetStringValue(str); + shouldSetValue = str != mTextStr; + } + if (shouldSetValue) { + rv = htmlContent->SetHTMLAttribute(nsHTMLAtoms::value, mTextStr, PR_TRUE); +#if 1 + if (NS_SUCCEEDED(rv)) { + nsIFrame* displayFrame = GetDisplayFrame(mPresContext); + + nsIReflowCommand* cmd; + rv = NS_NewHTMLReflowCommand(&cmd, displayFrame, nsIReflowCommand::StyleChanged); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr shell; + rv = mPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(rv) && shell) { + if (NS_SUCCEEDED(shell->EnterReflowLock())) { + shell->AppendReflowCommand(cmd); + shell->ExitReflowLock(PR_TRUE); + } + } + NS_RELEASE(cmd); + } + } +#else + if (mParent) { + nsCOMPtr shell; + rv = mPresContext->GetShell(getter_AddRefs(shell)); + mState |= NS_FRAME_IS_DIRTY; + mParent->ReflowDirtyChild(shell, (nsIFrame*) this); + } + +#endif + } } } return rv; @@ -1965,18 +1526,19 @@ nsComboboxControlFrame::DoneAddingContent(PRBool aIsDone) NS_IMETHODIMP nsComboboxControlFrame::AddOption(nsIPresContext* aPresContext, PRInt32 aIndex) { -#ifdef DO_REFLOW_DEBUG - printf("**********\n*********AddOption: %d\n", aIndex); +#ifdef DEBUG_rodsXXX + if (!pCB) pCB = this; #endif + nsISelectControlFrame* listFrame = nsnull; nsIFrame* dropdownFrame = GetDropdownFrame(); nsresult rv = dropdownFrame->QueryInterface(NS_GET_IID(nsISelectControlFrame), (void**)&listFrame); if (NS_SUCCEEDED(rv) && listFrame) { rv = listFrame->AddOption(aPresContext, aIndex); - //PRInt32 index; - //mListControlFrame->GetSelectedIndex(&index); - //UpdateSelection(PR_FALSE, PR_TRUE, index); + PRInt32 index; + mListControlFrame->GetSelectedIndex(&index); + UpdateSelection(PR_FALSE, PR_TRUE, index); NS_RELEASE(listFrame); } // If we added the first option, we might need to select it. @@ -2083,60 +1645,6 @@ nsComboboxControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) } -NS_IMETHODIMP -nsComboboxControlFrame::CreateDisplayFrame(nsIPresContext* aPresContext) -{ - - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - 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 frame - nsCOMPtr styleContext; - rv = aPresContext->ResolvePseudoStyleContextFor(mContent, - 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(mContent, - nsHTMLAtoms::mozDisplayComboboxControlFrame, - styleContext, - PR_FALSE, - getter_AddRefs(textStyleContext)); - if (NS_FAILED(rv)) { return rv; } - if (!textStyleContext) { return NS_ERROR_NULL_POINTER; } - nsCOMPtr content(do_QueryInterface(mDisplayContent)); - mTextFrame->Init(aPresContext, content, mDisplayFrame, textStyleContext, nsnull); - mTextFrame->SetInitialChildList(aPresContext, nsnull, nsnull); - nsCOMPtr presShell; - rv = aPresContext->GetShell(getter_AddRefs(presShell)); - if (NS_FAILED(rv)) { return rv; } - if (!presShell) { return NS_ERROR_NULL_POINTER; } - nsCOMPtr frameManager; - rv = presShell->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); - - return NS_OK; -} - - NS_IMETHODIMP nsComboboxControlFrame::CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aChildList) @@ -2161,29 +1669,22 @@ nsComboboxControlFrame::CreateAnonymousContent(nsIPresContext* aPresContext, // create content used for display //nsIAtom* tag = NS_NewAtom("mozcombodisplay"); - // Add a child text content node for the label - nsCOMPtr labelContent; - nsresult result = NS_NewTextNode(getter_AddRefs(labelContent)); - nsAutoString value="X"; - if (NS_SUCCEEDED(result) && labelContent) { - // set the value of the text node - mDisplayContent = do_QueryInterface(labelContent); - mDisplayContent->SetText(value.GetUnicode(), value.Length(), PR_TRUE); + NS_NewHTMLInputElement(&mDisplayContent, nsHTMLAtoms::input); - nsIDocument* doc; - mContent->GetDocument(doc); - labelContent->SetDocument(doc, PR_FALSE); - NS_RELEASE(doc); - mContent->AppendChildTo(labelContent, PR_FALSE); + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, nsAutoString("button"), PR_FALSE); - // create button which drops the list down - result = NS_NewHTMLInputElement(&mButtonContent, nsHTMLAtoms::input); - //NS_ADDREF(mButtonContent); - if (NS_SUCCEEDED(result) && mButtonContent) { - mButtonContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, nsAutoString("button"), PR_FALSE); - aChildList.AppendElement(mButtonContent); - } - } + //XXX: Do not use nsHTMLAtoms::id use nsHTMLAtoms::kClass instead. There will end up being multiple + //ids set to the same value which is illegal. + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, nsAutoString("-moz-display"), PR_FALSE); + // This is + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, nsAutoString("X"), PR_TRUE); + aChildList.AppendElement(mDisplayContent); + + // create button which drops the list down + NS_NewHTMLInputElement(&mButtonContent, nsHTMLAtoms::input); + //NS_ADDREF(mButtonContent); + mButtonContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, nsAutoString("button"), PR_FALSE); + aChildList.AppendElement(mButtonContent); return NS_OK; } @@ -2201,22 +1702,6 @@ nsComboboxControlFrame::Destroy(nsIPresContext* aPresContext) { // Cleanup frames in popup child list mPopupFrames.DestroyFrames(aPresContext); - if (mDisplayFrame) { - mFrameConstructor->RemoveMappingsForFrameSubtree(aPresContext, mDisplayFrame, nsnull); - mDisplayFrame->Destroy(aPresContext); - mDisplayFrame=nsnull; - } - - if (mDisplayContent) { - nsCOMPtr content(do_QueryInterface(mDisplayContent)); - if (content) { - PRInt32 index; - if (NS_SUCCEEDED(mContent->IndexOf(content, index))) { - mContent->RemoveChildAt(index, PR_FALSE); - } - } - } - return nsAreaFrame::Destroy(aPresContext); } @@ -2244,7 +1729,7 @@ nsComboboxControlFrame::SetInitialChildList(nsIPresContext* aPresContext, mPopupFrames.SetFrames(aChildList); } else { rv = nsAreaFrame::SetInitialChildList(aPresContext, aListName, aChildList); - InitTextStr(aPresContext, PR_FALSE); + InitTextStr(aPresContext, PR_TRUE); } return rv; } @@ -2333,39 +1818,3 @@ nsComboboxControlFrame::RestoreState(nsIPresContext* aPresContext, nsIPresState* return mListControlFrame->RestoreStateInternal(aPresContext, aState); } - -NS_METHOD -nsComboboxControlFrame::Paint(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) -{ -#ifdef NOISY - printf("%p paint layer %d at (%d, %d, %d, %d)\n", this, aWhichLayer, - aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height); -#endif - nsAreaFrame::Paint(aPresContext,aRenderingContext,aDirtyRect,aWhichLayer); - - if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { - nsRect rect(0, 0, mRect.width, mRect.height); - if (mDisplayFrame) { - aRenderingContext.PushState(); - PRBool clipEmpty; - nsRect clipRect; - mDisplayFrame->GetRect(clipRect); - aRenderingContext.SetClipRect(clipRect, nsClipCombine_kReplace, clipEmpty); - PaintChild(aPresContext, aRenderingContext, aDirtyRect, - mDisplayFrame, NS_FRAME_PAINT_LAYER_BACKGROUND); - PaintChild(aPresContext, aRenderingContext, aDirtyRect, - mDisplayFrame, NS_FRAME_PAINT_LAYER_FOREGROUND); - 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/mozilla/layout/html/forms/src/nsComboboxControlFrame.h b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h index 69f4edfc955..1813dab4fe5 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.h +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h @@ -23,17 +23,7 @@ #ifndef nsComboboxControlFrame_h___ #define nsComboboxControlFrame_h___ -#ifdef DEBUG_evaughan -//#define DEBUG_rods -#endif - -#ifdef DEBUG_rods -//#define DO_REFLOW_DEBUG -//#define DO_REFLOW_COUNTER -//#define DO_UNCONSTRAINED_CHECK -//#define DO_PIXELS -//#define DO_NEW_REFLOW -#endif +#define OPTIMIZE_RESIZE_RELOW #include "nsAreaFrame.h" #include "nsIFormControlFrame.h" @@ -44,8 +34,6 @@ #include "nsIStatefulFrame.h" #include "nsIRollupListener.h" #include "nsIPresState.h" -#include "nsCSSFrameConstructor.h" -#include "nsITextContent.h" class nsFormFrame; class nsIView; @@ -96,10 +84,6 @@ public: nsGUIEvent* aEvent, nsEventStatus* aEventStatus); - NS_IMETHOD Paint(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); #ifdef NS_DEBUG NS_IMETHOD GetFrameName(nsString& aResult) const; #endif @@ -160,6 +144,8 @@ public: NS_IMETHOD UpdateSelection(PRBool aDoDispatchEvent, PRBool aForceUpdate, PRInt32 aNewIndex); NS_IMETHOD AbsolutelyPositionDropDown(); NS_IMETHOD GetAbsoluteRect(nsRect* aRect); + NS_IMETHOD SetFrameConstructor(nsCSSFrameConstructor *aConstructor) + { return NS_OK;} // not owner - do not addref! // nsISelectControlFrame NS_IMETHOD AddOption(nsIPresContext* aPresContext, PRInt32 index); @@ -176,17 +162,8 @@ public: //nsIRollupListener NS_IMETHOD Rollup(); - NS_IMETHOD SetFrameConstructor(nsCSSFrameConstructor *aConstructor) - { mFrameConstructor = aConstructor; return NS_OK;} // not owner - do not addref! protected: - NS_IMETHOD CreateDisplayFrame(nsIPresContext* aPresContext); - -#ifdef DO_NEW_REFLOW - NS_IMETHOD ReflowItems(nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - nsHTMLReflowMetrics& aDesiredSize); -#endif // nsHTMLContainerFrame virtual PRIntn GetSkipSides() const; @@ -210,6 +187,7 @@ public: nsIFrame *aFrame, nsRect& aAbsoluteTwipsRect, nsRect& aAbsolutePixelRect); + nsIFrame* GetDisplayFrame(nsIPresContext* aPresContext); protected: void ShowPopup(PRBool aShowPopup); void ShowList(nsIPresContext* aPresContext, PRBool aShowList); @@ -221,32 +199,19 @@ protected: NS_IMETHOD ToggleList(nsIPresContext* aPresContext); NS_IMETHOD MakeSureSomethingIsSelected(nsIPresContext* aPresContext); // Default to option 0 - void ReflowCombobox(nsIPresContext * aPresContext, - const nsHTMLReflowState& aReflowState, - nsHTMLReflowMetrics& aDesiredSize, - nsReflowStatus& aStatus, - nsIFrame * aDisplayFrame, - nsIFrame * aDropDownBtn, - nscoord& aDisplayWidth, - nscoord aBtnWidth, - const nsMargin& aBorderPadding, - nscoord aFallBackHgt = -1, - PRBool aCheckHeight = PR_FALSE); - - nsFrameList mPopupFrames; // additional named child list - nsIPresContext* mPresContext; // XXX: Remove the need to cache the pres context. - nsFormFrame* mFormFrame; // Parent Form Frame - nsString mTextStr; // Current Combo box selection - PRInt32 mSelectedIndex; // current selected index - nsCOMPtr mDisplayContent; // Anonymous content used to display the current selection - nsIHTMLContent* mButtonContent; // Anonymous content used to popup the dropdown list - PRBool mDroppedDown; // Current state of the dropdown list, PR_TRUE is dropped down - nsIFrame* mDisplayFrame; // frame to display selection - nsIFrame* mButtonFrame; // button frame - nsIFrame* mDropdownFrame; // dropdown list frame - nsIFrame* mTextFrame; // display area frame - nsIListControlFrame * mListControlFrame; // ListControl Interface for the dropdown frame - PRBool mIgnoreFocus; // Tells the combo to ignore all focus notifications + nsFrameList mPopupFrames; // additional named child list + nsIPresContext* mPresContext; // XXX: Remove the need to cache the pres context. + nsFormFrame* mFormFrame; // Parent Form Frame + nsString mTextStr; // Current Combo box selection + PRInt32 mSelectedIndex; // current selected index + nsIHTMLContent* mDisplayContent; // Anonymous content used to display the current selection + nsIHTMLContent* mButtonContent; // Anonymous content used to popup the dropdown list + PRBool mDroppedDown; // Current state of the dropdown list, PR_TRUE is dropped down + nsIFrame* mDisplayFrame; // frame to display selection + nsIFrame* mButtonFrame; // button frame + nsIFrame* mDropdownFrame; // dropdown list frame + nsIListControlFrame * mListControlFrame; // ListControl Interface for the dropdown frame + PRBool mIgnoreFocus; // Tells the combo to ignore all focus notifications nsCOMPtr mPresState; // Need cache state when list is null @@ -254,18 +219,6 @@ protected: // Resize Reflow Optimization nsSize mCacheSize; nsSize mCachedMaxElementSize; - nsSize mCachedAvailableSize; - - nsSize mCachedUncDropdownSize; - nsSize mCachedUncComboSize; - - nscoord mItemDisplayWidth; - //nscoord mItemDisplayHeight; - nsCSSFrameConstructor* mFrameConstructor; - -#ifdef DO_REFLOW_COUNTER - PRInt32 mReflowId; -#endif private: NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.cpp b/mozilla/layout/html/forms/src/nsListControlFrame.cpp index 02501cfe657..7866ab948a7 100644 --- a/mozilla/layout/html/forms/src/nsListControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsListControlFrame.cpp @@ -381,7 +381,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, PRBool bailOnHeight; // This ifdef is for turning off the optimization // so we can check timings against the old version -#if 1 +#if 0 nsFormControlFrame::SkipResizeReflow(mCacheSize, mCachedMaxElementSize,