From 1539b1b9c3b9720547ca067762f2acb0cdec81a1 Mon Sep 17 00:00:00 2001 From: "rods%netscape.com" Date: Wed, 9 Feb 2000 19:34:39 +0000 Subject: [PATCH] removing unneeded native frames and unneeded frame classes that these derived from fixing checkbox and radiobutton state restore fixing right btn click on dropdown adding in initial work for accesskey bug 17027,26296,27063,7559; carpool a=leaf; r=kmcclusk --- layout/forms/nsComboboxControlFrame.cpp | 77 +++- layout/forms/nsComboboxControlFrame.h | 6 +- layout/forms/nsFileControlFrame.cpp | 10 +- layout/forms/nsFileControlFrame.h | 7 +- layout/forms/nsFormControlFrame.cpp | 104 +++-- layout/forms/nsFormControlFrame.h | 13 +- layout/forms/nsFormControlHelper.cpp | 2 +- layout/forms/nsGfxButtonControlFrame.cpp | 8 +- layout/forms/nsGfxCheckboxControlFrame.cpp | 375 +++++++++++++++++- layout/forms/nsGfxCheckboxControlFrame.h | 83 +++- layout/forms/nsGfxRadioControlFrame.cpp | 196 ++++++++- layout/forms/nsGfxRadioControlFrame.h | 32 +- layout/forms/nsHTMLButtonControlFrame.cpp | 15 +- layout/forms/nsHTMLButtonControlFrame.h | 2 + layout/forms/nsImageControlFrame.cpp | 7 + layout/forms/nsLegendFrame.cpp | 21 +- layout/forms/nsLegendFrame.h | 12 + layout/forms/nsListControlFrame.cpp | 73 +++- layout/forms/nsListControlFrame.h | 1 + layout/forms/nsTextControlFrame.cpp | 1 - layout/html/forms/src/makefile.win | 11 - .../html/forms/src/nsCheckboxControlFrame.h | 4 +- .../html/forms/src/nsComboboxControlFrame.cpp | 77 +++- .../html/forms/src/nsComboboxControlFrame.h | 6 +- layout/html/forms/src/nsFileControlFrame.cpp | 10 +- layout/html/forms/src/nsFileControlFrame.h | 7 +- layout/html/forms/src/nsFormControlFrame.cpp | 104 +++-- layout/html/forms/src/nsFormControlFrame.h | 13 +- layout/html/forms/src/nsFormControlHelper.cpp | 2 +- layout/html/forms/src/nsFormFrame.cpp | 90 ++++- layout/html/forms/src/nsFormFrame.h | 13 +- .../forms/src/nsGfxButtonControlFrame.cpp | 8 +- .../forms/src/nsGfxCheckboxControlFrame.cpp | 375 +++++++++++++++++- .../forms/src/nsGfxCheckboxControlFrame.h | 83 +++- .../html/forms/src/nsGfxListControlFrame.cpp | 15 +- layout/html/forms/src/nsGfxListControlFrame.h | 2 +- .../html/forms/src/nsGfxRadioControlFrame.cpp | 196 ++++++++- .../html/forms/src/nsGfxRadioControlFrame.h | 32 +- .../html/forms/src/nsGfxTextControlFrame.cpp | 80 +++- layout/html/forms/src/nsGfxTextControlFrame.h | 17 +- .../forms/src/nsHTMLButtonControlFrame.cpp | 15 +- .../html/forms/src/nsHTMLButtonControlFrame.h | 2 + layout/html/forms/src/nsImageControlFrame.cpp | 7 + layout/html/forms/src/nsLabelFrame.cpp | 23 +- layout/html/forms/src/nsLegendFrame.cpp | 21 +- layout/html/forms/src/nsLegendFrame.h | 12 + layout/html/forms/src/nsListControlFrame.cpp | 73 +++- layout/html/forms/src/nsListControlFrame.h | 1 + layout/html/forms/src/nsRadioControlFrame.h | 2 - layout/html/forms/src/nsRadioControlGroup.cpp | 12 +- layout/html/forms/src/nsRadioControlGroup.h | 16 +- layout/html/forms/src/nsTextControlFrame.cpp | 1 - 52 files changed, 2113 insertions(+), 262 deletions(-) diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index d12709f7f36c..062ca5fd1444 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -132,6 +132,8 @@ nsComboboxControlFrame::~nsComboboxControlFrame() NS_IF_RELEASE(mPresContext); NS_IF_RELEASE(mDisplayContent); NS_IF_RELEASE(mButtonContent); + + nsFormControlFrame::RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); } //-------------------------------------------------------------- @@ -265,9 +267,7 @@ nsComboboxControlFrame::Reset(nsIPresContext* aPresContext) } void -nsComboboxControlFrame::PostCreateWidget(nsIPresContext* aPresContext, - nscoord& aWidth, - nscoord& aHeight) +nsComboboxControlFrame::InitializeControl(nsIPresContext* aPresContext) { Reset(aPresContext); } @@ -724,6 +724,7 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*,this)); } @@ -912,6 +913,7 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, #else // DO_OLD_REFLOW #ifdef DEBUG_rods +nsComboboxControlFrame * pCB = nsnull; static int myCounter = 0; #endif @@ -922,7 +924,8 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, nsReflowStatus& aStatus) { #ifdef DEBUG_rods - printf("****** nsComboboxControlFrame::Reflow %d Reason: ", myCounter++); + //if (pCB) { + printf("%p ****** nsComboboxControlFrame::Reflow %d Reason: ", this, myCounter++); switch (aReflowState.reason) { case eReflowReason_Initial: printf("eReflowReason_Initial\n");break; @@ -933,6 +936,7 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, break; case eReflowReason_StyleChange:printf("eReflowReason_StyleChange\n");break; } + //} #endif #if 0 @@ -993,7 +997,9 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // 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); @@ -1001,14 +1007,34 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, 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, firstPassState.availableWidth, firstPassState.availableHeight); - return NS_OK; + 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 } } @@ -1035,10 +1061,15 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, 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. @@ -1077,7 +1108,9 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, 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); @@ -1103,7 +1136,9 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, } } else { +#ifdef DEBUG_rods printf("*************************************\n"); +#endif // for debug ------- PRInt32 length = 0; mListControlFrame->GetNumberOfOptions(&length); @@ -1129,7 +1164,9 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // 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); @@ -1146,7 +1183,9 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, 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; @@ -1156,6 +1195,8 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, } 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. @@ -1164,18 +1205,15 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, aDesiredSize.maxElementSize->height = aDesiredSize.height; } - nsRect absoluteTwips; - nsRect absolutePixels; - GetAbsoluteFramePosition(aPresContext, this, absoluteTwips, absolutePixels); - PositionDropdown(aPresContext, aDesiredSize.height, absoluteTwips, absolutePixels); - 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; } @@ -1422,6 +1460,7 @@ nsComboboxControlFrame::SelectionChanged() } if (shouldSetValue) { rv = htmlContent->SetHTMLAttribute(nsHTMLAtoms::value, mTextStr, PR_TRUE); +#if 1 if (NS_SUCCEEDED(rv)) { nsIFrame* displayFrame = GetDisplayFrame(mPresContext); @@ -1439,6 +1478,15 @@ nsComboboxControlFrame::SelectionChanged() 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 } } } @@ -1467,12 +1515,19 @@ nsComboboxControlFrame::DoneAddingContent(PRBool aIsDone) NS_IMETHODIMP nsComboboxControlFrame::AddOption(nsIPresContext* aPresContext, PRInt32 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); NS_RELEASE(listFrame); } // If we added the first option, we might need to select it. diff --git a/layout/forms/nsComboboxControlFrame.h b/layout/forms/nsComboboxControlFrame.h index 781bfab81e3b..4359a810c32c 100644 --- a/layout/forms/nsComboboxControlFrame.h +++ b/layout/forms/nsComboboxControlFrame.h @@ -35,8 +35,6 @@ #include "nsIRollupListener.h" #include "nsIPresState.h" -class nsButtonControlFrame; -class nsTextControlFrame; class nsFormFrame; class nsIView; class nsStyleContext; @@ -109,9 +107,7 @@ public: NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); void SetFocus(PRBool aOn, PRBool aRepaint); void ScrollIntoView(nsIPresContext* aPresContext); - virtual void PostCreateWidget(nsIPresContext* aPresContext, - nscoord& aWidth, - nscoord& aHeight); + virtual void InitializeControl(nsIPresContext* aPresContext); virtual PRBool IsSuccessful(nsIFormControlFrame* aSubmitter); virtual void SetFormFrame(nsFormFrame* aFormFrame) { mFormFrame = aFormFrame; } virtual void Reset(nsIPresContext* aPresContext); diff --git a/layout/forms/nsFileControlFrame.cpp b/layout/forms/nsFileControlFrame.cpp index 3bf49fa1a111..e7940b39b3d9 100644 --- a/layout/forms/nsFileControlFrame.cpp +++ b/layout/forms/nsFileControlFrame.cpp @@ -22,9 +22,7 @@ #include "nsFileControlFrame.h" #include "nsFormFrame.h" -#include "nsButtonControlFrame.h" -#include "nsTextControlFrame.h" -#include "nsNativeTextControlFrame.h" // XXX: remove when frame construction is done properly +#include "nsGfxTextControlFrame.h" #include "nsIContent.h" #include "prtypes.h" #include "nsIAtom.h" @@ -312,7 +310,7 @@ nsFileControlFrame::SetInitialChildList(nsIPresContext* aPresContext, * frame constuctor create the frame and its implementation. So we are given the text * node from the constructor and we find it in our tree. */ -nsTextControlFrame* +nsGfxTextControlFrame* nsFileControlFrame::GetTextControlFrame(nsIPresContext* aPresContext, nsIFrame* aStart) { // find the text control frame. @@ -331,13 +329,13 @@ nsFileControlFrame::GetTextControlFrame(nsIPresContext* aPresContext, nsIFrame* value.ToUpperCase(); nsString txt("TEXT"); if (value == txt) { - return (nsTextControlFrame*)childFrame; + return (nsGfxTextControlFrame*)childFrame; } } } // if not continue looking - nsTextControlFrame* frame = GetTextControlFrame(aPresContext, childFrame); + nsGfxTextControlFrame* frame = GetTextControlFrame(aPresContext, childFrame); if (frame) return frame; diff --git a/layout/forms/nsFileControlFrame.h b/layout/forms/nsFileControlFrame.h index c90cf974c434..6f2b9260d63c 100644 --- a/layout/forms/nsFileControlFrame.h +++ b/layout/forms/nsFileControlFrame.h @@ -30,8 +30,7 @@ #include "nsIStatefulFrame.h" class nsIPresState; -class nsButtonControlFrame; -class nsTextControlFrame; +class nsGfxTextControlFrame; class nsFormFrame; class nsISupportsArray; class nsIHTMLContent; @@ -176,7 +175,7 @@ protected: virtual PRIntn GetSkipSides() const; - nsTextControlFrame* mTextFrame; + nsGfxTextControlFrame* mTextFrame; nsFormFrame* mFormFrame; nsIHTMLContent* mTextContent; nsString* mCachedState; @@ -184,7 +183,7 @@ protected: nsIPresContext* mPresContext; // weak reference private: - nsTextControlFrame* GetTextControlFrame(nsIPresContext* aPresContext, + nsGfxTextControlFrame* GetTextControlFrame(nsIPresContext* aPresContext, nsIFrame* aStart); NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } diff --git a/layout/forms/nsFormControlFrame.cpp b/layout/forms/nsFormControlFrame.cpp index 8017cca428ca..dba52d5f2304 100644 --- a/layout/forms/nsFormControlFrame.cpp +++ b/layout/forms/nsFormControlFrame.cpp @@ -54,6 +54,11 @@ #include "nsStyleUtil.h" #include "nsINameSpaceManager.h" #include "nsIDOMHTMLInputElement.h" +#include "nsIDOMHTMLLabelElement.h" +#include "nsIDOMHTMLTextAreaElement.h" +#include "nsIDOMHTMLLegendElement.h" +#include "nsIDOMHTMLButtonElement.h" +#include "nsIEventStateManager.h" static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID); @@ -87,6 +92,7 @@ nsFormControlFrame::~nsFormControlFrame() mFormFrame->RemoveRadioControlFrame(this); mFormFrame = nsnull; } + RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); } // Frames are not refcounted, no need to AddRef @@ -302,42 +308,29 @@ nsFormControlFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + if (!mDidInit) { + mPresContext = aPresContext; + InitializeControl(aPresContext); + mDidInit = PR_TRUE; + } + // add ourself as an nsIFormControlFrame if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); } + nsresult skiprv = SkipResizeReflow(mCacheSize, mCachedMaxElementSize, aPresContext, aDesiredSize, aReflowState, aStatus); if (NS_SUCCEEDED(skiprv)) { return skiprv; } - nsWidgetRendering mode; - aPresContext->GetWidgetRenderingMode(&mode); - if (eWidgetRendering_Native == mode) { - GetDesiredSize(aPresContext, aReflowState, aDesiredSize, mWidgetSize); - - if (!mDidInit) { - PostCreateWidget(aPresContext, aDesiredSize.width, aDesiredSize.height); - mDidInit = PR_TRUE; - } - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; - - } else { - nsresult rv = nsLeafFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); - if (!mDidInit) { - //GetDesiredSize(aPresContext, aReflowState, aDesiredSize); - PostCreateWidget(aPresContext, aDesiredSize.width, aDesiredSize.height); - mDidInit = PR_TRUE; - } - return rv; - } + nsresult rv = nsLeafFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); aStatus = NS_FRAME_COMPLETE; SetupCachedSizes(mCacheSize, mCachedMaxElementSize, aDesiredSize); - return NS_OK; + return rv; } @@ -347,9 +340,72 @@ nsFormControlFrame::GetWidgetInitData(nsIPresContext* aPresContext) return nsnull; } -void -nsFormControlFrame::PostCreateWidget(nsIPresContext* aPresContext, nscoord& aWidth, nscoord& aHeight) + +nsresult +nsFormControlFrame::RegUnRegAccessKey(nsIPresContext* aPresContext, nsIFrame * aFrame, PRBool aDoReg) { +#if 0 + NS_ASSERTION(aPresContext, "aPresContext is NULL in RegUnRegAccessKey!"); + NS_ASSERTION(aFrame, "aFrame is NULL in RegUnRegAccessKey!"); + + nsresult rv = NS_ERROR_FAILURE; + nsAutoString accessKey; + + if (aFrame != nsnull) { + nsCOMPtr content; + if (NS_SUCCEEDED(aFrame->GetContent(getter_AddRefs(content)))) { +#if 1 + PRInt32 nameSpaceID; + content->GetNameSpaceID(nameSpaceID); + nsAutoString resultValue; + rv = content->GetAttribute(nameSpaceID, nsHTMLAtoms::accesskey, accessKey); +#else + nsCOMPtr inputElement(do_QueryInterface(content)); + if (inputElement) { + rv = inputElement->GetAccessKey(accessKey); + } else { + nsCOMPtr textarea(do_QueryInterface(content)); + if (textarea) { + rv = textarea->GetAccessKey(accessKey); + } else { + nsCOMPtr label(do_QueryInterface(content)); + if (label) { + rv = label->GetAccessKey(accessKey); + } else { + nsCOMPtr legend(do_QueryInterface(content)); + if (legend) { + rv = legend->GetAccessKey(accessKey); + } else { + nsCOMPtr btn(do_QueryInterface(content)); + if (btn) { + rv = btn->GetAccessKey(accessKey); + } + } + } + } + } +#endif + } + } + + if (NS_CONTENT_ATTR_NOT_THERE != rv) { + nsCOMPtr stateManager; + if (NS_SUCCEEDED(aPresContext->GetEventStateManager(getter_AddRefs(stateManager)))) { + if (aDoReg) { + return stateManager->RegisterAccessKey(aFrame, (PRUint32)accessKey.First()); + } else { + return stateManager->UnregisterAccessKey(aFrame); + } + } + } +#endif + return NS_ERROR_FAILURE; +} + +void +nsFormControlFrame::InitializeControl(nsIPresContext* aPresContext) +{ + RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); } void diff --git a/layout/forms/nsFormControlFrame.h b/layout/forms/nsFormControlFrame.h index 23fd99880586..f5b8a139f4b2 100644 --- a/layout/forms/nsFormControlFrame.h +++ b/layout/forms/nsFormControlFrame.h @@ -31,11 +31,14 @@ #include "nsLeafFrame.h" #include "nsCoord.h" #include "nsIStyleContext.h" +#include "nsIPresContext.h" +#include "nsCOMPtr.h" class nsIView; class nsIPresContext; class nsStyleCoord; class nsFormFrame; +class nsIFocusableContent; #define CSS_NOTSET -1 #define ATTR_NOTSET -1 @@ -152,11 +155,9 @@ public: virtual void ControlChanged(nsIPresContext* aPresContext) {} /** - * Perform opertations after the widget associated with this frame has been - * created. + * Chance to Initialize to a defualt value */ - virtual void PostCreateWidget(nsIPresContext* aPresContext, - nscoord& aWidth, nscoord& aHeight); + virtual void InitializeControl(nsIPresContext* aPresContext); virtual void SetFocus(PRBool aOn = PR_TRUE, PRBool aRepaint = PR_FALSE); virtual void ScrollIntoView(nsIPresContext* aPresContext); @@ -221,6 +222,8 @@ public: nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + // AccessKey Helper function + static nsresult RegUnRegAccessKey(nsIPresContext* aPresContext, nsIFrame * aFrame, PRBool aDoReg); protected: @@ -301,6 +304,8 @@ protected: nscoord mSuggestedWidth; nscoord mSuggestedHeight; + nsCOMPtr mPresContext; + // Reflow Optimization nsSize mCacheSize; nsSize mCachedMaxElementSize; diff --git a/layout/forms/nsFormControlHelper.cpp b/layout/forms/nsFormControlHelper.cpp index bb3614c00557..dc24f6195e79 100644 --- a/layout/forms/nsFormControlHelper.cpp +++ b/layout/forms/nsFormControlHelper.cpp @@ -453,7 +453,7 @@ nsFormControlHelper::CalculateSize (nsIPresContext* aPresContext, // need to set charWidth and aDesiredSize.height charWidth = GetTextSize(aPresContext, aFrame, 1, aDesiredSize, aRendContext); col = (col <= 0) ? 15 : col; // XXX why a default of 15 pixels, why hide it - // XXX this conflicts with a default of 20 found in nsTextControlFrame. + // XXX this conflicts with a default of 20 found in nsGfxTextControlFrame. aDesiredSize.width = NSIntPixelsToTwips(col, p2t); } else { col = (col <= 0) ? 1 : col; // XXX why a default of 1 char, why hide it diff --git a/layout/forms/nsGfxButtonControlFrame.cpp b/layout/forms/nsGfxButtonControlFrame.cpp index adbea904cacd..653af3cc93c8 100644 --- a/layout/forms/nsGfxButtonControlFrame.cpp +++ b/layout/forms/nsGfxButtonControlFrame.cpp @@ -332,7 +332,7 @@ nsGfxButtonControlFrame::Reflow(nsIPresContext* aPresContext, nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); } -#if 1 +#if 0 nsresult skiprv = nsFormControlFrame::SkipResizeReflow(mCacheSize, mCachedMaxElementSize, aPresContext, aDesiredSize, aReflowState, aStatus); @@ -362,6 +362,12 @@ nsGfxButtonControlFrame::Reflow(nsIPresContext* aPresContext, aPresContext->GetCompatibilityMode(&mode); if (mode == eCompatibility_NavQuirks) { + // nsHTMLButtonControlFrame::Reflow registers it for Standard Mode + // and sets up mPresContext + if (eReflowReason_Initial == aReflowState.reason) { + mPresContext = aPresContext; + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); + } // Do NavQuirks Sizing and layout rv = DoNavQuirksReflow(aPresContext, aDesiredSize, aReflowState, aStatus); } else { diff --git a/layout/forms/nsGfxCheckboxControlFrame.cpp b/layout/forms/nsGfxCheckboxControlFrame.cpp index 135aaa523b01..423eac39b719 100644 --- a/layout/forms/nsGfxCheckboxControlFrame.cpp +++ b/layout/forms/nsGfxCheckboxControlFrame.cpp @@ -27,9 +27,12 @@ #include "nsFormFrame.h" #include "nsIFormControl.h" #include "nsIContent.h" -#include "nsWidgetsCID.h" #include "nsIComponentManager.h" +#include "nsHTMLAtoms.h" +#include "nsINameSpaceManager.h" +#include "nsIPresState.h" +//------------------------------------------------------------ nsresult NS_NewGfxCheckboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) { @@ -46,18 +49,156 @@ NS_NewGfxCheckboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) } +//------------------------------------------------------------ // Initialize GFX-rendered state nsGfxCheckboxControlFrame::nsGfxCheckboxControlFrame() : mChecked(eOff) { } +//---------------------------------------------------------------------- +// nsISupports +//---------------------------------------------------------------------- +// Frames are not refcounted, no need to AddRef +NS_IMETHODIMP +nsGfxCheckboxControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!"); + if ( !aInstancePtr ) + return NS_ERROR_NULL_POINTER; + if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) { + *aInstancePtr = (void*)(nsIStatefulFrame*) this; + return NS_OK; + } + return nsFormControlFrame::QueryInterface(aIID, aInstancePtr); +} +//------------------------------------------------------------ +// +// Init +// +// We need to override this in order to see if we're a tristate checkbox. +// +NS_IMETHODIMP +nsGfxCheckboxControlFrame::Init(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) +{ + nsFormControlFrame::Init ( aPresContext, aContent, aParent, aContext, aPrevInFlow ); + + // figure out if we're a tristate at the start. This may change later on once + // we've been running for a while, so more code is in AttributeChanged() to pick + // that up. Regardless, we need this check when initializing. + nsAutoString value; + nsresult res = mContent->GetAttribute ( kNameSpaceID_None, GetTristateAtom(), value ); + if ( res == NS_CONTENT_ATTR_HAS_VALUE ) + mIsTristate = PR_TRUE; + + // give the attribute a default value so it's always present, if we're a tristate + if ( IsTristateCheckbox() ) + mContent->SetAttribute ( kNameSpaceID_None, GetTristateValueAtom(), "0", PR_FALSE ); + + return NS_OK; +} + +//------------------------------------------------------------ +// +// GetTristateAtom [static] +// +// Use a lazily instantiated static initialization scheme to create an atom that +// represents the attribute set when this should be a tri-state checkbox. +// +// Does NOT addref! +// +nsIAtom* +nsGfxCheckboxControlFrame :: GetTristateAtom ( ) +{ + return nsHTMLAtoms::moz_tristate; +} + +//------------------------------------------------------------ +// +// GetTristateValueAtom [static] +// +// Use a lazily instantiated static initialization scheme to create an atom that +// represents the attribute that holds the value when the button is a tri-state (since +// we can't use "checked"). +// +// Does NOT addref! +// +nsIAtom* +nsGfxCheckboxControlFrame :: GetTristateValueAtom ( ) +{ + return nsHTMLAtoms::moz_tristatevalue; +} + +//------------------------------------------------------------ +// +// AttributeChanged +// +// Override to check for the attribute that determines if we're a normal or a +// tristate checkbox. If we notice a switch from one to the other, we need +// to adjust the proper attributes in the content model accordingly. +// +// Also, since the value of a tri-state is kept in a separate attribute (we +// can't use "checked" because it's a boolean), we have to notice it changing +// here. +// +NS_IMETHODIMP +nsGfxCheckboxControlFrame::AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aHint) +{ + if ( aAttribute == GetTristateAtom() ) { + nsAutoString value; + nsresult res = mContent->GetAttribute ( kNameSpaceID_None, GetTristateAtom(), value ); + PRBool isNowTristate = (res == NS_CONTENT_ATTR_HAS_VALUE); + if ( isNowTristate != mIsTristate ) + SwitchModesWithEmergencyBrake(aPresContext, isNowTristate); + } + else if ( aAttribute == GetTristateValueAtom() ) { + // ignore this change if we're not a tri-state checkbox + if ( IsTristateCheckbox() ) { + nsAutoString value; + nsresult res = mContent->GetAttribute ( kNameSpaceID_None, GetTristateValueAtom(), value ); + if ( res == NS_CONTENT_ATTR_HAS_VALUE ) + SetCheckboxControlFrameState(aPresContext, value); + } + } + else + return nsFormControlFrame::AttributeChanged(aPresContext, aChild, aNameSpaceID, aAttribute, aHint); + + return NS_OK; +} + +//------------------------------------------------------------ +// +// InitializeControl +// +// Set the default checked state of the checkbox. +// +void +nsGfxCheckboxControlFrame::InitializeControl(nsIPresContext* aPresContext) +{ + nsFormControlFrame::InitializeControl(aPresContext); + + PRBool checked = PR_FALSE; + nsresult result = GetDefaultCheckState(&checked); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + SetCheckboxState (aPresContext, checked ? eOn : eOff ); + } +} + +//------------------------------------------------------------ void nsGfxCheckboxControlFrame::PaintCheckBox(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) { aRenderingContext.PushState(); @@ -111,6 +252,7 @@ nsGfxCheckboxControlFrame::PaintCheckBox(nsIPresContext* aPresContext, } +//------------------------------------------------------------ // // PaintMixedMark // @@ -155,6 +297,7 @@ nsGfxCheckboxControlFrame::PaintMixedMark ( nsIRenderingContext& aRenderingConte } // PaintMixedMark +//------------------------------------------------------------ NS_METHOD nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -167,7 +310,7 @@ nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, return NS_OK; // Paint the background - Inherited::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { // Paint the checkmark PaintCheckBox(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); @@ -176,20 +319,232 @@ nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, } -nsCheckboxControlFrame::CheckState -nsGfxCheckboxControlFrame :: GetCheckboxState ( ) +//------------------------------------------------------------ +nsGfxCheckboxControlFrame::CheckState +nsGfxCheckboxControlFrame::GetCheckboxState ( ) { return mChecked; } +//------------------------------------------------------------ void -nsGfxCheckboxControlFrame :: SetCheckboxState (nsIPresContext* aPresContext, - nsCheckboxControlFrame::CheckState aValue ) +nsGfxCheckboxControlFrame::SetCheckboxState (nsIPresContext* aPresContext, + nsGfxCheckboxControlFrame::CheckState aValue ) { mChecked = aValue; nsFormControlHelper::ForceDrawFrame(aPresContext, this); } +//------------------------------------------------------------ +void nsGfxCheckboxControlFrame::GetCheckboxControlFrameState(nsString& aValue) +{ + CheckStateToString(GetCheckboxState(), aValue); +} + + +//------------------------------------------------------------ +void nsGfxCheckboxControlFrame::SetCheckboxControlFrameState(nsIPresContext* aPresContext, + const nsString& aValue) +{ + CheckState state = StringToCheckState(aValue); + SetCheckboxState(aPresContext, state); +} + +//------------------------------------------------------------ +NS_IMETHODIMP nsGfxCheckboxControlFrame::SetProperty(nsIPresContext* aPresContext, + nsIAtom* aName, + const nsString& aValue) +{ + if (nsHTMLAtoms::checked == aName) + SetCheckboxControlFrameState(aPresContext, aValue); + else + return nsFormControlFrame::SetProperty(aPresContext, aName, aValue); + + return NS_OK; +} + + +//------------------------------------------------------------ +NS_IMETHODIMP nsGfxCheckboxControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) +{ + if (nsHTMLAtoms::checked == aName) + GetCheckboxControlFrameState(aValue); + else + return nsFormControlFrame::GetProperty(aName, aValue); + + return NS_OK; +} + +//------------------------------------------------------------ +PRInt32 +nsGfxCheckboxControlFrame::GetMaxNumValues() +{ + return 1; +} + +//------------------------------------------------------------ +PRBool +nsGfxCheckboxControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) +{ + nsAutoString name; + nsresult nameResult = GetName(&name); + if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_HAS_VALUE != nameResult)) { + return PR_FALSE; + } + + PRBool result = PR_TRUE; + CheckState state = GetCheckboxState(); + + nsAutoString value; + nsresult valueResult = GetValue(&value); + + if (eOn != state) { + result = PR_FALSE; + } else { + if (NS_CONTENT_ATTR_HAS_VALUE != valueResult) { + aValues[0] = "on"; + } else { + aValues[0] = value; + } + aNames[0] = name; + aNumValues = 1; + } + + return result; +} + +//------------------------------------------------------------ +void +nsGfxCheckboxControlFrame::Reset(nsIPresContext* aPresContext) +{ + PRBool checked; + GetDefaultCheckState(&checked); + SetCheckboxState (aPresContext, checked ? eOn : eOff ); +} + + +//------------------------------------------------------------ +// +// CheckStateToString +// +// Converts from a CheckState to a string +// +void +nsGfxCheckboxControlFrame::CheckStateToString ( CheckState inState, nsString& outStateAsString ) +{ + switch ( inState ) { + case eOn: + outStateAsString = NS_STRING_TRUE; + break; + + case eOff: + outStateAsString = NS_STRING_FALSE; + break; + + case eMixed: + outStateAsString = "2"; + break; + } +} // CheckStateToString + + +//------------------------------------------------------------ +// +// StringToCheckState +// +// Converts from a string to a CheckState enum +// +nsGfxCheckboxControlFrame::CheckState +nsGfxCheckboxControlFrame::StringToCheckState ( const nsString & aStateAsString ) +{ + if ( aStateAsString == NS_STRING_TRUE ) + return eOn; + else if ( aStateAsString == NS_STRING_FALSE ) + return eOff; + + // not true and not false means mixed + return eMixed; + +} // StringToCheckState + + +//------------------------------------------------------------ +// +// SwitchModesWithEmergencyBrake +// +// Since we use an attribute to decide if we're a tristate box or not, this can change +// at any time. Since we have to use separate attributes to store the values depending +// on the mode, we have to convert from one to the other. +// +void +nsGfxCheckboxControlFrame::SwitchModesWithEmergencyBrake ( nsIPresContext* aPresContext, + PRBool inIsNowTristate ) +{ + if ( inIsNowTristate ) { + // we were a normal checkbox, and now we're a tristate. That means that the + // state of the checkbox was in "checked" and needs to be copied over into + // our parallel attribute. + nsAutoString value; + CheckStateToString ( GetCheckboxState(), value ); + mContent->SetAttribute ( kNameSpaceID_None, GetTristateValueAtom(), value, PR_FALSE ); + } + else { + // we were a tri-state checkbox, and now we're a normal checkbox. The current + // state is already up to date (because it's always up to date). We just have + // to make sure it's not mixed. If it is, just set it to checked. Remove our + // parallel attribute so that we're nice and HTML4 compliant. + if ( GetCheckboxState() == eMixed ) + SetCheckboxState(aPresContext, eOn); + mContent->UnsetAttribute ( kNameSpaceID_None, GetTristateValueAtom(), PR_FALSE ); + } + + // switch! + mIsTristate = inIsNowTristate; + +} // SwitchModesWithEmergencyBrake + +//---------------------------------------------------------------------- +// nsIStatefulFrame +//---------------------------------------------------------------------- +NS_IMETHODIMP nsGfxCheckboxControlFrame::GetStateType(nsIPresContext* aPresContext, + nsIStatefulFrame::StateType* aStateType) +{ + *aStateType=nsIStatefulFrame::eCheckboxType; + return NS_OK; +} + +NS_IMETHODIMP nsGfxCheckboxControlFrame::SaveState(nsIPresContext* aPresContext, + nsIPresState** aState) +{ + // Construct a pres state. + NS_NewPresState(aState); // The addref happens here. + + // This string will hold a single item, whether or not we're checked. + nsAutoString stateString; + GetCheckboxControlFrameState(stateString); + (*aState)->SetStateProperty("checked", stateString); + + return NS_OK; +} + +NS_IMETHODIMP nsGfxCheckboxControlFrame::RestoreState(nsIPresContext* aPresContext, + nsIPresState* aState) +{ + if (!mDidInit) { + mPresContext = aPresContext; + InitializeControl(aPresContext); + mDidInit = PR_TRUE; + } + nsAutoString string; + aState->GetStateProperty("checked", string); + SetCheckboxControlFrameState(aPresContext, string); + return NS_OK; +} + +//------------------------------------------------------------ +// Extra Debug Methods +//------------------------------------------------------------ #ifdef DEBUG_rodsXXX NS_IMETHODIMP nsGfxCheckboxControlFrame::Reflow(nsIPresContext* aPresContext, @@ -197,7 +552,7 @@ nsGfxCheckboxControlFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - nsresult rv = nsNativeFormControlFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + nsresult rv = nsFormControlFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); COMPARE_QUIRK_SIZE("nsGfxCheckboxControlFrame", 13, 13) return rv; diff --git a/layout/forms/nsGfxCheckboxControlFrame.h b/layout/forms/nsGfxCheckboxControlFrame.h index 588deb65d03b..c227a02159ae 100644 --- a/layout/forms/nsGfxCheckboxControlFrame.h +++ b/layout/forms/nsGfxCheckboxControlFrame.h @@ -22,13 +22,13 @@ #ifndef nsGfxCheckboxControlFrame_h___ #define nsGfxCheckboxControlFrame_h___ -#include "nsCheckboxControlFrame.h" +#include "nsFormControlFrame.h" +#include "nsIStatefulFrame.h" -class nsGfxCheckboxControlFrame : public nsCheckboxControlFrame { -private: - typedef nsCheckboxControlFrame Inherited; - +class nsGfxCheckboxControlFrame : public nsFormControlFrame, + public nsIStatefulFrame +{ public: nsGfxCheckboxControlFrame(); @@ -37,17 +37,43 @@ public: return MakeFrameName("CheckboxControl", aResult); } #endif + // this should be protected, but VC6 is lame. + enum CheckState { eOff, eOn, eMixed } ; - // overrides base class HandleEvent to do nothing - // events are handled by the DOM - NS_IMETHOD HandleEvent(nsIPresContext* aPresContext, - nsGUIEvent* aEvent, - nsEventStatus* aEventStatus) { return NS_OK; } + NS_IMETHOD Init(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) ; + + NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aHint) ; NS_IMETHOD Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer); + + void InitializeControl(nsIPresContext* aPresContext); + + // nsIFormControlFrame + NS_IMETHOD SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsString& aValue); + NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); + virtual void Reset(nsIPresContext* aPresContext); + virtual PRInt32 GetMaxNumValues(); + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + + // nsIStatefulFrame + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); + NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); + NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); + + #ifdef DEBUG_rodsXXX NS_IMETHOD Reflow(nsIPresContext* aCX, nsHTMLReflowMetrics& aDesiredSize, @@ -56,8 +82,35 @@ public: #endif protected: - virtual CheckState GetCheckboxState(); - virtual void SetCheckboxState(nsIPresContext* aPresContext, CheckState aValue); + + // native/gfx implementations need to implement needs. + CheckState GetCheckboxState(); + void SetCheckboxState(nsIPresContext* aPresContext, CheckState aValue); + + // Utility methods for implementing SetProperty/GetProperty + void SetCheckboxControlFrameState(nsIPresContext* aPresContext, + const nsString& aValue); + void GetCheckboxControlFrameState(nsString& aValue); + + // utility routine for converting from DOM values to internal enum + void CheckStateToString ( CheckState inState, nsString& outStateAsString ) ; + CheckState StringToCheckState ( const nsString & aStateAsString ) ; + + // figure out if we're a tri-state checkbox. + PRBool IsTristateCheckbox ( ) const { return mIsTristate; } + + // we just became a tri-state, or we just lost tri-state status. fix up + // the attributes for the new mode. + void SwitchModesWithEmergencyBrake ( nsIPresContext* aPresContext, + PRBool inIsNowTristate ) ; + + // for tri-state checkbox. meaningless for normal HTML + PRBool mIsTristate; + + static nsIAtom* GetTristateAtom() ; + static nsIAtom* GetTristateValueAtom() ; + +protected: virtual void PaintCheckBox(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -68,7 +121,11 @@ protected: //GFX-rendered state variables CheckState mChecked; - + +private: + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } + NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } + }; #endif diff --git a/layout/forms/nsGfxRadioControlFrame.cpp b/layout/forms/nsGfxRadioControlFrame.cpp index 04073d8cf0e1..e005f53b1620 100644 --- a/layout/forms/nsGfxRadioControlFrame.cpp +++ b/layout/forms/nsGfxRadioControlFrame.cpp @@ -21,7 +21,6 @@ */ #include "nsGfxRadioControlFrame.h" -#include "nsIRadioButton.h" #include "nsHTMLAtoms.h" #include "nsHTMLParts.h" #include "nsFormFrame.h" @@ -31,6 +30,8 @@ #include "nsIComponentManager.h" #include "nsCOMPtr.h" #include "nsCSSRendering.h" +#include "nsIPresState.h" +#include "nsINameSpaceManager.h" nsresult @@ -57,11 +58,31 @@ nsGfxRadioControlFrame::nsGfxRadioControlFrame() nsGfxRadioControlFrame::~nsGfxRadioControlFrame() { - NS_IF_RELEASE(mRadioButtonFaceStyle); + NS_IF_RELEASE(mRadioButtonFaceStyle); } -//-------------------------------------------------------------- +// Frames are not refcounted, no need to AddRef +NS_IMETHODIMP +nsGfxRadioControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(NS_GET_IID(nsIRadioControlFrame))) { + *aInstancePtr = (void*) ((nsIRadioControlFrame*) this); + return NS_OK; + } + if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) { + *aInstancePtr = (void*) ((nsIStatefulFrame*) this); + return NS_OK; + } + + return nsFormControlFrame::QueryInterface(aIID, aInstancePtr); +} + +//-------------------------------------------------------------- NS_IMETHODIMP nsGfxRadioControlFrame::GetAdditionalStyleContext(PRInt32 aIndex, nsIStyleContext** aStyleContext) const @@ -82,6 +103,7 @@ nsGfxRadioControlFrame::GetAdditionalStyleContext(PRInt32 aIndex, return NS_OK; } +//-------------------------------------------------------------- NS_IMETHODIMP nsGfxRadioControlFrame::SetAdditionalStyleContext(PRInt32 aIndex, nsIStyleContext* aStyleContext) @@ -99,7 +121,69 @@ nsGfxRadioControlFrame::SetAdditionalStyleContext(PRInt32 aIndex, return NS_OK; } +//-------------------------------------------------------------- +NS_IMETHODIMP nsGfxRadioControlFrame::SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsString& aValue) +{ + if (nsHTMLAtoms::checked == aName) { + PRBool state = (aValue == NS_STRING_TRUE) ? PR_TRUE : PR_FALSE; + SetRadioState(aPresContext, state); + if (mFormFrame) { + mFormFrame->OnRadioChecked(aPresContext, *this, state); + } + } + else { + return nsFormControlFrame::SetProperty(aPresContext, aName, aValue); + } + + return NS_OK; +} + +//-------------------------------------------------------------- +NS_IMETHODIMP nsGfxRadioControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) +{ + // Return the value of the property from the widget it is not null. + // If is null, assume the widget is GFX-rendered and return a member variable instead. + + if (nsHTMLAtoms::checked == aName) { + nsFormControlHelper::GetBoolString(GetRadioState(), aValue); + } else { + return nsFormControlFrame::GetProperty(aName, aValue); + } + + return NS_OK; +} + +//-------------------------------------------------------------- +PRBool +nsGfxRadioControlFrame::GetChecked(PRBool aGetInitialValue) +{ + PRBool checked = PR_FALSE; + if (PR_TRUE == aGetInitialValue) { + GetDefaultCheckState(&checked); + } + else { + GetCurrentCheckState(&checked); + } + return(checked); +} + +//-------------------------------------------------------------- +void +nsGfxRadioControlFrame::SetChecked(nsIPresContext* aPresContext, PRBool aValue, PRBool aSetInitialValue) +{ + if (aSetInitialValue) { + if (aValue) { + mContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::checked, nsAutoString("1"), PR_FALSE); // XXX should be "empty" value + } else { + mContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::checked, nsAutoString("0"), PR_FALSE); + } + } + + SetRadioState(aPresContext, aValue); +} + +//-------------------------------------------------------------- NS_IMETHODIMP nsGfxRadioControlFrame::SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioButtonFaceStyleContext) { @@ -108,6 +192,47 @@ nsGfxRadioControlFrame::SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioBu return NS_OK; } +//-------------------------------------------------------------- +PRBool +nsGfxRadioControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) +{ + nsAutoString name; + nsresult result = GetName(&name); + if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_HAS_VALUE != result)) { + return PR_FALSE; + } + + PRBool state = GetRadioState(); + + if(PR_TRUE != state) { + return PR_FALSE; + } + + nsAutoString value; + result = GetValue(&value); + + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + aValues[0] = value; + } else { + aValues[0] = "on"; + } + aNames[0] = name; + aNumValues = 1; + + return PR_TRUE; +} + +//-------------------------------------------------------------- +void +nsGfxRadioControlFrame::Reset(nsIPresContext* aPresContext) +{ + PRBool checked = PR_TRUE; + GetDefaultCheckState(&checked); + SetCurrentCheckState(checked); +} + +//-------------------------------------------------------------- void nsGfxRadioControlFrame::PaintRadioButton(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -141,6 +266,7 @@ nsGfxRadioControlFrame::PaintRadioButton(nsIPresContext* aPresContext, } } +//-------------------------------------------------------------- NS_METHOD nsGfxRadioControlFrame::Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -153,7 +279,7 @@ nsGfxRadioControlFrame::Paint(nsIPresContext* aPresContext, return NS_OK; // Paint the background - Inherited::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { PaintRadioButton(aPresContext, aRenderingContext, aDirtyRect); @@ -162,17 +288,79 @@ nsGfxRadioControlFrame::Paint(nsIPresContext* aPresContext, } +//-------------------------------------------------------------- PRBool nsGfxRadioControlFrame::GetRadioState() { return mChecked; } +//-------------------------------------------------------------- void nsGfxRadioControlFrame::SetRadioState(nsIPresContext* aPresContext, PRBool aValue) { mChecked = aValue; nsFormControlHelper::ForceDrawFrame(aPresContext, this); } +void +nsGfxRadioControlFrame::InitializeControl(nsIPresContext* aPresContext) +{ + nsFormControlFrame::InitializeControl(aPresContext); + + // set the widget to the initial state + PRBool checked = PR_FALSE; + nsresult result = GetDefaultCheckState(&checked); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + SetRadioState(aPresContext, checked); + } +} + +//---------------------------------------------------------------------- +// nsIStatefulFrame +//---------------------------------------------------------------------- +NS_IMETHODIMP +nsGfxRadioControlFrame::GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType) +{ + *aStateType = nsIStatefulFrame::eRadioType; + return NS_OK; +} + +//---------------------------------------------------------------------- +NS_IMETHODIMP +nsGfxRadioControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) +{ + // Construct a pres state. + NS_NewPresState(aState); // The addref happens here. + + // This string will hold a single item, whether or not we're checked. + nsAutoString stateString; + nsFormControlHelper::GetBoolString(GetRadioState(), stateString); + (*aState)->SetStateProperty("checked", stateString); + + return NS_OK; +} + + + +//---------------------------------------------------------------------- +NS_IMETHODIMP +nsGfxRadioControlFrame::RestoreState(nsIPresContext* aPresContext, nsIPresState* aState) +{ + if (!mDidInit) { + mPresContext = aPresContext; + InitializeControl(aPresContext); + mDidInit = PR_TRUE; + } + nsAutoString string; + aState->GetStateProperty("checked", string); + PRBool state = (string == NS_STRING_TRUE) ? PR_TRUE : PR_FALSE; + SetRadioState(aPresContext, state); + return NS_OK; +} + + +//---------------------------------------------------------------------- +// Extra Debug Helper Methods +//---------------------------------------------------------------------- #ifdef DEBUG_rodsXXX NS_IMETHODIMP nsGfxRadioControlFrame::Reflow(nsIPresContext* aPresContext, diff --git a/layout/forms/nsGfxRadioControlFrame.h b/layout/forms/nsGfxRadioControlFrame.h index 73ac07ce1172..e40ab27e3f80 100644 --- a/layout/forms/nsGfxRadioControlFrame.h +++ b/layout/forms/nsGfxRadioControlFrame.h @@ -23,25 +23,36 @@ #ifndef nsGfxRadioControlFrame_h___ #define nsGfxRadioControlFrame_h___ -#include "nsRadioControlFrame.h" +#include "nsFormControlFrame.h" +#include "nsIStatefulFrame.h" +#include "nsIRadioControlFrame.h" // nsGfxRadioControlFrame #define NS_GFX_RADIO_CONTROL_FRAME_FACE_CONTEXT_INDEX 0 // for additional style contexts #define NS_GFX_RADIO_CONTROL_FRAME_LAST_CONTEXT_INDEX 0 -class nsGfxRadioControlFrame : public nsRadioControlFrame +class nsGfxRadioControlFrame : public nsFormControlFrame, + public nsIStatefulFrame, + public nsIRadioControlFrame + { private: - typedef nsRadioControlFrame Inherited; public: nsGfxRadioControlFrame(); ~nsGfxRadioControlFrame(); //nsIRadioControlFrame methods + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); NS_IMETHOD SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioButtonFaceStyleContext); + + virtual PRBool GetChecked(PRBool aGetInitialValue); + virtual void SetChecked(nsIPresContext* aPresContext, PRBool aValue, PRBool aSetInitialValue); + + void InitializeControl(nsIPresContext* aPresContext); + NS_IMETHOD GetAdditionalStyleContext(PRInt32 aIndex, nsIStyleContext** aStyleContext) const; NS_IMETHOD SetAdditionalStyleContext(PRInt32 aIndex, @@ -67,6 +78,21 @@ public: nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect); + virtual PRInt32 GetMaxNumValues() { return 1; } + + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + virtual void Reset(nsIPresContext* aPresContext); + + // nsIFormControlFrame + NS_IMETHOD SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsString& aValue); + NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); + + //nsIStatefulFrame + NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); + NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); + NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); + ///XXX: End o the temporary methods #ifdef DEBUG_rodsXXX NS_IMETHOD Reflow(nsIPresContext* aCX, diff --git a/layout/forms/nsHTMLButtonControlFrame.cpp b/layout/forms/nsHTMLButtonControlFrame.cpp index e4d3a18f7c90..e67c837e8495 100644 --- a/layout/forms/nsHTMLButtonControlFrame.cpp +++ b/layout/forms/nsHTMLButtonControlFrame.cpp @@ -92,6 +92,7 @@ nsHTMLButtonControlFrame::nsHTMLButtonControlFrame() nsHTMLButtonControlFrame::~nsHTMLButtonControlFrame() { + nsFormControlFrame::RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); if (mFormFrame) { mFormFrame->RemoveFormControlFrame(*this); mFormFrame = nsnull; @@ -513,15 +514,18 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext* aPresContext, nsReflowStatus& aStatus) { if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { + mPresContext = aPresContext; + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); } +#if 0 nsresult skiprv = nsFormControlFrame::SkipResizeReflow(mCacheSize, mCachedMaxElementSize, aPresContext, aDesiredSize, aReflowState, aStatus); if (NS_SUCCEEDED(skiprv)) { return skiprv; } - +#endif // XXX remove the following when the reflow state is fixed ButtonHack((nsHTMLReflowState&)aReflowState, "html4 button"); @@ -662,10 +666,12 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext* aPresContext, //aDesiredSize.width += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; //aDesiredSize.height += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; +#if 1 //adjust our max element size, if necessary if (aDesiredSize.maxElementSize) { aDesiredSize.AddBorderPaddingToMaxElementSize(aReflowState.mComputedBorderPadding); } +#endif aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; @@ -684,11 +690,10 @@ nsHTMLButtonControlFrame::GetSkipSides() const } NS_IMETHODIMP -nsHTMLButtonControlFrame::GetFont(nsIPresContext* aPresContext, - const nsFont*& aFont) +nsHTMLButtonControlFrame::GetFont(nsIPresContext* aPresContext, + const nsFont*& aFont) { - nsFormControlHelper::GetFont(this, aPresContext, mStyleContext, aFont); - return NS_OK; + return nsFormControlHelper::GetFont(this, aPresContext, mStyleContext, aFont); } NS_IMETHODIMP diff --git a/layout/forms/nsHTMLButtonControlFrame.h b/layout/forms/nsHTMLButtonControlFrame.h index 4c902e08dd07..84ea27d4f860 100644 --- a/layout/forms/nsHTMLButtonControlFrame.h +++ b/layout/forms/nsHTMLButtonControlFrame.h @@ -156,6 +156,8 @@ protected: PRBool mDidInit; nsButtonFrameRenderer mRenderer; + nsCOMPtr mPresContext; + //Resize Reflow OpitmizationSize; nsSize mCacheSize; nsSize mCachedMaxElementSize; diff --git a/layout/forms/nsImageControlFrame.cpp b/layout/forms/nsImageControlFrame.cpp index 9f6ec1af23f6..378216ed8bb7 100644 --- a/layout/forms/nsImageControlFrame.cpp +++ b/layout/forms/nsImageControlFrame.cpp @@ -46,6 +46,7 @@ #include "nsIHTMLAttributes.h" #include "nsGenericHTMLElement.h" #include "nsFormFrame.h" +#include "nsFormControlFrame.h" //Enumeration of possible mouse states used to detect mouse clicks /*enum nsMouseState { @@ -145,6 +146,8 @@ protected: nsCursor mPreviousCursor; nsRect mTranslatedRect; PRBool mGotFocus; + + nsCOMPtr mPresContext; }; @@ -160,6 +163,8 @@ nsImageControlFrame::nsImageControlFrame() nsImageControlFrame::~nsImageControlFrame() { + nsFormControlFrame::RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); + if (mFormFrame) { mFormFrame->RemoveFormControlFrame(*this); mFormFrame = nsnull; @@ -255,6 +260,8 @@ nsImageControlFrame::Reflow(nsIPresContext* aPresContext, nsReflowStatus& aStatus) { if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { + mPresContext = aPresContext; + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); // add ourself as an nsIFormControlFrame nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); } diff --git a/layout/forms/nsLegendFrame.cpp b/layout/forms/nsLegendFrame.cpp index 17146e4e3497..dec875b4bcfa 100644 --- a/layout/forms/nsLegendFrame.cpp +++ b/layout/forms/nsLegendFrame.cpp @@ -30,7 +30,6 @@ #include "nsIFrame.h" #include "nsISupports.h" #include "nsIAtom.h" -#include "nsIPresContext.h" #include "nsIHTMLContent.h" #include "nsHTMLIIDs.h" #include "nsHTMLParts.h" @@ -39,6 +38,7 @@ #include "nsStyleConsts.h" #include "nsStyleUtil.h" #include "nsFont.h" +#include "nsFormControlFrame.h" static NS_DEFINE_IID(kLegendFrameCID, NS_LEGEND_FRAME_CID); static NS_DEFINE_IID(kIDOMHTMLLegendElementIID, NS_IDOMHTMLLEGENDELEMENT_IID); @@ -63,6 +63,11 @@ nsLegendFrame::nsLegendFrame() { } +nsLegendFrame::~nsLegendFrame() +{ + nsFormControlFrame::RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); +} + // Frames are not refcounted, no need to AddRef NS_IMETHODIMP nsLegendFrame::QueryInterface(REFNSIID aIID, void** aInstancePtrResult) @@ -78,6 +83,20 @@ nsLegendFrame::QueryInterface(REFNSIID aIID, void** aInstancePtrResult) return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtrResult); } +NS_IMETHODIMP +nsLegendFrame::Reflow(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + if (eReflowReason_Initial == aReflowState.reason) { + mPresContext = aPresContext; + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); + } + return nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); +} + + PRInt32 nsLegendFrame::GetAlign() { PRInt32 intValue = NS_STYLE_TEXT_ALIGN_LEFT; diff --git a/layout/forms/nsLegendFrame.h b/layout/forms/nsLegendFrame.h index 6401d24caa40..5538435740cd 100644 --- a/layout/forms/nsLegendFrame.h +++ b/layout/forms/nsLegendFrame.h @@ -24,6 +24,9 @@ #define nsLegendFrame_h___ #include "nsAreaFrame.h" +#include "nsIPresContext.h" +#include "nsCOMPtr.h" + class nsIContent; class nsIFrame; class nsIPresContext; @@ -38,14 +41,23 @@ class nsLegendFrame : public nsAreaFrame { public: nsLegendFrame(); + virtual ~nsLegendFrame(); NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + NS_IMETHOD Reflow(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus); + + #ifdef NS_DEBUG NS_IMETHOD GetFrameName(nsString& aResult) const; #endif PRInt32 GetAlign(); + + nsCOMPtr mPresContext; }; diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index 0fbda31ccddf..b26a500b157a 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/layout/forms/nsListControlFrame.cpp @@ -123,6 +123,8 @@ nsListControlFrame::nsListControlFrame() //--------------------------------------------------------- nsListControlFrame::~nsListControlFrame() { + nsFormControlFrame::RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); + // if list is dropped down // make sure it gets rolled up if (IsInDropDownMode()) { @@ -286,7 +288,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { -#ifdef DEBUG_rodsXXX +#ifdef DEBUG_rods printf("nsListControlFrame::Reflow Reason: "); switch (aReflowState.reason) { case eReflowReason_Initial:printf("eReflowReason_Initial\n");break; @@ -355,6 +357,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, mHasBeenInitialized = PR_TRUE; InitSelectionCache(-1); // Reset sel cache so as not to send event Reset(mPresContext); +#if 1 nsCOMPtr cmd; nsresult rv = NS_NewHTMLReflowCommand(getter_AddRefs(cmd), this, nsIReflowCommand::StyleChanged); if (NS_FAILED(rv)) { return rv; } @@ -368,10 +371,18 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, rv = shell->AppendReflowCommand(cmd); // must do this next line regardless of result of AppendReflowCommand shell->ExitReflowLock(PR_TRUE); +#else + if (mParent) { + nsCOMPtr shell; + nsresult rv = mPresContext->GetShell(getter_AddRefs(shell)); + mState |= NS_FRAME_IS_DIRTY; + mParent->ReflowDirtyChild(shell, (nsIFrame*) this); + } +#endif } } -#if 1 +#if 0 nsresult skiprv = nsFormControlFrame::SkipResizeReflow(mCacheSize, mCachedMaxElementSize, aPresContext, aDesiredSize, aReflowState, aStatus); if (NS_SUCCEEDED(skiprv)) { @@ -416,6 +427,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, // Add the list frame as a child of the form if (IsInDropDownMode() == PR_FALSE && !mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); } @@ -1943,6 +1955,17 @@ nsListControlFrame::AddOption(nsIPresContext* aPresContext, PRInt32 aIndex) Reset(aPresContext); // this sets mSelectedIndex to the defaulted selection wasReset = PR_TRUE; } + +#if DEBUG_rods + { + nsAutoString text = "No Value"; + nsresult rv = option->GetLabel(text); + if (NS_CONTENT_ATTR_NOT_THERE == rv || 0 == text.Length()) { + option->GetText(text); + } + printf("this %p Index: %d [%s] CB: %p\n", this, aIndex, text.ToNewCString(), mComboboxFrame); //leaks + } +#endif } } @@ -2468,6 +2491,30 @@ void nsListControlFrame::ResetSelectedItem() } } +//---------------------------------------------------------------------- +// helper +//---------------------------------------------------------------------- +PRBool +nsListControlFrame::IsLeftButton(nsIDOMEvent* aMouseEvent) +{ + // only allow selection with the left button + nsCOMPtr mouseEvent = do_QueryInterface(aMouseEvent); + if (mouseEvent) { + PRUint16 whichButton; + if (NS_SUCCEEDED(mouseEvent->GetButton(&whichButton))) { + if (whichButton != 1) { + aMouseEvent->PreventDefault(); + aMouseEvent->PreventCapture(); + aMouseEvent->PreventBubble(); + return PR_FALSE; + } else { + return PR_TRUE; + } + } + } + return PR_FALSE; +} + //---------------------------------------------------------------------- // nsIDOMMouseListener //---------------------------------------------------------------------- @@ -2479,6 +2526,11 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent) return NS_OK; } + // only allow selection with the left button + if (!IsLeftButton(aMouseEvent)) { + return NS_ERROR_FAILURE; // means consume event + } + // Check to see if the disabled option was clicked on // NS_ERROR_FAILURE is returned is it isn't over an option PRBool optionIsDisabled; @@ -2512,7 +2564,11 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent) UpdateSelection(PR_TRUE, PR_FALSE, mContent); } - return NS_OK; + aMouseEvent->PreventDefault(); + aMouseEvent->PreventCapture(); + aMouseEvent->PreventBubble(); + return NS_ERROR_FAILURE; + //return NS_OK; } //--------------------------------------------------------- @@ -2579,6 +2635,11 @@ nsListControlFrame::MouseDown(nsIDOMEvent* aMouseEvent) return NS_OK; } + // only allow selection with the left button + if (!IsLeftButton(aMouseEvent)) { + return NS_ERROR_FAILURE; // means consume event + } + // Check to see if the disabled option was clicked on // NS_ERROR_FAILURE is returned is it isn't over an option PRBool optionIsDisabled; @@ -2673,7 +2734,11 @@ nsListControlFrame::MouseDown(nsIDOMEvent* aMouseEvent) } } } - return NS_OK; + aMouseEvent->PreventDefault(); + aMouseEvent->PreventCapture(); + aMouseEvent->PreventBubble(); + return NS_ERROR_FAILURE; //consumes event + //return NS_OK; } //---------------------------------------------------------------------- diff --git a/layout/forms/nsListControlFrame.h b/layout/forms/nsListControlFrame.h index 8ae637d86979..d17e78ccb289 100644 --- a/layout/forms/nsListControlFrame.h +++ b/layout/forms/nsListControlFrame.h @@ -217,6 +217,7 @@ protected: PRBool HasSameContent(nsIFrame* aFrame1, nsIFrame* aFrame2); void HandleListSelection(nsIDOMEvent * aDOMEvent); PRInt32 GetSelectedIndexFromFrame(nsIFrame *aHitFrame); + PRBool IsLeftButton(nsIDOMEvent* aMouseEvent); // onChange detection nsresult InitSelectionCache(PRInt32 aLength); diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp index ee48bfd89157..804e77d78361 100644 --- a/layout/forms/nsTextControlFrame.cpp +++ b/layout/forms/nsTextControlFrame.cpp @@ -30,7 +30,6 @@ #include "nsIHTMLContent.h" #include "nsHTMLIIDs.h" #include "nsITextWidget.h" -#include "nsITextAreaWidget.h" #include "nsWidgetsCID.h" #include "nsSize.h" #include "nsString.h" diff --git a/layout/html/forms/src/makefile.win b/layout/html/forms/src/makefile.win index e8985ef58976..cf0b6f1404f8 100644 --- a/layout/html/forms/src/makefile.win +++ b/layout/html/forms/src/makefile.win @@ -34,13 +34,8 @@ CPPSRCS= \ nsListControlFrame.cpp \ nsFormFrame.cpp \ nsFormControlFrame.cpp \ - nsButtonControlFrame.cpp \ - nsCheckboxControlFrame.cpp \ nsFileControlFrame.cpp \ - nsRadioControlFrame.cpp \ - nsTextControlFrame.cpp \ nsGfxTextControlFrame.cpp \ - nsTextControlFrame.cpp \ nsFieldSetFrame.cpp \ nsLegendFrame.cpp \ nsHTMLButtonControlFrame.cpp \ @@ -51,7 +46,6 @@ CPPSRCS= \ nsGfxCheckboxControlFrame.cpp \ nsGfxRadioControlFrame.cpp \ nsGfxAutoTextControlFrame.cpp \ - nsNativeFormControlFrame.cpp \ nsRadioControlGroup.cpp CPP_OBJS= \ @@ -61,11 +55,7 @@ CPP_OBJS= \ .\$(OBJDIR)\nsListControlFrame.obj \ .\$(OBJDIR)\nsFormFrame.obj \ .\$(OBJDIR)\nsFormControlFrame.obj \ - .\$(OBJDIR)\nsButtonControlFrame.obj \ - .\$(OBJDIR)\nsCheckboxControlFrame.obj \ .\$(OBJDIR)\nsFileControlFrame.obj \ - .\$(OBJDIR)\nsRadioControlFrame.obj \ - .\$(OBJDIR)\nsTextControlFrame.obj \ .\$(OBJDIR)\nsGfxTextControlFrame.obj \ .\$(OBJDIR)\nsFieldSetFrame.obj \ .\$(OBJDIR)\nsLegendFrame.obj \ @@ -77,7 +67,6 @@ CPP_OBJS= \ .\$(OBJDIR)\nsGfxCheckboxControlFrame.obj \ .\$(OBJDIR)\nsGfxRadioControlFrame.obj \ .\$(OBJDIR)\nsGfxAutoTextControlFrame.obj \ - .\$(OBJDIR)\nsNativeFormControlFrame.obj \ .\$(OBJDIR)\nsRadioControlGroup.obj diff --git a/layout/html/forms/src/nsCheckboxControlFrame.h b/layout/html/forms/src/nsCheckboxControlFrame.h index c6d6d491fc31..489f3c6d4694 100644 --- a/layout/html/forms/src/nsCheckboxControlFrame.h +++ b/layout/html/forms/src/nsCheckboxControlFrame.h @@ -22,7 +22,7 @@ #ifndef nsCheckboxControlFrame_h___ #define nsCheckboxControlFrame_h___ -#include "nsNativeFormControlFrame.h" +#include "nsFormControlFrame.h" #include "nsIStatefulFrame.h" class nsIPresState; @@ -47,7 +47,7 @@ class nsIPresState; // become checked since "mixed" doesn't exist on normal checkboxes. // -class nsCheckboxControlFrame : public nsNativeFormControlFrame, +class nsCheckboxControlFrame : public nsFormControlFrame, public nsIStatefulFrame { public: diff --git a/layout/html/forms/src/nsComboboxControlFrame.cpp b/layout/html/forms/src/nsComboboxControlFrame.cpp index d12709f7f36c..062ca5fd1444 100644 --- a/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/layout/html/forms/src/nsComboboxControlFrame.cpp @@ -132,6 +132,8 @@ nsComboboxControlFrame::~nsComboboxControlFrame() NS_IF_RELEASE(mPresContext); NS_IF_RELEASE(mDisplayContent); NS_IF_RELEASE(mButtonContent); + + nsFormControlFrame::RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); } //-------------------------------------------------------------- @@ -265,9 +267,7 @@ nsComboboxControlFrame::Reset(nsIPresContext* aPresContext) } void -nsComboboxControlFrame::PostCreateWidget(nsIPresContext* aPresContext, - nscoord& aWidth, - nscoord& aHeight) +nsComboboxControlFrame::InitializeControl(nsIPresContext* aPresContext) { Reset(aPresContext); } @@ -724,6 +724,7 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*,this)); } @@ -912,6 +913,7 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, #else // DO_OLD_REFLOW #ifdef DEBUG_rods +nsComboboxControlFrame * pCB = nsnull; static int myCounter = 0; #endif @@ -922,7 +924,8 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, nsReflowStatus& aStatus) { #ifdef DEBUG_rods - printf("****** nsComboboxControlFrame::Reflow %d Reason: ", myCounter++); + //if (pCB) { + printf("%p ****** nsComboboxControlFrame::Reflow %d Reason: ", this, myCounter++); switch (aReflowState.reason) { case eReflowReason_Initial: printf("eReflowReason_Initial\n");break; @@ -933,6 +936,7 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, break; case eReflowReason_StyleChange:printf("eReflowReason_StyleChange\n");break; } + //} #endif #if 0 @@ -993,7 +997,9 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // 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); @@ -1001,14 +1007,34 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, 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, firstPassState.availableWidth, firstPassState.availableHeight); - return NS_OK; + 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 } } @@ -1035,10 +1061,15 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, 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. @@ -1077,7 +1108,9 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, 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); @@ -1103,7 +1136,9 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, } } else { +#ifdef DEBUG_rods printf("*************************************\n"); +#endif // for debug ------- PRInt32 length = 0; mListControlFrame->GetNumberOfOptions(&length); @@ -1129,7 +1164,9 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // 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); @@ -1146,7 +1183,9 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, 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; @@ -1156,6 +1195,8 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, } 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. @@ -1164,18 +1205,15 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, aDesiredSize.maxElementSize->height = aDesiredSize.height; } - nsRect absoluteTwips; - nsRect absolutePixels; - GetAbsoluteFramePosition(aPresContext, this, absoluteTwips, absolutePixels); - PositionDropdown(aPresContext, aDesiredSize.height, absoluteTwips, absolutePixels); - 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; } @@ -1422,6 +1460,7 @@ nsComboboxControlFrame::SelectionChanged() } if (shouldSetValue) { rv = htmlContent->SetHTMLAttribute(nsHTMLAtoms::value, mTextStr, PR_TRUE); +#if 1 if (NS_SUCCEEDED(rv)) { nsIFrame* displayFrame = GetDisplayFrame(mPresContext); @@ -1439,6 +1478,15 @@ nsComboboxControlFrame::SelectionChanged() 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 } } } @@ -1467,12 +1515,19 @@ nsComboboxControlFrame::DoneAddingContent(PRBool aIsDone) NS_IMETHODIMP nsComboboxControlFrame::AddOption(nsIPresContext* aPresContext, PRInt32 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); NS_RELEASE(listFrame); } // If we added the first option, we might need to select it. diff --git a/layout/html/forms/src/nsComboboxControlFrame.h b/layout/html/forms/src/nsComboboxControlFrame.h index 781bfab81e3b..4359a810c32c 100644 --- a/layout/html/forms/src/nsComboboxControlFrame.h +++ b/layout/html/forms/src/nsComboboxControlFrame.h @@ -35,8 +35,6 @@ #include "nsIRollupListener.h" #include "nsIPresState.h" -class nsButtonControlFrame; -class nsTextControlFrame; class nsFormFrame; class nsIView; class nsStyleContext; @@ -109,9 +107,7 @@ public: NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); void SetFocus(PRBool aOn, PRBool aRepaint); void ScrollIntoView(nsIPresContext* aPresContext); - virtual void PostCreateWidget(nsIPresContext* aPresContext, - nscoord& aWidth, - nscoord& aHeight); + virtual void InitializeControl(nsIPresContext* aPresContext); virtual PRBool IsSuccessful(nsIFormControlFrame* aSubmitter); virtual void SetFormFrame(nsFormFrame* aFormFrame) { mFormFrame = aFormFrame; } virtual void Reset(nsIPresContext* aPresContext); diff --git a/layout/html/forms/src/nsFileControlFrame.cpp b/layout/html/forms/src/nsFileControlFrame.cpp index 3bf49fa1a111..e7940b39b3d9 100644 --- a/layout/html/forms/src/nsFileControlFrame.cpp +++ b/layout/html/forms/src/nsFileControlFrame.cpp @@ -22,9 +22,7 @@ #include "nsFileControlFrame.h" #include "nsFormFrame.h" -#include "nsButtonControlFrame.h" -#include "nsTextControlFrame.h" -#include "nsNativeTextControlFrame.h" // XXX: remove when frame construction is done properly +#include "nsGfxTextControlFrame.h" #include "nsIContent.h" #include "prtypes.h" #include "nsIAtom.h" @@ -312,7 +310,7 @@ nsFileControlFrame::SetInitialChildList(nsIPresContext* aPresContext, * frame constuctor create the frame and its implementation. So we are given the text * node from the constructor and we find it in our tree. */ -nsTextControlFrame* +nsGfxTextControlFrame* nsFileControlFrame::GetTextControlFrame(nsIPresContext* aPresContext, nsIFrame* aStart) { // find the text control frame. @@ -331,13 +329,13 @@ nsFileControlFrame::GetTextControlFrame(nsIPresContext* aPresContext, nsIFrame* value.ToUpperCase(); nsString txt("TEXT"); if (value == txt) { - return (nsTextControlFrame*)childFrame; + return (nsGfxTextControlFrame*)childFrame; } } } // if not continue looking - nsTextControlFrame* frame = GetTextControlFrame(aPresContext, childFrame); + nsGfxTextControlFrame* frame = GetTextControlFrame(aPresContext, childFrame); if (frame) return frame; diff --git a/layout/html/forms/src/nsFileControlFrame.h b/layout/html/forms/src/nsFileControlFrame.h index c90cf974c434..6f2b9260d63c 100644 --- a/layout/html/forms/src/nsFileControlFrame.h +++ b/layout/html/forms/src/nsFileControlFrame.h @@ -30,8 +30,7 @@ #include "nsIStatefulFrame.h" class nsIPresState; -class nsButtonControlFrame; -class nsTextControlFrame; +class nsGfxTextControlFrame; class nsFormFrame; class nsISupportsArray; class nsIHTMLContent; @@ -176,7 +175,7 @@ protected: virtual PRIntn GetSkipSides() const; - nsTextControlFrame* mTextFrame; + nsGfxTextControlFrame* mTextFrame; nsFormFrame* mFormFrame; nsIHTMLContent* mTextContent; nsString* mCachedState; @@ -184,7 +183,7 @@ protected: nsIPresContext* mPresContext; // weak reference private: - nsTextControlFrame* GetTextControlFrame(nsIPresContext* aPresContext, + nsGfxTextControlFrame* GetTextControlFrame(nsIPresContext* aPresContext, nsIFrame* aStart); NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } diff --git a/layout/html/forms/src/nsFormControlFrame.cpp b/layout/html/forms/src/nsFormControlFrame.cpp index 8017cca428ca..dba52d5f2304 100644 --- a/layout/html/forms/src/nsFormControlFrame.cpp +++ b/layout/html/forms/src/nsFormControlFrame.cpp @@ -54,6 +54,11 @@ #include "nsStyleUtil.h" #include "nsINameSpaceManager.h" #include "nsIDOMHTMLInputElement.h" +#include "nsIDOMHTMLLabelElement.h" +#include "nsIDOMHTMLTextAreaElement.h" +#include "nsIDOMHTMLLegendElement.h" +#include "nsIDOMHTMLButtonElement.h" +#include "nsIEventStateManager.h" static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID); @@ -87,6 +92,7 @@ nsFormControlFrame::~nsFormControlFrame() mFormFrame->RemoveRadioControlFrame(this); mFormFrame = nsnull; } + RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); } // Frames are not refcounted, no need to AddRef @@ -302,42 +308,29 @@ nsFormControlFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + if (!mDidInit) { + mPresContext = aPresContext; + InitializeControl(aPresContext); + mDidInit = PR_TRUE; + } + // add ourself as an nsIFormControlFrame if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); } + nsresult skiprv = SkipResizeReflow(mCacheSize, mCachedMaxElementSize, aPresContext, aDesiredSize, aReflowState, aStatus); if (NS_SUCCEEDED(skiprv)) { return skiprv; } - nsWidgetRendering mode; - aPresContext->GetWidgetRenderingMode(&mode); - if (eWidgetRendering_Native == mode) { - GetDesiredSize(aPresContext, aReflowState, aDesiredSize, mWidgetSize); - - if (!mDidInit) { - PostCreateWidget(aPresContext, aDesiredSize.width, aDesiredSize.height); - mDidInit = PR_TRUE; - } - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; - - } else { - nsresult rv = nsLeafFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); - if (!mDidInit) { - //GetDesiredSize(aPresContext, aReflowState, aDesiredSize); - PostCreateWidget(aPresContext, aDesiredSize.width, aDesiredSize.height); - mDidInit = PR_TRUE; - } - return rv; - } + nsresult rv = nsLeafFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); aStatus = NS_FRAME_COMPLETE; SetupCachedSizes(mCacheSize, mCachedMaxElementSize, aDesiredSize); - return NS_OK; + return rv; } @@ -347,9 +340,72 @@ nsFormControlFrame::GetWidgetInitData(nsIPresContext* aPresContext) return nsnull; } -void -nsFormControlFrame::PostCreateWidget(nsIPresContext* aPresContext, nscoord& aWidth, nscoord& aHeight) + +nsresult +nsFormControlFrame::RegUnRegAccessKey(nsIPresContext* aPresContext, nsIFrame * aFrame, PRBool aDoReg) { +#if 0 + NS_ASSERTION(aPresContext, "aPresContext is NULL in RegUnRegAccessKey!"); + NS_ASSERTION(aFrame, "aFrame is NULL in RegUnRegAccessKey!"); + + nsresult rv = NS_ERROR_FAILURE; + nsAutoString accessKey; + + if (aFrame != nsnull) { + nsCOMPtr content; + if (NS_SUCCEEDED(aFrame->GetContent(getter_AddRefs(content)))) { +#if 1 + PRInt32 nameSpaceID; + content->GetNameSpaceID(nameSpaceID); + nsAutoString resultValue; + rv = content->GetAttribute(nameSpaceID, nsHTMLAtoms::accesskey, accessKey); +#else + nsCOMPtr inputElement(do_QueryInterface(content)); + if (inputElement) { + rv = inputElement->GetAccessKey(accessKey); + } else { + nsCOMPtr textarea(do_QueryInterface(content)); + if (textarea) { + rv = textarea->GetAccessKey(accessKey); + } else { + nsCOMPtr label(do_QueryInterface(content)); + if (label) { + rv = label->GetAccessKey(accessKey); + } else { + nsCOMPtr legend(do_QueryInterface(content)); + if (legend) { + rv = legend->GetAccessKey(accessKey); + } else { + nsCOMPtr btn(do_QueryInterface(content)); + if (btn) { + rv = btn->GetAccessKey(accessKey); + } + } + } + } + } +#endif + } + } + + if (NS_CONTENT_ATTR_NOT_THERE != rv) { + nsCOMPtr stateManager; + if (NS_SUCCEEDED(aPresContext->GetEventStateManager(getter_AddRefs(stateManager)))) { + if (aDoReg) { + return stateManager->RegisterAccessKey(aFrame, (PRUint32)accessKey.First()); + } else { + return stateManager->UnregisterAccessKey(aFrame); + } + } + } +#endif + return NS_ERROR_FAILURE; +} + +void +nsFormControlFrame::InitializeControl(nsIPresContext* aPresContext) +{ + RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); } void diff --git a/layout/html/forms/src/nsFormControlFrame.h b/layout/html/forms/src/nsFormControlFrame.h index 23fd99880586..f5b8a139f4b2 100644 --- a/layout/html/forms/src/nsFormControlFrame.h +++ b/layout/html/forms/src/nsFormControlFrame.h @@ -31,11 +31,14 @@ #include "nsLeafFrame.h" #include "nsCoord.h" #include "nsIStyleContext.h" +#include "nsIPresContext.h" +#include "nsCOMPtr.h" class nsIView; class nsIPresContext; class nsStyleCoord; class nsFormFrame; +class nsIFocusableContent; #define CSS_NOTSET -1 #define ATTR_NOTSET -1 @@ -152,11 +155,9 @@ public: virtual void ControlChanged(nsIPresContext* aPresContext) {} /** - * Perform opertations after the widget associated with this frame has been - * created. + * Chance to Initialize to a defualt value */ - virtual void PostCreateWidget(nsIPresContext* aPresContext, - nscoord& aWidth, nscoord& aHeight); + virtual void InitializeControl(nsIPresContext* aPresContext); virtual void SetFocus(PRBool aOn = PR_TRUE, PRBool aRepaint = PR_FALSE); virtual void ScrollIntoView(nsIPresContext* aPresContext); @@ -221,6 +222,8 @@ public: nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + // AccessKey Helper function + static nsresult RegUnRegAccessKey(nsIPresContext* aPresContext, nsIFrame * aFrame, PRBool aDoReg); protected: @@ -301,6 +304,8 @@ protected: nscoord mSuggestedWidth; nscoord mSuggestedHeight; + nsCOMPtr mPresContext; + // Reflow Optimization nsSize mCacheSize; nsSize mCachedMaxElementSize; diff --git a/layout/html/forms/src/nsFormControlHelper.cpp b/layout/html/forms/src/nsFormControlHelper.cpp index bb3614c00557..dc24f6195e79 100644 --- a/layout/html/forms/src/nsFormControlHelper.cpp +++ b/layout/html/forms/src/nsFormControlHelper.cpp @@ -453,7 +453,7 @@ nsFormControlHelper::CalculateSize (nsIPresContext* aPresContext, // need to set charWidth and aDesiredSize.height charWidth = GetTextSize(aPresContext, aFrame, 1, aDesiredSize, aRendContext); col = (col <= 0) ? 15 : col; // XXX why a default of 15 pixels, why hide it - // XXX this conflicts with a default of 20 found in nsTextControlFrame. + // XXX this conflicts with a default of 20 found in nsGfxTextControlFrame. aDesiredSize.width = NSIntPixelsToTwips(col, p2t); } else { col = (col <= 0) ? 1 : col; // XXX why a default of 1 char, why hide it diff --git a/layout/html/forms/src/nsFormFrame.cpp b/layout/html/forms/src/nsFormFrame.cpp index 25158bbac94e..274efb8c3b5a 100644 --- a/layout/html/forms/src/nsFormFrame.cpp +++ b/layout/html/forms/src/nsFormFrame.cpp @@ -66,8 +66,7 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); #include "nsIDocument.h" #include "nsILinkHandler.h" -#include "nsRadioControlFrame.h" -#include "nsIRadioButton.h" +#include "nsGfxRadioControlFrame.h" #include "nsDocument.h" #include "nsIDOMHTMLFormElement.h" #include "nsIDOMNSHTMLFormElement.h" @@ -84,6 +83,7 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); // Get base target for submission #include "nsIHTMLContent.h" +#include "nsIDOMHTMLInputElement.h" #include "net.h" #include "xp_file.h" @@ -333,6 +333,32 @@ void nsFormFrame::RemoveFormControlFrame(nsIFormControlFrame& aFrame) mFormControls.RemoveElement(&aFrame); } +NS_IMETHODIMP +nsFormFrame::RemoveFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame) +{ + nsresult rv = NS_OK; + + nsIFormControlFrame* fcFrame = nsnull; + nsresult result = aOldFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + if ((NS_OK == result) || (nsnull != fcFrame)) { + PRInt32 type; + fcFrame->GetType(&type); + if (NS_FORM_INPUT_RADIO == type) { + nsRadioControlGroup * group; + nsAutoString name; + nsresult rv = GetRadioInfo(fcFrame, name, group); + if (NS_SUCCEEDED(rv) && nsnull != group) { + DoDefaultSelection(aPresContext, group, (nsGfxRadioControlFrame*)fcFrame); + } + } + } + + return nsBlockFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); +} + nsresult nsFormFrame::GetRadioInfo(nsIFormControlFrame* aFrame, nsString& aName, nsRadioControlGroup *& aGroup) @@ -359,6 +385,57 @@ nsresult nsFormFrame::GetRadioInfo(nsIFormControlFrame* aFrame, return NS_ERROR_FAILURE; } +void nsFormFrame::DoDefaultSelection(nsIPresContext* aPresContext, + nsRadioControlGroup * aGroup, + nsGfxRadioControlFrame * aRadioToIgnore) +{ + // If in standard mode, then a radio group MUST default + // to the first item in the group (it must be selected) + nsCompatibility mode; + aPresContext->GetCompatibilityMode(&mode); + if (eCompatibility_Standard == mode) { + // first find out if any have a default selection + PRInt32 i; + PRInt32 numItems = aGroup->GetNumRadios(); + PRBool oneIsSelected = PR_FALSE; + for (i=0;iGetRadioAt(i); + nsCOMPtr content; + radioBtn->GetContent(getter_AddRefs(content)); + if (content) { + nsCOMPtr input(do_QueryInterface(content)); + if (input) { + input->GetDefaultChecked(&oneIsSelected); + } + } + } + + // if there isn't a default selcted radio then + // select the firdst one in the group. + // if aRadioToIgnore is not null then it is being deleted + // so don't select that item, select the next one if there is one. + if (!oneIsSelected && numItems > 0) { + nsGfxRadioControlFrame * radioBtn = (nsGfxRadioControlFrame*) aGroup->GetRadioAt(0); + if (aRadioToIgnore != nsnull && aRadioToIgnore == radioBtn) { + if (numItems == 1) { + return; + } + radioBtn = (nsGfxRadioControlFrame*) aGroup->GetRadioAt(1); + } + nsCOMPtr content; + radioBtn->GetContent(getter_AddRefs(content)); + if (content) { + nsCOMPtr input(do_QueryInterface(content)); + if (input) { + input->SetChecked(PR_TRUE); + OnRadioChecked(aPresContext, *radioBtn, PR_TRUE); + } + } + } + } +} + + void nsFormFrame::AddFormControlFrame(nsIPresContext* aPresContext, nsIFormControlFrame& aFrame) { mFormControls.AppendElement(&aFrame); @@ -381,7 +458,7 @@ void nsFormFrame::AddFormControlFrame(nsIPresContext* aPresContext, nsIFormContr // radio group processing if (NS_FORM_INPUT_RADIO == type) { - nsRadioControlFrame* radioFrame = (nsRadioControlFrame*)&aFrame; + nsGfxRadioControlFrame* radioFrame = (nsGfxRadioControlFrame*)&aFrame; // gets the name of the radio group and the group nsRadioControlGroup * group; nsAutoString name; @@ -401,6 +478,7 @@ void nsFormFrame::AddFormControlFrame(nsIPresContext* aPresContext, nsIFormContr radioFrame->SetChecked(aPresContext, PR_FALSE, PR_TRUE); } } + DoDefaultSelection(aPresContext, group); } } @@ -411,7 +489,7 @@ void nsFormFrame::RemoveRadioControlFrame(nsIFormControlFrame * aFrame) // radio group processing if (NS_FORM_INPUT_RADIO == type) { - nsRadioControlFrame* radioFrame = (nsRadioControlFrame*)aFrame; + nsGfxRadioControlFrame* radioFrame = (nsGfxRadioControlFrame*)aFrame; // gets the name of the radio group and the group nsRadioControlGroup * group; nsAutoString name; @@ -423,7 +501,7 @@ void nsFormFrame::RemoveRadioControlFrame(nsIFormControlFrame * aFrame) } void -nsFormFrame::OnRadioChecked(nsIPresContext* aPresContext, nsRadioControlFrame& aControl, PRBool aChecked) +nsFormFrame::OnRadioChecked(nsIPresContext* aPresContext, nsGfxRadioControlFrame& aControl, PRBool aChecked) { nsString radioName; aControl.GetName(&radioName); @@ -437,7 +515,7 @@ nsFormFrame::OnRadioChecked(nsIPresContext* aPresContext, nsRadioControlFrame& a nsRadioControlGroup* group = (nsRadioControlGroup *) mRadioGroups.ElementAt(j); nsString groupName; group->GetName(groupName); - nsRadioControlFrame* checkedRadio = group->GetCheckedRadio(); + nsGfxRadioControlFrame* checkedRadio = group->GetCheckedRadio(); if (groupName.Equals(radioName)) { if (aChecked) { if (&aControl != checkedRadio) { diff --git a/layout/html/forms/src/nsFormFrame.h b/layout/html/forms/src/nsFormFrame.h index dd4507fdd05d..2dcf0a2463d9 100644 --- a/layout/html/forms/src/nsFormFrame.h +++ b/layout/html/forms/src/nsFormFrame.h @@ -34,7 +34,7 @@ class nsIFrame; class nsIPresContext; struct nsHTMLReflowState; class nsFormControlFrame; -class nsRadioControlFrame; +class nsGfxRadioControlFrame; class nsIFormControlFrame; class nsIDOMHTMLFormElement; class nsIDocument; @@ -52,6 +52,11 @@ public: NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); + NS_IMETHOD RemoveFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame); + // nsIFormManager NS_IMETHOD OnReset(nsIPresContext* aPresContext); @@ -60,7 +65,7 @@ public: // other methods - void OnRadioChecked(nsIPresContext* aPresContext, nsRadioControlFrame& aRadio, PRBool aChecked = PR_TRUE); + void OnRadioChecked(nsIPresContext* aPresContext, nsGfxRadioControlFrame& aRadio, PRBool aChecked = PR_TRUE); void AddFormControlFrame(nsIPresContext* aPresContext, nsIFormControlFrame& aFrame); static void AddFormControlFrame(nsIPresContext* aPresContext, nsIFrame& aFrame); @@ -93,6 +98,10 @@ protected: NS_IMETHOD_(nsrefcnt) Release(void); void RemoveRadioGroups(); + void DoDefaultSelection(nsIPresContext* aPresContext, + nsRadioControlGroup * aGroup, + nsGfxRadioControlFrame * aRadioToIgnore = nsnull); + nsresult ProcessValue(nsIFormProcessor& aFormProcessor, nsIFormControlFrame* aFrameControl, const nsString& aName, nsString& aNewValue); nsresult ProcessAsURLEncoded(nsIFormProcessor* aFormProcessor, PRBool aIsPost, nsString& aData, nsIFormControlFrame* aFrame); nsresult ProcessAsMultipart(nsIFormProcessor* aFormProcessor, nsIFileSpec*& aMultipartDataFile, nsIFormControlFrame* aFrame); diff --git a/layout/html/forms/src/nsGfxButtonControlFrame.cpp b/layout/html/forms/src/nsGfxButtonControlFrame.cpp index adbea904cacd..653af3cc93c8 100644 --- a/layout/html/forms/src/nsGfxButtonControlFrame.cpp +++ b/layout/html/forms/src/nsGfxButtonControlFrame.cpp @@ -332,7 +332,7 @@ nsGfxButtonControlFrame::Reflow(nsIPresContext* aPresContext, nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); } -#if 1 +#if 0 nsresult skiprv = nsFormControlFrame::SkipResizeReflow(mCacheSize, mCachedMaxElementSize, aPresContext, aDesiredSize, aReflowState, aStatus); @@ -362,6 +362,12 @@ nsGfxButtonControlFrame::Reflow(nsIPresContext* aPresContext, aPresContext->GetCompatibilityMode(&mode); if (mode == eCompatibility_NavQuirks) { + // nsHTMLButtonControlFrame::Reflow registers it for Standard Mode + // and sets up mPresContext + if (eReflowReason_Initial == aReflowState.reason) { + mPresContext = aPresContext; + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); + } // Do NavQuirks Sizing and layout rv = DoNavQuirksReflow(aPresContext, aDesiredSize, aReflowState, aStatus); } else { diff --git a/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp b/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp index 135aaa523b01..423eac39b719 100644 --- a/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp +++ b/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp @@ -27,9 +27,12 @@ #include "nsFormFrame.h" #include "nsIFormControl.h" #include "nsIContent.h" -#include "nsWidgetsCID.h" #include "nsIComponentManager.h" +#include "nsHTMLAtoms.h" +#include "nsINameSpaceManager.h" +#include "nsIPresState.h" +//------------------------------------------------------------ nsresult NS_NewGfxCheckboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) { @@ -46,18 +49,156 @@ NS_NewGfxCheckboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) } +//------------------------------------------------------------ // Initialize GFX-rendered state nsGfxCheckboxControlFrame::nsGfxCheckboxControlFrame() : mChecked(eOff) { } +//---------------------------------------------------------------------- +// nsISupports +//---------------------------------------------------------------------- +// Frames are not refcounted, no need to AddRef +NS_IMETHODIMP +nsGfxCheckboxControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!"); + if ( !aInstancePtr ) + return NS_ERROR_NULL_POINTER; + if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) { + *aInstancePtr = (void*)(nsIStatefulFrame*) this; + return NS_OK; + } + return nsFormControlFrame::QueryInterface(aIID, aInstancePtr); +} +//------------------------------------------------------------ +// +// Init +// +// We need to override this in order to see if we're a tristate checkbox. +// +NS_IMETHODIMP +nsGfxCheckboxControlFrame::Init(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) +{ + nsFormControlFrame::Init ( aPresContext, aContent, aParent, aContext, aPrevInFlow ); + + // figure out if we're a tristate at the start. This may change later on once + // we've been running for a while, so more code is in AttributeChanged() to pick + // that up. Regardless, we need this check when initializing. + nsAutoString value; + nsresult res = mContent->GetAttribute ( kNameSpaceID_None, GetTristateAtom(), value ); + if ( res == NS_CONTENT_ATTR_HAS_VALUE ) + mIsTristate = PR_TRUE; + + // give the attribute a default value so it's always present, if we're a tristate + if ( IsTristateCheckbox() ) + mContent->SetAttribute ( kNameSpaceID_None, GetTristateValueAtom(), "0", PR_FALSE ); + + return NS_OK; +} + +//------------------------------------------------------------ +// +// GetTristateAtom [static] +// +// Use a lazily instantiated static initialization scheme to create an atom that +// represents the attribute set when this should be a tri-state checkbox. +// +// Does NOT addref! +// +nsIAtom* +nsGfxCheckboxControlFrame :: GetTristateAtom ( ) +{ + return nsHTMLAtoms::moz_tristate; +} + +//------------------------------------------------------------ +// +// GetTristateValueAtom [static] +// +// Use a lazily instantiated static initialization scheme to create an atom that +// represents the attribute that holds the value when the button is a tri-state (since +// we can't use "checked"). +// +// Does NOT addref! +// +nsIAtom* +nsGfxCheckboxControlFrame :: GetTristateValueAtom ( ) +{ + return nsHTMLAtoms::moz_tristatevalue; +} + +//------------------------------------------------------------ +// +// AttributeChanged +// +// Override to check for the attribute that determines if we're a normal or a +// tristate checkbox. If we notice a switch from one to the other, we need +// to adjust the proper attributes in the content model accordingly. +// +// Also, since the value of a tri-state is kept in a separate attribute (we +// can't use "checked" because it's a boolean), we have to notice it changing +// here. +// +NS_IMETHODIMP +nsGfxCheckboxControlFrame::AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aHint) +{ + if ( aAttribute == GetTristateAtom() ) { + nsAutoString value; + nsresult res = mContent->GetAttribute ( kNameSpaceID_None, GetTristateAtom(), value ); + PRBool isNowTristate = (res == NS_CONTENT_ATTR_HAS_VALUE); + if ( isNowTristate != mIsTristate ) + SwitchModesWithEmergencyBrake(aPresContext, isNowTristate); + } + else if ( aAttribute == GetTristateValueAtom() ) { + // ignore this change if we're not a tri-state checkbox + if ( IsTristateCheckbox() ) { + nsAutoString value; + nsresult res = mContent->GetAttribute ( kNameSpaceID_None, GetTristateValueAtom(), value ); + if ( res == NS_CONTENT_ATTR_HAS_VALUE ) + SetCheckboxControlFrameState(aPresContext, value); + } + } + else + return nsFormControlFrame::AttributeChanged(aPresContext, aChild, aNameSpaceID, aAttribute, aHint); + + return NS_OK; +} + +//------------------------------------------------------------ +// +// InitializeControl +// +// Set the default checked state of the checkbox. +// +void +nsGfxCheckboxControlFrame::InitializeControl(nsIPresContext* aPresContext) +{ + nsFormControlFrame::InitializeControl(aPresContext); + + PRBool checked = PR_FALSE; + nsresult result = GetDefaultCheckState(&checked); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + SetCheckboxState (aPresContext, checked ? eOn : eOff ); + } +} + +//------------------------------------------------------------ void nsGfxCheckboxControlFrame::PaintCheckBox(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) { aRenderingContext.PushState(); @@ -111,6 +252,7 @@ nsGfxCheckboxControlFrame::PaintCheckBox(nsIPresContext* aPresContext, } +//------------------------------------------------------------ // // PaintMixedMark // @@ -155,6 +297,7 @@ nsGfxCheckboxControlFrame::PaintMixedMark ( nsIRenderingContext& aRenderingConte } // PaintMixedMark +//------------------------------------------------------------ NS_METHOD nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -167,7 +310,7 @@ nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, return NS_OK; // Paint the background - Inherited::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { // Paint the checkmark PaintCheckBox(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); @@ -176,20 +319,232 @@ nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, } -nsCheckboxControlFrame::CheckState -nsGfxCheckboxControlFrame :: GetCheckboxState ( ) +//------------------------------------------------------------ +nsGfxCheckboxControlFrame::CheckState +nsGfxCheckboxControlFrame::GetCheckboxState ( ) { return mChecked; } +//------------------------------------------------------------ void -nsGfxCheckboxControlFrame :: SetCheckboxState (nsIPresContext* aPresContext, - nsCheckboxControlFrame::CheckState aValue ) +nsGfxCheckboxControlFrame::SetCheckboxState (nsIPresContext* aPresContext, + nsGfxCheckboxControlFrame::CheckState aValue ) { mChecked = aValue; nsFormControlHelper::ForceDrawFrame(aPresContext, this); } +//------------------------------------------------------------ +void nsGfxCheckboxControlFrame::GetCheckboxControlFrameState(nsString& aValue) +{ + CheckStateToString(GetCheckboxState(), aValue); +} + + +//------------------------------------------------------------ +void nsGfxCheckboxControlFrame::SetCheckboxControlFrameState(nsIPresContext* aPresContext, + const nsString& aValue) +{ + CheckState state = StringToCheckState(aValue); + SetCheckboxState(aPresContext, state); +} + +//------------------------------------------------------------ +NS_IMETHODIMP nsGfxCheckboxControlFrame::SetProperty(nsIPresContext* aPresContext, + nsIAtom* aName, + const nsString& aValue) +{ + if (nsHTMLAtoms::checked == aName) + SetCheckboxControlFrameState(aPresContext, aValue); + else + return nsFormControlFrame::SetProperty(aPresContext, aName, aValue); + + return NS_OK; +} + + +//------------------------------------------------------------ +NS_IMETHODIMP nsGfxCheckboxControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) +{ + if (nsHTMLAtoms::checked == aName) + GetCheckboxControlFrameState(aValue); + else + return nsFormControlFrame::GetProperty(aName, aValue); + + return NS_OK; +} + +//------------------------------------------------------------ +PRInt32 +nsGfxCheckboxControlFrame::GetMaxNumValues() +{ + return 1; +} + +//------------------------------------------------------------ +PRBool +nsGfxCheckboxControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) +{ + nsAutoString name; + nsresult nameResult = GetName(&name); + if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_HAS_VALUE != nameResult)) { + return PR_FALSE; + } + + PRBool result = PR_TRUE; + CheckState state = GetCheckboxState(); + + nsAutoString value; + nsresult valueResult = GetValue(&value); + + if (eOn != state) { + result = PR_FALSE; + } else { + if (NS_CONTENT_ATTR_HAS_VALUE != valueResult) { + aValues[0] = "on"; + } else { + aValues[0] = value; + } + aNames[0] = name; + aNumValues = 1; + } + + return result; +} + +//------------------------------------------------------------ +void +nsGfxCheckboxControlFrame::Reset(nsIPresContext* aPresContext) +{ + PRBool checked; + GetDefaultCheckState(&checked); + SetCheckboxState (aPresContext, checked ? eOn : eOff ); +} + + +//------------------------------------------------------------ +// +// CheckStateToString +// +// Converts from a CheckState to a string +// +void +nsGfxCheckboxControlFrame::CheckStateToString ( CheckState inState, nsString& outStateAsString ) +{ + switch ( inState ) { + case eOn: + outStateAsString = NS_STRING_TRUE; + break; + + case eOff: + outStateAsString = NS_STRING_FALSE; + break; + + case eMixed: + outStateAsString = "2"; + break; + } +} // CheckStateToString + + +//------------------------------------------------------------ +// +// StringToCheckState +// +// Converts from a string to a CheckState enum +// +nsGfxCheckboxControlFrame::CheckState +nsGfxCheckboxControlFrame::StringToCheckState ( const nsString & aStateAsString ) +{ + if ( aStateAsString == NS_STRING_TRUE ) + return eOn; + else if ( aStateAsString == NS_STRING_FALSE ) + return eOff; + + // not true and not false means mixed + return eMixed; + +} // StringToCheckState + + +//------------------------------------------------------------ +// +// SwitchModesWithEmergencyBrake +// +// Since we use an attribute to decide if we're a tristate box or not, this can change +// at any time. Since we have to use separate attributes to store the values depending +// on the mode, we have to convert from one to the other. +// +void +nsGfxCheckboxControlFrame::SwitchModesWithEmergencyBrake ( nsIPresContext* aPresContext, + PRBool inIsNowTristate ) +{ + if ( inIsNowTristate ) { + // we were a normal checkbox, and now we're a tristate. That means that the + // state of the checkbox was in "checked" and needs to be copied over into + // our parallel attribute. + nsAutoString value; + CheckStateToString ( GetCheckboxState(), value ); + mContent->SetAttribute ( kNameSpaceID_None, GetTristateValueAtom(), value, PR_FALSE ); + } + else { + // we were a tri-state checkbox, and now we're a normal checkbox. The current + // state is already up to date (because it's always up to date). We just have + // to make sure it's not mixed. If it is, just set it to checked. Remove our + // parallel attribute so that we're nice and HTML4 compliant. + if ( GetCheckboxState() == eMixed ) + SetCheckboxState(aPresContext, eOn); + mContent->UnsetAttribute ( kNameSpaceID_None, GetTristateValueAtom(), PR_FALSE ); + } + + // switch! + mIsTristate = inIsNowTristate; + +} // SwitchModesWithEmergencyBrake + +//---------------------------------------------------------------------- +// nsIStatefulFrame +//---------------------------------------------------------------------- +NS_IMETHODIMP nsGfxCheckboxControlFrame::GetStateType(nsIPresContext* aPresContext, + nsIStatefulFrame::StateType* aStateType) +{ + *aStateType=nsIStatefulFrame::eCheckboxType; + return NS_OK; +} + +NS_IMETHODIMP nsGfxCheckboxControlFrame::SaveState(nsIPresContext* aPresContext, + nsIPresState** aState) +{ + // Construct a pres state. + NS_NewPresState(aState); // The addref happens here. + + // This string will hold a single item, whether or not we're checked. + nsAutoString stateString; + GetCheckboxControlFrameState(stateString); + (*aState)->SetStateProperty("checked", stateString); + + return NS_OK; +} + +NS_IMETHODIMP nsGfxCheckboxControlFrame::RestoreState(nsIPresContext* aPresContext, + nsIPresState* aState) +{ + if (!mDidInit) { + mPresContext = aPresContext; + InitializeControl(aPresContext); + mDidInit = PR_TRUE; + } + nsAutoString string; + aState->GetStateProperty("checked", string); + SetCheckboxControlFrameState(aPresContext, string); + return NS_OK; +} + +//------------------------------------------------------------ +// Extra Debug Methods +//------------------------------------------------------------ #ifdef DEBUG_rodsXXX NS_IMETHODIMP nsGfxCheckboxControlFrame::Reflow(nsIPresContext* aPresContext, @@ -197,7 +552,7 @@ nsGfxCheckboxControlFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - nsresult rv = nsNativeFormControlFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + nsresult rv = nsFormControlFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); COMPARE_QUIRK_SIZE("nsGfxCheckboxControlFrame", 13, 13) return rv; diff --git a/layout/html/forms/src/nsGfxCheckboxControlFrame.h b/layout/html/forms/src/nsGfxCheckboxControlFrame.h index 588deb65d03b..c227a02159ae 100644 --- a/layout/html/forms/src/nsGfxCheckboxControlFrame.h +++ b/layout/html/forms/src/nsGfxCheckboxControlFrame.h @@ -22,13 +22,13 @@ #ifndef nsGfxCheckboxControlFrame_h___ #define nsGfxCheckboxControlFrame_h___ -#include "nsCheckboxControlFrame.h" +#include "nsFormControlFrame.h" +#include "nsIStatefulFrame.h" -class nsGfxCheckboxControlFrame : public nsCheckboxControlFrame { -private: - typedef nsCheckboxControlFrame Inherited; - +class nsGfxCheckboxControlFrame : public nsFormControlFrame, + public nsIStatefulFrame +{ public: nsGfxCheckboxControlFrame(); @@ -37,17 +37,43 @@ public: return MakeFrameName("CheckboxControl", aResult); } #endif + // this should be protected, but VC6 is lame. + enum CheckState { eOff, eOn, eMixed } ; - // overrides base class HandleEvent to do nothing - // events are handled by the DOM - NS_IMETHOD HandleEvent(nsIPresContext* aPresContext, - nsGUIEvent* aEvent, - nsEventStatus* aEventStatus) { return NS_OK; } + NS_IMETHOD Init(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) ; + + NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aHint) ; NS_IMETHOD Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer); + + void InitializeControl(nsIPresContext* aPresContext); + + // nsIFormControlFrame + NS_IMETHOD SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsString& aValue); + NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); + virtual void Reset(nsIPresContext* aPresContext); + virtual PRInt32 GetMaxNumValues(); + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + + // nsIStatefulFrame + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); + NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); + NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); + + #ifdef DEBUG_rodsXXX NS_IMETHOD Reflow(nsIPresContext* aCX, nsHTMLReflowMetrics& aDesiredSize, @@ -56,8 +82,35 @@ public: #endif protected: - virtual CheckState GetCheckboxState(); - virtual void SetCheckboxState(nsIPresContext* aPresContext, CheckState aValue); + + // native/gfx implementations need to implement needs. + CheckState GetCheckboxState(); + void SetCheckboxState(nsIPresContext* aPresContext, CheckState aValue); + + // Utility methods for implementing SetProperty/GetProperty + void SetCheckboxControlFrameState(nsIPresContext* aPresContext, + const nsString& aValue); + void GetCheckboxControlFrameState(nsString& aValue); + + // utility routine for converting from DOM values to internal enum + void CheckStateToString ( CheckState inState, nsString& outStateAsString ) ; + CheckState StringToCheckState ( const nsString & aStateAsString ) ; + + // figure out if we're a tri-state checkbox. + PRBool IsTristateCheckbox ( ) const { return mIsTristate; } + + // we just became a tri-state, or we just lost tri-state status. fix up + // the attributes for the new mode. + void SwitchModesWithEmergencyBrake ( nsIPresContext* aPresContext, + PRBool inIsNowTristate ) ; + + // for tri-state checkbox. meaningless for normal HTML + PRBool mIsTristate; + + static nsIAtom* GetTristateAtom() ; + static nsIAtom* GetTristateValueAtom() ; + +protected: virtual void PaintCheckBox(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -68,7 +121,11 @@ protected: //GFX-rendered state variables CheckState mChecked; - + +private: + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } + NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } + }; #endif diff --git a/layout/html/forms/src/nsGfxListControlFrame.cpp b/layout/html/forms/src/nsGfxListControlFrame.cpp index 94fa011eee97..3c044ce848cc 100644 --- a/layout/html/forms/src/nsGfxListControlFrame.cpp +++ b/layout/html/forms/src/nsGfxListControlFrame.cpp @@ -125,6 +125,8 @@ nsGfxListControlFrame::nsGfxListControlFrame() //--------------------------------------------------------- nsGfxListControlFrame::~nsGfxListControlFrame() { + nsFormControlFrame::RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); + // if list is dropped down // make sure it gets rolled up if (IsInDropDownMode()) { @@ -375,6 +377,7 @@ nsGfxListControlFrame::Reflow(nsIPresContext* aPresContext, // Add the list frame as a child of the form if (IsInDropDownMode() == PR_FALSE && !mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); } @@ -583,8 +586,8 @@ nsGfxListControlFrame::Reflow(nsIPresContext* aPresContext, // for the list frame and use that as the max/minimum size for the contents if (visibleHeight == 0) { nsCOMPtr fontMet; - nsFormControlHelper::GetFrameFontFM(aPresContext, this, getter_AddRefs(fontMet)); - if (fontMet) { + nsresult res = nsFormControlHelper::GetFrameFontFM(aPresContext, this, getter_AddRefs(fontMet)); + if (NS_SUCCEEDED(res) && fontMet) { aReflowState.rendContext->SetFont(fontMet); fontMet->GetHeight(visibleHeight); mMaxHeight = visibleHeight; @@ -654,8 +657,7 @@ NS_IMETHODIMP nsGfxListControlFrame::GetFont(nsIPresContext* aPresContext, const nsFont*& aFont) { - nsFormControlHelper::GetFont(this, aPresContext, mStyleContext, aFont); - return NS_OK; + return nsFormControlHelper::GetFont(this, aPresContext, mStyleContext, aFont); } @@ -1459,10 +1461,7 @@ nsGfxListControlFrame::SetContentSelected(PRInt32 aIndex, PRBool aSelected) if (aSelected) { DisplaySelected(content); // Now that it is selected scroll to it - nsCOMPtr content(do_QueryInterface(content)); - if (content) { - ScrollToFrame(content); - } + ScrollToFrame(content); } else { DisplayDeselected(content); } diff --git a/layout/html/forms/src/nsGfxListControlFrame.h b/layout/html/forms/src/nsGfxListControlFrame.h index ea8240770a37..927e75bf52ff 100644 --- a/layout/html/forms/src/nsGfxListControlFrame.h +++ b/layout/html/forms/src/nsGfxListControlFrame.h @@ -89,7 +89,7 @@ public: NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); NS_IMETHOD GetMultiple(PRBool* aResult, nsIDOMHTMLSelectElement* aSelect = nsnull); NS_IMETHOD GetFont(nsIPresContext* aPresContext, - const nsFont*& aFont); + const nsFont*& aFont); NS_IMETHOD GetFormContent(nsIContent*& aContent) const; virtual void SetFocus(PRBool aOn = PR_TRUE, PRBool aRepaint = PR_FALSE); diff --git a/layout/html/forms/src/nsGfxRadioControlFrame.cpp b/layout/html/forms/src/nsGfxRadioControlFrame.cpp index 04073d8cf0e1..e005f53b1620 100644 --- a/layout/html/forms/src/nsGfxRadioControlFrame.cpp +++ b/layout/html/forms/src/nsGfxRadioControlFrame.cpp @@ -21,7 +21,6 @@ */ #include "nsGfxRadioControlFrame.h" -#include "nsIRadioButton.h" #include "nsHTMLAtoms.h" #include "nsHTMLParts.h" #include "nsFormFrame.h" @@ -31,6 +30,8 @@ #include "nsIComponentManager.h" #include "nsCOMPtr.h" #include "nsCSSRendering.h" +#include "nsIPresState.h" +#include "nsINameSpaceManager.h" nsresult @@ -57,11 +58,31 @@ nsGfxRadioControlFrame::nsGfxRadioControlFrame() nsGfxRadioControlFrame::~nsGfxRadioControlFrame() { - NS_IF_RELEASE(mRadioButtonFaceStyle); + NS_IF_RELEASE(mRadioButtonFaceStyle); } -//-------------------------------------------------------------- +// Frames are not refcounted, no need to AddRef +NS_IMETHODIMP +nsGfxRadioControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(NS_GET_IID(nsIRadioControlFrame))) { + *aInstancePtr = (void*) ((nsIRadioControlFrame*) this); + return NS_OK; + } + if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) { + *aInstancePtr = (void*) ((nsIStatefulFrame*) this); + return NS_OK; + } + + return nsFormControlFrame::QueryInterface(aIID, aInstancePtr); +} + +//-------------------------------------------------------------- NS_IMETHODIMP nsGfxRadioControlFrame::GetAdditionalStyleContext(PRInt32 aIndex, nsIStyleContext** aStyleContext) const @@ -82,6 +103,7 @@ nsGfxRadioControlFrame::GetAdditionalStyleContext(PRInt32 aIndex, return NS_OK; } +//-------------------------------------------------------------- NS_IMETHODIMP nsGfxRadioControlFrame::SetAdditionalStyleContext(PRInt32 aIndex, nsIStyleContext* aStyleContext) @@ -99,7 +121,69 @@ nsGfxRadioControlFrame::SetAdditionalStyleContext(PRInt32 aIndex, return NS_OK; } +//-------------------------------------------------------------- +NS_IMETHODIMP nsGfxRadioControlFrame::SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsString& aValue) +{ + if (nsHTMLAtoms::checked == aName) { + PRBool state = (aValue == NS_STRING_TRUE) ? PR_TRUE : PR_FALSE; + SetRadioState(aPresContext, state); + if (mFormFrame) { + mFormFrame->OnRadioChecked(aPresContext, *this, state); + } + } + else { + return nsFormControlFrame::SetProperty(aPresContext, aName, aValue); + } + + return NS_OK; +} + +//-------------------------------------------------------------- +NS_IMETHODIMP nsGfxRadioControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) +{ + // Return the value of the property from the widget it is not null. + // If is null, assume the widget is GFX-rendered and return a member variable instead. + + if (nsHTMLAtoms::checked == aName) { + nsFormControlHelper::GetBoolString(GetRadioState(), aValue); + } else { + return nsFormControlFrame::GetProperty(aName, aValue); + } + + return NS_OK; +} + +//-------------------------------------------------------------- +PRBool +nsGfxRadioControlFrame::GetChecked(PRBool aGetInitialValue) +{ + PRBool checked = PR_FALSE; + if (PR_TRUE == aGetInitialValue) { + GetDefaultCheckState(&checked); + } + else { + GetCurrentCheckState(&checked); + } + return(checked); +} + +//-------------------------------------------------------------- +void +nsGfxRadioControlFrame::SetChecked(nsIPresContext* aPresContext, PRBool aValue, PRBool aSetInitialValue) +{ + if (aSetInitialValue) { + if (aValue) { + mContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::checked, nsAutoString("1"), PR_FALSE); // XXX should be "empty" value + } else { + mContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::checked, nsAutoString("0"), PR_FALSE); + } + } + + SetRadioState(aPresContext, aValue); +} + +//-------------------------------------------------------------- NS_IMETHODIMP nsGfxRadioControlFrame::SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioButtonFaceStyleContext) { @@ -108,6 +192,47 @@ nsGfxRadioControlFrame::SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioBu return NS_OK; } +//-------------------------------------------------------------- +PRBool +nsGfxRadioControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) +{ + nsAutoString name; + nsresult result = GetName(&name); + if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_HAS_VALUE != result)) { + return PR_FALSE; + } + + PRBool state = GetRadioState(); + + if(PR_TRUE != state) { + return PR_FALSE; + } + + nsAutoString value; + result = GetValue(&value); + + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + aValues[0] = value; + } else { + aValues[0] = "on"; + } + aNames[0] = name; + aNumValues = 1; + + return PR_TRUE; +} + +//-------------------------------------------------------------- +void +nsGfxRadioControlFrame::Reset(nsIPresContext* aPresContext) +{ + PRBool checked = PR_TRUE; + GetDefaultCheckState(&checked); + SetCurrentCheckState(checked); +} + +//-------------------------------------------------------------- void nsGfxRadioControlFrame::PaintRadioButton(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -141,6 +266,7 @@ nsGfxRadioControlFrame::PaintRadioButton(nsIPresContext* aPresContext, } } +//-------------------------------------------------------------- NS_METHOD nsGfxRadioControlFrame::Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -153,7 +279,7 @@ nsGfxRadioControlFrame::Paint(nsIPresContext* aPresContext, return NS_OK; // Paint the background - Inherited::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { PaintRadioButton(aPresContext, aRenderingContext, aDirtyRect); @@ -162,17 +288,79 @@ nsGfxRadioControlFrame::Paint(nsIPresContext* aPresContext, } +//-------------------------------------------------------------- PRBool nsGfxRadioControlFrame::GetRadioState() { return mChecked; } +//-------------------------------------------------------------- void nsGfxRadioControlFrame::SetRadioState(nsIPresContext* aPresContext, PRBool aValue) { mChecked = aValue; nsFormControlHelper::ForceDrawFrame(aPresContext, this); } +void +nsGfxRadioControlFrame::InitializeControl(nsIPresContext* aPresContext) +{ + nsFormControlFrame::InitializeControl(aPresContext); + + // set the widget to the initial state + PRBool checked = PR_FALSE; + nsresult result = GetDefaultCheckState(&checked); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + SetRadioState(aPresContext, checked); + } +} + +//---------------------------------------------------------------------- +// nsIStatefulFrame +//---------------------------------------------------------------------- +NS_IMETHODIMP +nsGfxRadioControlFrame::GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType) +{ + *aStateType = nsIStatefulFrame::eRadioType; + return NS_OK; +} + +//---------------------------------------------------------------------- +NS_IMETHODIMP +nsGfxRadioControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) +{ + // Construct a pres state. + NS_NewPresState(aState); // The addref happens here. + + // This string will hold a single item, whether or not we're checked. + nsAutoString stateString; + nsFormControlHelper::GetBoolString(GetRadioState(), stateString); + (*aState)->SetStateProperty("checked", stateString); + + return NS_OK; +} + + + +//---------------------------------------------------------------------- +NS_IMETHODIMP +nsGfxRadioControlFrame::RestoreState(nsIPresContext* aPresContext, nsIPresState* aState) +{ + if (!mDidInit) { + mPresContext = aPresContext; + InitializeControl(aPresContext); + mDidInit = PR_TRUE; + } + nsAutoString string; + aState->GetStateProperty("checked", string); + PRBool state = (string == NS_STRING_TRUE) ? PR_TRUE : PR_FALSE; + SetRadioState(aPresContext, state); + return NS_OK; +} + + +//---------------------------------------------------------------------- +// Extra Debug Helper Methods +//---------------------------------------------------------------------- #ifdef DEBUG_rodsXXX NS_IMETHODIMP nsGfxRadioControlFrame::Reflow(nsIPresContext* aPresContext, diff --git a/layout/html/forms/src/nsGfxRadioControlFrame.h b/layout/html/forms/src/nsGfxRadioControlFrame.h index 73ac07ce1172..e40ab27e3f80 100644 --- a/layout/html/forms/src/nsGfxRadioControlFrame.h +++ b/layout/html/forms/src/nsGfxRadioControlFrame.h @@ -23,25 +23,36 @@ #ifndef nsGfxRadioControlFrame_h___ #define nsGfxRadioControlFrame_h___ -#include "nsRadioControlFrame.h" +#include "nsFormControlFrame.h" +#include "nsIStatefulFrame.h" +#include "nsIRadioControlFrame.h" // nsGfxRadioControlFrame #define NS_GFX_RADIO_CONTROL_FRAME_FACE_CONTEXT_INDEX 0 // for additional style contexts #define NS_GFX_RADIO_CONTROL_FRAME_LAST_CONTEXT_INDEX 0 -class nsGfxRadioControlFrame : public nsRadioControlFrame +class nsGfxRadioControlFrame : public nsFormControlFrame, + public nsIStatefulFrame, + public nsIRadioControlFrame + { private: - typedef nsRadioControlFrame Inherited; public: nsGfxRadioControlFrame(); ~nsGfxRadioControlFrame(); //nsIRadioControlFrame methods + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); NS_IMETHOD SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioButtonFaceStyleContext); + + virtual PRBool GetChecked(PRBool aGetInitialValue); + virtual void SetChecked(nsIPresContext* aPresContext, PRBool aValue, PRBool aSetInitialValue); + + void InitializeControl(nsIPresContext* aPresContext); + NS_IMETHOD GetAdditionalStyleContext(PRInt32 aIndex, nsIStyleContext** aStyleContext) const; NS_IMETHOD SetAdditionalStyleContext(PRInt32 aIndex, @@ -67,6 +78,21 @@ public: nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect); + virtual PRInt32 GetMaxNumValues() { return 1; } + + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + virtual void Reset(nsIPresContext* aPresContext); + + // nsIFormControlFrame + NS_IMETHOD SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsString& aValue); + NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); + + //nsIStatefulFrame + NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); + NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); + NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); + ///XXX: End o the temporary methods #ifdef DEBUG_rodsXXX NS_IMETHOD Reflow(nsIPresContext* aCX, diff --git a/layout/html/forms/src/nsGfxTextControlFrame.cpp b/layout/html/forms/src/nsGfxTextControlFrame.cpp index 9a599c5906b8..1caa005a7744 100644 --- a/layout/html/forms/src/nsGfxTextControlFrame.cpp +++ b/layout/html/forms/src/nsGfxTextControlFrame.cpp @@ -31,7 +31,6 @@ #include "nsIHTMLContent.h" #include "nsHTMLIIDs.h" #include "nsITextWidget.h" -#include "nsITextAreaWidget.h" #include "nsWidgetsCID.h" #include "nsSize.h" #include "nsString.h" @@ -81,6 +80,7 @@ #include "nsIPresShell.h" #include "nsIEventStateManager.h" #include "nsStyleUtil.h" +#include "nsLinebreakConverter.h" // for anonymous content and frames #include "nsHTMLParts.h" @@ -100,9 +100,7 @@ static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); static NS_DEFINE_IID(kTextCID, NS_TEXTFIELD_CID); -static NS_DEFINE_IID(kTextAreaCID, NS_TEXTAREA_CID); static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID); -static NS_DEFINE_IID(kITextAreaWidgetIID, NS_ITEXTAREAWIDGET_IID); static NS_DEFINE_IID(kIDOMHTMLTextAreaElementIID, NS_IDOMHTMLTEXTAREAELEMENT_IID); static NS_DEFINE_IID(kIDOMHTMLInputElementIID, NS_IDOMHTMLINPUTELEMENT_IID); @@ -189,12 +187,17 @@ nsGfxTextControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) NS_PRECONDITION(0 != aInstancePtr, "null ptr"); if (NULL == aInstancePtr) { return NS_ERROR_NULL_POINTER; + } else if (aIID.Equals(NS_GET_IID(nsIGfxTextControlFrame))) { *aInstancePtr = (void*)(nsIGfxTextControlFrame*) this; + return NS_OK; + + } else if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) { + *aInstancePtr = (void*)(nsIStatefulFrame*) this; return NS_OK; } - return nsTextControlFrame::QueryInterface(aIID, aInstancePtr); + return nsFormControlFrame::QueryInterface(aIID, aInstancePtr); } NS_IMETHODIMP @@ -205,7 +208,7 @@ nsGfxTextControlFrame::Init(nsIPresContext* aPresContext, nsIFrame* aPrevInFlow) { mFramePresContext = aPresContext; - return (nsTextControlFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow)); + return nsFormControlFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); } NS_IMETHODIMP @@ -333,6 +336,8 @@ nsGfxTextControlFrame::nsGfxTextControlFrame() nsGfxTextControlFrame::~nsGfxTextControlFrame() { + nsFormControlFrame::RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); + nsresult result; if (mDisplayFrame) { mFrameConstructor->RemoveMappingsForFrameSubtree(mFramePresContext, @@ -1080,6 +1085,12 @@ void nsGfxTextControlFrame::CalcSizeOfSubDocInTwips(const nsMargin &aBorder, aSubBounds.height = (aFrameSize.height - (aBorder.top + aPadding.top + aBorder.bottom + aPadding.bottom)); } +PRInt32 +nsGfxTextControlFrame::GetMaxNumValues() +{ + return 1; +} + PRBool nsGfxTextControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, nsString* aValues, nsString* aNames) @@ -1990,6 +2001,8 @@ nsGfxTextControlFrame::Reflow(nsIPresContext* aPresContext, // add ourself as an nsIFormControlFrame if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { + mPresContext = aPresContext; + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); } @@ -2991,7 +3004,7 @@ nsGfxTextControlFrame::GetAdditionalChildListName(PRInt32 aIndex, return NS_OK; } - return nsTextControlFrame::GetAdditionalChildListName(aIndex, aListName); + return nsLeafFrame::GetAdditionalChildListName(aIndex, aListName); } NS_IMETHODIMP @@ -3004,7 +3017,7 @@ nsGfxTextControlFrame::FirstChild(nsIPresContext* aPresContext, return NS_OK; } - return nsTextControlFrame::FirstChild(aPresContext, aListName, aFirstChild); + return nsLeafFrame::FirstChild(aPresContext, aListName, aFirstChild); } NS_IMETHODIMP @@ -3015,7 +3028,58 @@ nsGfxTextControlFrame::Destroy(nsIPresContext* aPresContext) mDisplayFrame->Destroy(aPresContext); mDisplayFrame=nsnull; } - return nsTextControlFrame::Destroy(aPresContext); + return nsLeafFrame::Destroy(aPresContext); +} +//---------------------------------------------------------------------- +// nsIStatefulFrame +//---------------------------------------------------------------------- +NS_IMETHODIMP +nsGfxTextControlFrame::GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType) +{ + *aStateType = nsIStatefulFrame::eTextType; + return NS_OK; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState) +{ + // Construct a pres state. + NS_NewPresState(aState); // The addref happens here. + + nsAutoString theString; + nsresult res = GetProperty(nsHTMLAtoms::value, theString); + if (NS_SUCCEEDED(res)) { + char* chars = theString.ToNewCString(); + if (chars) { + + // GetProperty returns platform-native line breaks. We must convert + // these to content line breaks. + char* newChars = nsLinebreakConverter::ConvertLineBreaks(chars, + nsLinebreakConverter::eLinebreakPlatform, nsLinebreakConverter::eLinebreakContent); + if (newChars) { + nsCRT::free(chars); + chars = newChars; + } + + (*aState)->SetStateProperty("value", nsAutoString(chars)); + + nsCRT::free(chars); + } else { + res = NS_ERROR_OUT_OF_MEMORY; + } + } + + (*aState)->SetStateProperty("value", theString); + return res; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::RestoreState(nsIPresContext* aPresContext, nsIPresState* aState) +{ + nsAutoString stateString; + aState->GetStateProperty("value", stateString); + nsresult res = SetProperty(aPresContext, nsHTMLAtoms::value, stateString); + return res; } #ifdef NS_DEBUG diff --git a/layout/html/forms/src/nsGfxTextControlFrame.h b/layout/html/forms/src/nsGfxTextControlFrame.h index 81b28ab0e6b0..ed7063c5eae2 100644 --- a/layout/html/forms/src/nsGfxTextControlFrame.h +++ b/layout/html/forms/src/nsGfxTextControlFrame.h @@ -27,7 +27,6 @@ #include "nsCOMPtr.h" #include "nsCWeakReference.h" #include "nsFormControlFrame.h" -#include "nsTextControlFrame.h" #include "nsIDocumentLoaderObserver.h" #include "nsIEditor.h" #include "nsIDocumentObserver.h" @@ -46,6 +45,8 @@ #include "nsIWebShell.h" #include "nsIViewManager.h" +#include "nsIStatefulFrame.h" + #include "nsCSSFrameConstructor.h" class nsIFrame; @@ -377,7 +378,8 @@ protected: * and attaches an editor to the subdocument. ******************************************************************************/ -class nsGfxTextControlFrame : public nsTextControlFrame, +class nsGfxTextControlFrame : public nsFormControlFrame, + public nsIStatefulFrame, public nsIGfxTextControlFrame { private: @@ -420,9 +422,6 @@ public: NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); virtual void SetFocus(PRBool aOn = PR_TRUE, PRBool aRepaint = PR_FALSE); virtual nsWidgetInitData* GetWidgetInitData(nsIPresContext* aPresContext); - virtual void PostCreateWidget(nsIPresContext* aPresContext, - nscoord& aWidth, - nscoord& aHeight) {}; /** handler for attribute changes to mContent */ NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, @@ -451,6 +450,7 @@ public: virtual void EnterPressed(nsIPresContext* aPresContext) ; + virtual PRInt32 GetMaxNumValues(); virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, nsString* aValues, nsString* aNames); virtual void Reset(nsIPresContext* aPresContext); @@ -509,7 +509,14 @@ public: NS_IMETHOD GetWebShell(nsIWebShell **aWebShell); NS_IMETHOD SetInnerFocus(); + //nsIStatefulFrame + NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); + NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); + NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); + + protected: + PRInt32 GetDefaultColumnWidth() const { return (PRInt32)(20); } // this was DEFAULT_PIXEL_WIDTH /** calculate the inner region of the text control (size - border and padding) in pixels */ virtual void CalcSizeOfSubDocInTwips(const nsMargin &aBorder, diff --git a/layout/html/forms/src/nsHTMLButtonControlFrame.cpp b/layout/html/forms/src/nsHTMLButtonControlFrame.cpp index e4d3a18f7c90..e67c837e8495 100644 --- a/layout/html/forms/src/nsHTMLButtonControlFrame.cpp +++ b/layout/html/forms/src/nsHTMLButtonControlFrame.cpp @@ -92,6 +92,7 @@ nsHTMLButtonControlFrame::nsHTMLButtonControlFrame() nsHTMLButtonControlFrame::~nsHTMLButtonControlFrame() { + nsFormControlFrame::RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); if (mFormFrame) { mFormFrame->RemoveFormControlFrame(*this); mFormFrame = nsnull; @@ -513,15 +514,18 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext* aPresContext, nsReflowStatus& aStatus) { if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { + mPresContext = aPresContext; + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); } +#if 0 nsresult skiprv = nsFormControlFrame::SkipResizeReflow(mCacheSize, mCachedMaxElementSize, aPresContext, aDesiredSize, aReflowState, aStatus); if (NS_SUCCEEDED(skiprv)) { return skiprv; } - +#endif // XXX remove the following when the reflow state is fixed ButtonHack((nsHTMLReflowState&)aReflowState, "html4 button"); @@ -662,10 +666,12 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext* aPresContext, //aDesiredSize.width += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; //aDesiredSize.height += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; +#if 1 //adjust our max element size, if necessary if (aDesiredSize.maxElementSize) { aDesiredSize.AddBorderPaddingToMaxElementSize(aReflowState.mComputedBorderPadding); } +#endif aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; @@ -684,11 +690,10 @@ nsHTMLButtonControlFrame::GetSkipSides() const } NS_IMETHODIMP -nsHTMLButtonControlFrame::GetFont(nsIPresContext* aPresContext, - const nsFont*& aFont) +nsHTMLButtonControlFrame::GetFont(nsIPresContext* aPresContext, + const nsFont*& aFont) { - nsFormControlHelper::GetFont(this, aPresContext, mStyleContext, aFont); - return NS_OK; + return nsFormControlHelper::GetFont(this, aPresContext, mStyleContext, aFont); } NS_IMETHODIMP diff --git a/layout/html/forms/src/nsHTMLButtonControlFrame.h b/layout/html/forms/src/nsHTMLButtonControlFrame.h index 4c902e08dd07..84ea27d4f860 100644 --- a/layout/html/forms/src/nsHTMLButtonControlFrame.h +++ b/layout/html/forms/src/nsHTMLButtonControlFrame.h @@ -156,6 +156,8 @@ protected: PRBool mDidInit; nsButtonFrameRenderer mRenderer; + nsCOMPtr mPresContext; + //Resize Reflow OpitmizationSize; nsSize mCacheSize; nsSize mCachedMaxElementSize; diff --git a/layout/html/forms/src/nsImageControlFrame.cpp b/layout/html/forms/src/nsImageControlFrame.cpp index 9f6ec1af23f6..378216ed8bb7 100644 --- a/layout/html/forms/src/nsImageControlFrame.cpp +++ b/layout/html/forms/src/nsImageControlFrame.cpp @@ -46,6 +46,7 @@ #include "nsIHTMLAttributes.h" #include "nsGenericHTMLElement.h" #include "nsFormFrame.h" +#include "nsFormControlFrame.h" //Enumeration of possible mouse states used to detect mouse clicks /*enum nsMouseState { @@ -145,6 +146,8 @@ protected: nsCursor mPreviousCursor; nsRect mTranslatedRect; PRBool mGotFocus; + + nsCOMPtr mPresContext; }; @@ -160,6 +163,8 @@ nsImageControlFrame::nsImageControlFrame() nsImageControlFrame::~nsImageControlFrame() { + nsFormControlFrame::RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); + if (mFormFrame) { mFormFrame->RemoveFormControlFrame(*this); mFormFrame = nsnull; @@ -255,6 +260,8 @@ nsImageControlFrame::Reflow(nsIPresContext* aPresContext, nsReflowStatus& aStatus) { if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { + mPresContext = aPresContext; + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); // add ourself as an nsIFormControlFrame nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); } diff --git a/layout/html/forms/src/nsLabelFrame.cpp b/layout/html/forms/src/nsLabelFrame.cpp index 159e7abd5dbd..e02e72416f75 100644 --- a/layout/html/forms/src/nsLabelFrame.cpp +++ b/layout/html/forms/src/nsLabelFrame.cpp @@ -54,18 +54,10 @@ #include "nsIDocument.h" #include "nsIHTMLDocument.h" #include "nsIDOMHTMLAnchorElement.h" +#include "nsFormControlFrame.h" #include "nsIFocusableContent.h" -//Enumeration of possible mouse states used to detect mouse clicks -enum nsMouseState { - eMouseNone, - eMouseEnter, - eMouseExit, - eMouseDown, - eMouseUp -}; - static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); @@ -78,6 +70,7 @@ class nsLabelFrame : public nsHTMLContainerFrame { public: nsLabelFrame(); + virtual ~nsLabelFrame(); NS_IMETHOD Init(nsIPresContext* aPresContext, nsIContent* aContent, @@ -127,6 +120,8 @@ protected: PRBool mControlIsInside; nsIFormControlFrame* mControlFrame; nsRect mTranslatedRect; + + nsCOMPtr mPresContext; }; nsresult @@ -155,6 +150,11 @@ nsLabelFrame::nsLabelFrame() mTranslatedRect = nsRect(0,0,0,0); } +nsLabelFrame::~nsLabelFrame() +{ + nsFormControlFrame::RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); +} + void nsLabelFrame::GetTranslatedRect(nsIPresContext* aPresContext, nsRect& aRect) { @@ -541,7 +541,10 @@ nsLabelFrame::Reflow(nsIPresContext* aPresContext, aReflowState.reflowCommand->GetNext(nextFrame); NS_ASSERTION(nextFrame == mFrames.FirstChild(), "unexpected next reflow command frame"); } - } + } else if (eReflowReason_Initial == aReflowState.reason) { + mPresContext = aPresContext; + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); + } // XXX remove the following when the reflow state is fixed LabelHack((nsHTMLReflowState&)aReflowState, "BUG - label"); diff --git a/layout/html/forms/src/nsLegendFrame.cpp b/layout/html/forms/src/nsLegendFrame.cpp index 17146e4e3497..dec875b4bcfa 100644 --- a/layout/html/forms/src/nsLegendFrame.cpp +++ b/layout/html/forms/src/nsLegendFrame.cpp @@ -30,7 +30,6 @@ #include "nsIFrame.h" #include "nsISupports.h" #include "nsIAtom.h" -#include "nsIPresContext.h" #include "nsIHTMLContent.h" #include "nsHTMLIIDs.h" #include "nsHTMLParts.h" @@ -39,6 +38,7 @@ #include "nsStyleConsts.h" #include "nsStyleUtil.h" #include "nsFont.h" +#include "nsFormControlFrame.h" static NS_DEFINE_IID(kLegendFrameCID, NS_LEGEND_FRAME_CID); static NS_DEFINE_IID(kIDOMHTMLLegendElementIID, NS_IDOMHTMLLEGENDELEMENT_IID); @@ -63,6 +63,11 @@ nsLegendFrame::nsLegendFrame() { } +nsLegendFrame::~nsLegendFrame() +{ + nsFormControlFrame::RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); +} + // Frames are not refcounted, no need to AddRef NS_IMETHODIMP nsLegendFrame::QueryInterface(REFNSIID aIID, void** aInstancePtrResult) @@ -78,6 +83,20 @@ nsLegendFrame::QueryInterface(REFNSIID aIID, void** aInstancePtrResult) return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtrResult); } +NS_IMETHODIMP +nsLegendFrame::Reflow(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + if (eReflowReason_Initial == aReflowState.reason) { + mPresContext = aPresContext; + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); + } + return nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); +} + + PRInt32 nsLegendFrame::GetAlign() { PRInt32 intValue = NS_STYLE_TEXT_ALIGN_LEFT; diff --git a/layout/html/forms/src/nsLegendFrame.h b/layout/html/forms/src/nsLegendFrame.h index 6401d24caa40..5538435740cd 100644 --- a/layout/html/forms/src/nsLegendFrame.h +++ b/layout/html/forms/src/nsLegendFrame.h @@ -24,6 +24,9 @@ #define nsLegendFrame_h___ #include "nsAreaFrame.h" +#include "nsIPresContext.h" +#include "nsCOMPtr.h" + class nsIContent; class nsIFrame; class nsIPresContext; @@ -38,14 +41,23 @@ class nsLegendFrame : public nsAreaFrame { public: nsLegendFrame(); + virtual ~nsLegendFrame(); NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + NS_IMETHOD Reflow(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus); + + #ifdef NS_DEBUG NS_IMETHOD GetFrameName(nsString& aResult) const; #endif PRInt32 GetAlign(); + + nsCOMPtr mPresContext; }; diff --git a/layout/html/forms/src/nsListControlFrame.cpp b/layout/html/forms/src/nsListControlFrame.cpp index 0fbda31ccddf..b26a500b157a 100644 --- a/layout/html/forms/src/nsListControlFrame.cpp +++ b/layout/html/forms/src/nsListControlFrame.cpp @@ -123,6 +123,8 @@ nsListControlFrame::nsListControlFrame() //--------------------------------------------------------- nsListControlFrame::~nsListControlFrame() { + nsFormControlFrame::RegUnRegAccessKey(mPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); + // if list is dropped down // make sure it gets rolled up if (IsInDropDownMode()) { @@ -286,7 +288,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { -#ifdef DEBUG_rodsXXX +#ifdef DEBUG_rods printf("nsListControlFrame::Reflow Reason: "); switch (aReflowState.reason) { case eReflowReason_Initial:printf("eReflowReason_Initial\n");break; @@ -355,6 +357,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, mHasBeenInitialized = PR_TRUE; InitSelectionCache(-1); // Reset sel cache so as not to send event Reset(mPresContext); +#if 1 nsCOMPtr cmd; nsresult rv = NS_NewHTMLReflowCommand(getter_AddRefs(cmd), this, nsIReflowCommand::StyleChanged); if (NS_FAILED(rv)) { return rv; } @@ -368,10 +371,18 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, rv = shell->AppendReflowCommand(cmd); // must do this next line regardless of result of AppendReflowCommand shell->ExitReflowLock(PR_TRUE); +#else + if (mParent) { + nsCOMPtr shell; + nsresult rv = mPresContext->GetShell(getter_AddRefs(shell)); + mState |= NS_FRAME_IS_DIRTY; + mParent->ReflowDirtyChild(shell, (nsIFrame*) this); + } +#endif } } -#if 1 +#if 0 nsresult skiprv = nsFormControlFrame::SkipResizeReflow(mCacheSize, mCachedMaxElementSize, aPresContext, aDesiredSize, aReflowState, aStatus); if (NS_SUCCEEDED(skiprv)) { @@ -416,6 +427,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, // Add the list frame as a child of the form if (IsInDropDownMode() == PR_FALSE && !mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { + nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE); nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); } @@ -1943,6 +1955,17 @@ nsListControlFrame::AddOption(nsIPresContext* aPresContext, PRInt32 aIndex) Reset(aPresContext); // this sets mSelectedIndex to the defaulted selection wasReset = PR_TRUE; } + +#if DEBUG_rods + { + nsAutoString text = "No Value"; + nsresult rv = option->GetLabel(text); + if (NS_CONTENT_ATTR_NOT_THERE == rv || 0 == text.Length()) { + option->GetText(text); + } + printf("this %p Index: %d [%s] CB: %p\n", this, aIndex, text.ToNewCString(), mComboboxFrame); //leaks + } +#endif } } @@ -2468,6 +2491,30 @@ void nsListControlFrame::ResetSelectedItem() } } +//---------------------------------------------------------------------- +// helper +//---------------------------------------------------------------------- +PRBool +nsListControlFrame::IsLeftButton(nsIDOMEvent* aMouseEvent) +{ + // only allow selection with the left button + nsCOMPtr mouseEvent = do_QueryInterface(aMouseEvent); + if (mouseEvent) { + PRUint16 whichButton; + if (NS_SUCCEEDED(mouseEvent->GetButton(&whichButton))) { + if (whichButton != 1) { + aMouseEvent->PreventDefault(); + aMouseEvent->PreventCapture(); + aMouseEvent->PreventBubble(); + return PR_FALSE; + } else { + return PR_TRUE; + } + } + } + return PR_FALSE; +} + //---------------------------------------------------------------------- // nsIDOMMouseListener //---------------------------------------------------------------------- @@ -2479,6 +2526,11 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent) return NS_OK; } + // only allow selection with the left button + if (!IsLeftButton(aMouseEvent)) { + return NS_ERROR_FAILURE; // means consume event + } + // Check to see if the disabled option was clicked on // NS_ERROR_FAILURE is returned is it isn't over an option PRBool optionIsDisabled; @@ -2512,7 +2564,11 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent) UpdateSelection(PR_TRUE, PR_FALSE, mContent); } - return NS_OK; + aMouseEvent->PreventDefault(); + aMouseEvent->PreventCapture(); + aMouseEvent->PreventBubble(); + return NS_ERROR_FAILURE; + //return NS_OK; } //--------------------------------------------------------- @@ -2579,6 +2635,11 @@ nsListControlFrame::MouseDown(nsIDOMEvent* aMouseEvent) return NS_OK; } + // only allow selection with the left button + if (!IsLeftButton(aMouseEvent)) { + return NS_ERROR_FAILURE; // means consume event + } + // Check to see if the disabled option was clicked on // NS_ERROR_FAILURE is returned is it isn't over an option PRBool optionIsDisabled; @@ -2673,7 +2734,11 @@ nsListControlFrame::MouseDown(nsIDOMEvent* aMouseEvent) } } } - return NS_OK; + aMouseEvent->PreventDefault(); + aMouseEvent->PreventCapture(); + aMouseEvent->PreventBubble(); + return NS_ERROR_FAILURE; //consumes event + //return NS_OK; } //---------------------------------------------------------------------- diff --git a/layout/html/forms/src/nsListControlFrame.h b/layout/html/forms/src/nsListControlFrame.h index 8ae637d86979..d17e78ccb289 100644 --- a/layout/html/forms/src/nsListControlFrame.h +++ b/layout/html/forms/src/nsListControlFrame.h @@ -217,6 +217,7 @@ protected: PRBool HasSameContent(nsIFrame* aFrame1, nsIFrame* aFrame2); void HandleListSelection(nsIDOMEvent * aDOMEvent); PRInt32 GetSelectedIndexFromFrame(nsIFrame *aHitFrame); + PRBool IsLeftButton(nsIDOMEvent* aMouseEvent); // onChange detection nsresult InitSelectionCache(PRInt32 aLength); diff --git a/layout/html/forms/src/nsRadioControlFrame.h b/layout/html/forms/src/nsRadioControlFrame.h index 6403f17a2c04..5751e4e095c9 100644 --- a/layout/html/forms/src/nsRadioControlFrame.h +++ b/layout/html/forms/src/nsRadioControlFrame.h @@ -70,8 +70,6 @@ public: virtual void Reset(nsIPresContext* aPresContext); virtual const nsIID& GetCID(); - virtual const nsIID& GetIID(); - // // XXX: The following paint methods are TEMPORARY. It is being used to get printing working // under windows. Later it may be used to GFX-render the controls to the display. diff --git a/layout/html/forms/src/nsRadioControlGroup.cpp b/layout/html/forms/src/nsRadioControlGroup.cpp index 0a43e1b8070f..5f83ae73bab2 100644 --- a/layout/html/forms/src/nsRadioControlGroup.cpp +++ b/layout/html/forms/src/nsRadioControlGroup.cpp @@ -38,20 +38,20 @@ nsRadioControlGroup::GetRadioCount() const return mRadios.Count(); } -nsRadioControlFrame* +nsGfxRadioControlFrame* nsRadioControlGroup::GetRadioAt(PRInt32 aIndex) const { - return (nsRadioControlFrame*) mRadios.ElementAt(aIndex); + return (nsGfxRadioControlFrame*) mRadios.ElementAt(aIndex); } PRBool -nsRadioControlGroup::AddRadio(nsRadioControlFrame* aRadio) +nsRadioControlGroup::AddRadio(nsGfxRadioControlFrame* aRadio) { return mRadios.AppendElement(aRadio); } PRBool -nsRadioControlGroup::RemoveRadio(nsRadioControlFrame* aRadio) +nsRadioControlGroup::RemoveRadio(nsGfxRadioControlFrame* aRadio) { if (aRadio == mCheckedRadio) { mCheckedRadio = nsnull; @@ -59,14 +59,14 @@ nsRadioControlGroup::RemoveRadio(nsRadioControlFrame* aRadio) return mRadios.RemoveElement(aRadio); } -nsRadioControlFrame* +nsGfxRadioControlFrame* nsRadioControlGroup::GetCheckedRadio() { return mCheckedRadio; } void -nsRadioControlGroup::SetCheckedRadio(nsRadioControlFrame* aRadio) +nsRadioControlGroup::SetCheckedRadio(nsGfxRadioControlFrame* aRadio) { mCheckedRadio = aRadio; } diff --git a/layout/html/forms/src/nsRadioControlGroup.h b/layout/html/forms/src/nsRadioControlGroup.h index f41040463eb6..e5fe4070004f 100644 --- a/layout/html/forms/src/nsRadioControlGroup.h +++ b/layout/html/forms/src/nsRadioControlGroup.h @@ -23,7 +23,7 @@ #ifndef nsRadioControlGroup_h___ #define nsRadioControlGroup_h___ -#include "nsRadioControlFrame.h" +#include "nsGfxRadioControlFrame.h" class nsRadioControlGroup @@ -32,19 +32,21 @@ public: nsRadioControlGroup(nsString& aName); virtual ~nsRadioControlGroup(); - PRBool AddRadio(nsRadioControlFrame* aRadio); + PRBool AddRadio(nsGfxRadioControlFrame* aRadio); PRInt32 GetRadioCount() const; - nsRadioControlFrame* GetRadioAt(PRInt32 aIndex) const; - PRBool RemoveRadio(nsRadioControlFrame* aRadio); + nsGfxRadioControlFrame* GetRadioAt(PRInt32 aIndex) const; + PRInt32 GetNumRadios() const { return mRadios.Count(); } - nsRadioControlFrame* GetCheckedRadio(); - void SetCheckedRadio(nsRadioControlFrame* aRadio); + PRBool RemoveRadio(nsGfxRadioControlFrame* aRadio); + + nsGfxRadioControlFrame* GetCheckedRadio(); + void SetCheckedRadio(nsGfxRadioControlFrame* aRadio); void GetName(nsString& aNameResult) const; protected: nsString mName; nsVoidArray mRadios; - nsRadioControlFrame* mCheckedRadio; + nsGfxRadioControlFrame* mCheckedRadio; }; diff --git a/layout/html/forms/src/nsTextControlFrame.cpp b/layout/html/forms/src/nsTextControlFrame.cpp index ee48bfd89157..804e77d78361 100644 --- a/layout/html/forms/src/nsTextControlFrame.cpp +++ b/layout/html/forms/src/nsTextControlFrame.cpp @@ -30,7 +30,6 @@ #include "nsIHTMLContent.h" #include "nsHTMLIIDs.h" #include "nsITextWidget.h" -#include "nsITextAreaWidget.h" #include "nsWidgetsCID.h" #include "nsSize.h" #include "nsString.h"