diff --git a/mozilla/layout/forms/nsComboboxControlFrame.cpp b/mozilla/layout/forms/nsComboboxControlFrame.cpp index df6ba61febe..de35ed98ae7 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.cpp +++ b/mozilla/layout/forms/nsComboboxControlFrame.cpp @@ -38,11 +38,14 @@ #include "nsIDeviceContext.h" #include "nsIView.h" #include "nsIScrollableView.h" - #include "nsIEventStateManager.h" -// Get onChange to target Select not Option #include "nsIDOMNode.h" #include "nsIPrivateDOMEvent.h" +#include "nsIStatefulFrame.h" +#include "nsISupportsArray.h" +#include "nsISelectControlFrame.h" +#include "nsISupportsPrimitives.h" +#include "nsIComponentManager.h" static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); static NS_DEFINE_IID(kIComboboxControlFrameIID, NS_ICOMBOBOXCONTROLFRAME_IID); @@ -148,11 +151,15 @@ nsComboboxControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) } else if (aIID.Equals(kIAnonymousContentCreatorIID)) { *aInstancePtr = (void*)(nsIAnonymousContentCreator*) this; return NS_OK; - } else if (aIID.Equals(nsCOMTypeInfo::GetIID())) { - *aInstancePtr = (void *)((nsISelectControlFrame*)this); + } else if (aIID.Equals(NS_GET_IID(nsISelectControlFrame))) { + *aInstancePtr = (void *)(nsISelectControlFrame*)this; + NS_ADDREF_THIS(); + return NS_OK; + } else if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) { + *aInstancePtr = (void *)(nsIStatefulFrame*)this; + NS_ADDREF_THIS(); return NS_OK; } - return nsAreaFrame::QueryInterface(aIID, aInstancePtr); } @@ -1042,16 +1049,16 @@ nsComboboxControlFrame::SelectionChanged(PRBool aDoDispatchEvent) nsIDOMNode* node = nsnull; res = mContent->QueryInterface(kIDOMNodeIID, (void**)&node); if (NS_SUCCEEDED(res) && node) { - nsIPrivateDOMEvent* pDOMEvent = nsnull; + nsIPrivateDOMEvent* pDOMEvent = nsnull; res = DOMEvent->QueryInterface(kIPrivateDOMEventIID, (void**)&pDOMEvent); if (NS_SUCCEEDED(res) && pDOMEvent) { pDOMEvent->SetTarget(node); - NS_RELEASE(pDOMEvent); + NS_RELEASE(pDOMEvent); // Have the content handle the event. mContent->HandleDOMEvent(*mPresContext, &event, &DOMEvent, NS_EVENT_FLAG_BUBBLE, status); } - NS_RELEASE(node); + NS_RELEASE(node); } NS_RELEASE(DOMEvent); } @@ -1077,10 +1084,11 @@ nsComboboxControlFrame::AddOption(PRInt32 aIndex) { nsISelectControlFrame* listFrame = nsnull; nsIFrame* dropdownFrame = GetDropdownFrame(); - nsresult rv = dropdownFrame->QueryInterface(nsCOMTypeInfo::GetIID(), + nsresult rv = dropdownFrame->QueryInterface(NS_GET_IID(nsISelectControlFrame), (void**)&listFrame); - if (NS_SUCCEEDED(rv) && nsnull != listFrame) { - return listFrame->AddOption(aIndex); + if (NS_SUCCEEDED(rv) && listFrame) { + rv = listFrame->AddOption(aIndex); + NS_RELEASE(listFrame); } return rv; } @@ -1091,10 +1099,11 @@ nsComboboxControlFrame::RemoveOption(PRInt32 aIndex) { nsISelectControlFrame* listFrame = nsnull; nsIFrame* dropdownFrame = GetDropdownFrame(); - nsresult rv = dropdownFrame->QueryInterface(nsCOMTypeInfo::GetIID(), + nsresult rv = dropdownFrame->QueryInterface(NS_GET_IID(nsISelectControlFrame), (void**)&listFrame); - if (NS_SUCCEEDED(rv) && nsnull != listFrame) { - return listFrame->RemoveOption(aIndex); + if (NS_SUCCEEDED(rv) && listFrame) { + rv = listFrame->RemoveOption(aIndex); + NS_RELEASE(listFrame); } return rv; } @@ -1104,10 +1113,25 @@ nsComboboxControlFrame::SetOptionSelected(PRInt32 aIndex, PRBool aValue) { nsISelectControlFrame* listFrame = nsnull; nsIFrame* dropdownFrame = GetDropdownFrame(); - nsresult rv = dropdownFrame->QueryInterface(nsCOMTypeInfo::GetIID(), + nsresult rv = dropdownFrame->QueryInterface(NS_GET_IID(nsISelectControlFrame), (void**)&listFrame); - if (NS_SUCCEEDED(rv) && nsnull != listFrame) { - return listFrame->SetOptionSelected(aIndex, aValue); + if (NS_SUCCEEDED(rv) && listFrame) { + rv = listFrame->SetOptionSelected(aIndex, aValue); + NS_RELEASE(listFrame); + } + return rv; +} + +NS_IMETHODIMP +nsComboboxControlFrame::GetOptionSelected(PRInt32 aIndex, PRBool* aValue) +{ + nsISelectControlFrame* listFrame = nsnull; + nsIFrame* dropdownFrame = GetDropdownFrame(); + nsresult rv = dropdownFrame->QueryInterface(NS_GET_IID(nsISelectControlFrame), + (void**)&listFrame); + if (NS_SUCCEEDED(rv) && listFrame) { + rv = listFrame->GetOptionSelected(aIndex, aValue); + NS_RELEASE(listFrame); } return rv; } @@ -1368,4 +1392,42 @@ nsComboboxControlFrame::Blur(nsIDOMEvent* aEvent) return NS_OK; } +//---------------------------------------------------------------------- +// nsIStatefulFrame +// XXX Do we need to implement this here? It is already implemented in +// the ListControlFrame, our child... +//---------------------------------------------------------------------- +NS_IMETHODIMP +nsComboboxControlFrame::GetStateType(StateType* aStateType) +{ + *aStateType = eSelectType; + return NS_OK; +} +NS_IMETHODIMP +nsComboboxControlFrame::SaveState(nsISupports** aState) +{ + if (!mListControlFrame) return NS_ERROR_UNEXPECTED; + nsIStatefulFrame* sFrame = nsnull; + nsresult res = mListControlFrame->QueryInterface(NS_GET_IID(nsIStatefulFrame), + (void**)&sFrame); + if (NS_SUCCEEDED(res) && sFrame) { + res = sFrame->SaveState(aState); + NS_RELEASE(sFrame); + } + return res; +} + +NS_IMETHODIMP +nsComboboxControlFrame::RestoreState(nsISupports* aState) +{ + if (!mListControlFrame) return NS_ERROR_UNEXPECTED; + nsIStatefulFrame* sFrame = nsnull; + nsresult res = mListControlFrame->QueryInterface(NS_GET_IID(nsIStatefulFrame), + (void**)&sFrame); + if (NS_SUCCEEDED(res) && sFrame) { + res = sFrame->RestoreState(aState); + NS_RELEASE(sFrame); + } + return res; +} diff --git a/mozilla/layout/forms/nsComboboxControlFrame.h b/mozilla/layout/forms/nsComboboxControlFrame.h index a8aed6e33b8..e63a511827b 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.h +++ b/mozilla/layout/forms/nsComboboxControlFrame.h @@ -28,6 +28,7 @@ #include "nsVoidArray.h" #include "nsIAnonymousContentCreator.h" #include "nsISelectControlFrame.h" +#include "nsIStatefulFrame.h" class nsButtonControlFrame; class nsTextControlFrame; @@ -49,8 +50,8 @@ class nsComboboxControlFrame : public nsAreaFrame, public nsIDOMMouseListener, public nsIDOMFocusListener, public nsIAnonymousContentCreator, - public nsISelectControlFrame - + public nsISelectControlFrame, + public nsIStatefulFrame { public: nsComboboxControlFrame(); @@ -140,6 +141,7 @@ public: NS_IMETHOD AddOption(PRInt32 index); NS_IMETHOD RemoveOption(PRInt32 index); NS_IMETHOD SetOptionSelected(PRInt32 aIndex, PRBool aValue); + NS_IMETHOD GetOptionSelected(PRInt32 aIndex, PRBool* aValue); //nsIDOMEventListener virtual nsresult MouseDown(nsIDOMEvent* aMouseEvent); @@ -154,6 +156,11 @@ public: virtual nsresult Focus(nsIDOMEvent* aEvent); virtual nsresult Blur(nsIDOMEvent* aEvent); + //nsIStatefulFrame + NS_IMETHOD GetStateType(StateType* aStateType); + NS_IMETHOD SaveState(nsISupports** aState); + NS_IMETHOD RestoreState(nsISupports* aState); + protected: // nsHTMLContainerFrame diff --git a/mozilla/layout/forms/nsListControlFrame.cpp b/mozilla/layout/forms/nsListControlFrame.cpp index 4a2d73fb808..4871e9d0c4e 100644 --- a/mozilla/layout/forms/nsListControlFrame.cpp +++ b/mozilla/layout/forms/nsListControlFrame.cpp @@ -37,10 +37,13 @@ #include "nsIReflowCommand.h" #include "nsIPresShell.h" #include "nsHTMLParts.h" - #include "nsIDOMEventReceiver.h" #include "nsIEventStateManager.h" #include "nsIDOMUIEvent.h" +#include "nsIStatefulFrame.h" +#include "nsISupportsArray.h" +#include "nsISupportsPrimitives.h" +#include "nsIComponentManager.h" static NS_DEFINE_IID(kIDOMMouseListenerIID, NS_IDOMMOUSELISTENER_IID); static NS_DEFINE_IID(kIDOMMouseMotionListenerIID, NS_IDOMMOUSEMOTIONLISTENER_IID); @@ -150,6 +153,11 @@ nsListControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) NS_ADDREF_THIS(); return NS_OK; } + if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) { + *aInstancePtr = (void*)(nsIStatefulFrame*) this; + NS_ADDREF_THIS(); + return NS_OK; + } return nsScrollFrame::QueryInterface(aIID, aInstancePtr); } @@ -1637,6 +1645,15 @@ nsListControlFrame::SetOptionSelected(PRInt32 aIndex, PRBool aValue) return NS_OK; } +//--------------------------------------------------------- +// Determine if the specified item in the listbox is selected. +NS_IMETHODIMP +nsListControlFrame::GetOptionSelected(PRInt32 aIndex, PRBool* aValue) +{ + *aValue = IsContentSelectedByIndex(aIndex); + return NS_OK; +} + //---------------------------------------------------------------------- // End nsISelectControlFrame //---------------------------------------------------------------------- @@ -2145,3 +2162,78 @@ nsListControlFrame::KeyDown(nsIDOMEvent* aKeyEvent) return NS_OK; } +//---------------------------------------------------------------------- +// nsIStatefulFrame +//---------------------------------------------------------------------- +NS_IMETHODIMP +nsListControlFrame::GetStateType(StateType* aStateType) +{ + *aStateType = eSelectType; + return NS_OK; +} + +NS_IMETHODIMP +nsListControlFrame::SaveState(nsISupports** aState) +{ + nsISupportsArray* value = nsnull; + nsresult res = NS_NewISupportsArray(&value); + if (NS_SUCCEEDED(res) && value) { + PRInt32 j=0; + PRInt32 length = 0; + GetNumberOfOptions(&length); + PRInt32 i; + for (i=0; iSetData(i); + if (NS_SUCCEEDED(res)) { + PRBool okay = value->InsertElementAt((nsISupports *)thisVal, j++); + if (!okay) res = NS_ERROR_OUT_OF_MEMORY; // Most likely cause; + } + if (!NS_SUCCEEDED(res)) NS_RELEASE(thisVal); + } + } + if (!NS_SUCCEEDED(res)) break; + } + if (iCount(&count); + if (NS_SUCCEEDED(res)) { + nsISupportsPRInt32* thisVal = nsnull; + PRInt32 j=0; + for (PRUint32 i=0; iElementAt(i); + if (thisVal) { + res = thisVal->GetData(&j); + if (NS_SUCCEEDED(res)) { + res = SetOptionSelected(j, PR_TRUE); + } + } else { + res = NS_ERROR_UNEXPECTED; + } + if (!NS_SUCCEEDED(res)) break; + } + } + } + } + return res; +} diff --git a/mozilla/layout/forms/nsListControlFrame.h b/mozilla/layout/forms/nsListControlFrame.h index fccf099fe46..24581a604c7 100644 --- a/mozilla/layout/forms/nsListControlFrame.h +++ b/mozilla/layout/forms/nsListControlFrame.h @@ -26,6 +26,7 @@ #include "nsIDOMMouseListener.h" #include "nsIDOMMouseMotionListener.h" #include "nsIDOMKeyListener.h" +#include "nsIStatefulFrame.h" class nsIDOMHTMLSelectElement; class nsIDOMHTMLCollection; @@ -44,7 +45,8 @@ class nsListControlFrame : public nsScrollFrame, public nsIDOMMouseListener, public nsIDOMMouseMotionListener, public nsIDOMKeyListener, - public nsISelectControlFrame + public nsISelectControlFrame, + public nsIStatefulFrame { public: friend nsresult NS_NewListControlFrame(nsIFrame** aNewFrame); @@ -120,6 +122,12 @@ public: NS_IMETHOD AddOption(PRInt32 index); NS_IMETHOD RemoveOption(PRInt32 index); NS_IMETHOD SetOptionSelected(PRInt32 aIndex, PRBool aValue); + NS_IMETHOD GetOptionSelected(PRInt32 aIndex, PRBool* aValue); + + //nsIStatefulFrame + NS_IMETHOD GetStateType(StateType* aStateType); + NS_IMETHOD SaveState(nsISupports** aState); + NS_IMETHOD RestoreState(nsISupports* aState); //nsIDOMEventListener virtual nsresult MouseDown(nsIDOMEvent* aMouseEvent); diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp index df6ba61febe..de35ed98ae7 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp @@ -38,11 +38,14 @@ #include "nsIDeviceContext.h" #include "nsIView.h" #include "nsIScrollableView.h" - #include "nsIEventStateManager.h" -// Get onChange to target Select not Option #include "nsIDOMNode.h" #include "nsIPrivateDOMEvent.h" +#include "nsIStatefulFrame.h" +#include "nsISupportsArray.h" +#include "nsISelectControlFrame.h" +#include "nsISupportsPrimitives.h" +#include "nsIComponentManager.h" static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); static NS_DEFINE_IID(kIComboboxControlFrameIID, NS_ICOMBOBOXCONTROLFRAME_IID); @@ -148,11 +151,15 @@ nsComboboxControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) } else if (aIID.Equals(kIAnonymousContentCreatorIID)) { *aInstancePtr = (void*)(nsIAnonymousContentCreator*) this; return NS_OK; - } else if (aIID.Equals(nsCOMTypeInfo::GetIID())) { - *aInstancePtr = (void *)((nsISelectControlFrame*)this); + } else if (aIID.Equals(NS_GET_IID(nsISelectControlFrame))) { + *aInstancePtr = (void *)(nsISelectControlFrame*)this; + NS_ADDREF_THIS(); + return NS_OK; + } else if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) { + *aInstancePtr = (void *)(nsIStatefulFrame*)this; + NS_ADDREF_THIS(); return NS_OK; } - return nsAreaFrame::QueryInterface(aIID, aInstancePtr); } @@ -1042,16 +1049,16 @@ nsComboboxControlFrame::SelectionChanged(PRBool aDoDispatchEvent) nsIDOMNode* node = nsnull; res = mContent->QueryInterface(kIDOMNodeIID, (void**)&node); if (NS_SUCCEEDED(res) && node) { - nsIPrivateDOMEvent* pDOMEvent = nsnull; + nsIPrivateDOMEvent* pDOMEvent = nsnull; res = DOMEvent->QueryInterface(kIPrivateDOMEventIID, (void**)&pDOMEvent); if (NS_SUCCEEDED(res) && pDOMEvent) { pDOMEvent->SetTarget(node); - NS_RELEASE(pDOMEvent); + NS_RELEASE(pDOMEvent); // Have the content handle the event. mContent->HandleDOMEvent(*mPresContext, &event, &DOMEvent, NS_EVENT_FLAG_BUBBLE, status); } - NS_RELEASE(node); + NS_RELEASE(node); } NS_RELEASE(DOMEvent); } @@ -1077,10 +1084,11 @@ nsComboboxControlFrame::AddOption(PRInt32 aIndex) { nsISelectControlFrame* listFrame = nsnull; nsIFrame* dropdownFrame = GetDropdownFrame(); - nsresult rv = dropdownFrame->QueryInterface(nsCOMTypeInfo::GetIID(), + nsresult rv = dropdownFrame->QueryInterface(NS_GET_IID(nsISelectControlFrame), (void**)&listFrame); - if (NS_SUCCEEDED(rv) && nsnull != listFrame) { - return listFrame->AddOption(aIndex); + if (NS_SUCCEEDED(rv) && listFrame) { + rv = listFrame->AddOption(aIndex); + NS_RELEASE(listFrame); } return rv; } @@ -1091,10 +1099,11 @@ nsComboboxControlFrame::RemoveOption(PRInt32 aIndex) { nsISelectControlFrame* listFrame = nsnull; nsIFrame* dropdownFrame = GetDropdownFrame(); - nsresult rv = dropdownFrame->QueryInterface(nsCOMTypeInfo::GetIID(), + nsresult rv = dropdownFrame->QueryInterface(NS_GET_IID(nsISelectControlFrame), (void**)&listFrame); - if (NS_SUCCEEDED(rv) && nsnull != listFrame) { - return listFrame->RemoveOption(aIndex); + if (NS_SUCCEEDED(rv) && listFrame) { + rv = listFrame->RemoveOption(aIndex); + NS_RELEASE(listFrame); } return rv; } @@ -1104,10 +1113,25 @@ nsComboboxControlFrame::SetOptionSelected(PRInt32 aIndex, PRBool aValue) { nsISelectControlFrame* listFrame = nsnull; nsIFrame* dropdownFrame = GetDropdownFrame(); - nsresult rv = dropdownFrame->QueryInterface(nsCOMTypeInfo::GetIID(), + nsresult rv = dropdownFrame->QueryInterface(NS_GET_IID(nsISelectControlFrame), (void**)&listFrame); - if (NS_SUCCEEDED(rv) && nsnull != listFrame) { - return listFrame->SetOptionSelected(aIndex, aValue); + if (NS_SUCCEEDED(rv) && listFrame) { + rv = listFrame->SetOptionSelected(aIndex, aValue); + NS_RELEASE(listFrame); + } + return rv; +} + +NS_IMETHODIMP +nsComboboxControlFrame::GetOptionSelected(PRInt32 aIndex, PRBool* aValue) +{ + nsISelectControlFrame* listFrame = nsnull; + nsIFrame* dropdownFrame = GetDropdownFrame(); + nsresult rv = dropdownFrame->QueryInterface(NS_GET_IID(nsISelectControlFrame), + (void**)&listFrame); + if (NS_SUCCEEDED(rv) && listFrame) { + rv = listFrame->GetOptionSelected(aIndex, aValue); + NS_RELEASE(listFrame); } return rv; } @@ -1368,4 +1392,42 @@ nsComboboxControlFrame::Blur(nsIDOMEvent* aEvent) return NS_OK; } +//---------------------------------------------------------------------- +// nsIStatefulFrame +// XXX Do we need to implement this here? It is already implemented in +// the ListControlFrame, our child... +//---------------------------------------------------------------------- +NS_IMETHODIMP +nsComboboxControlFrame::GetStateType(StateType* aStateType) +{ + *aStateType = eSelectType; + return NS_OK; +} +NS_IMETHODIMP +nsComboboxControlFrame::SaveState(nsISupports** aState) +{ + if (!mListControlFrame) return NS_ERROR_UNEXPECTED; + nsIStatefulFrame* sFrame = nsnull; + nsresult res = mListControlFrame->QueryInterface(NS_GET_IID(nsIStatefulFrame), + (void**)&sFrame); + if (NS_SUCCEEDED(res) && sFrame) { + res = sFrame->SaveState(aState); + NS_RELEASE(sFrame); + } + return res; +} + +NS_IMETHODIMP +nsComboboxControlFrame::RestoreState(nsISupports* aState) +{ + if (!mListControlFrame) return NS_ERROR_UNEXPECTED; + nsIStatefulFrame* sFrame = nsnull; + nsresult res = mListControlFrame->QueryInterface(NS_GET_IID(nsIStatefulFrame), + (void**)&sFrame); + if (NS_SUCCEEDED(res) && sFrame) { + res = sFrame->RestoreState(aState); + NS_RELEASE(sFrame); + } + return res; +} diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.h b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h index a8aed6e33b8..e63a511827b 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.h +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h @@ -28,6 +28,7 @@ #include "nsVoidArray.h" #include "nsIAnonymousContentCreator.h" #include "nsISelectControlFrame.h" +#include "nsIStatefulFrame.h" class nsButtonControlFrame; class nsTextControlFrame; @@ -49,8 +50,8 @@ class nsComboboxControlFrame : public nsAreaFrame, public nsIDOMMouseListener, public nsIDOMFocusListener, public nsIAnonymousContentCreator, - public nsISelectControlFrame - + public nsISelectControlFrame, + public nsIStatefulFrame { public: nsComboboxControlFrame(); @@ -140,6 +141,7 @@ public: NS_IMETHOD AddOption(PRInt32 index); NS_IMETHOD RemoveOption(PRInt32 index); NS_IMETHOD SetOptionSelected(PRInt32 aIndex, PRBool aValue); + NS_IMETHOD GetOptionSelected(PRInt32 aIndex, PRBool* aValue); //nsIDOMEventListener virtual nsresult MouseDown(nsIDOMEvent* aMouseEvent); @@ -154,6 +156,11 @@ public: virtual nsresult Focus(nsIDOMEvent* aEvent); virtual nsresult Blur(nsIDOMEvent* aEvent); + //nsIStatefulFrame + NS_IMETHOD GetStateType(StateType* aStateType); + NS_IMETHOD SaveState(nsISupports** aState); + NS_IMETHOD RestoreState(nsISupports* aState); + protected: // nsHTMLContainerFrame diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.cpp b/mozilla/layout/html/forms/src/nsListControlFrame.cpp index 4a2d73fb808..4871e9d0c4e 100644 --- a/mozilla/layout/html/forms/src/nsListControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsListControlFrame.cpp @@ -37,10 +37,13 @@ #include "nsIReflowCommand.h" #include "nsIPresShell.h" #include "nsHTMLParts.h" - #include "nsIDOMEventReceiver.h" #include "nsIEventStateManager.h" #include "nsIDOMUIEvent.h" +#include "nsIStatefulFrame.h" +#include "nsISupportsArray.h" +#include "nsISupportsPrimitives.h" +#include "nsIComponentManager.h" static NS_DEFINE_IID(kIDOMMouseListenerIID, NS_IDOMMOUSELISTENER_IID); static NS_DEFINE_IID(kIDOMMouseMotionListenerIID, NS_IDOMMOUSEMOTIONLISTENER_IID); @@ -150,6 +153,11 @@ nsListControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) NS_ADDREF_THIS(); return NS_OK; } + if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) { + *aInstancePtr = (void*)(nsIStatefulFrame*) this; + NS_ADDREF_THIS(); + return NS_OK; + } return nsScrollFrame::QueryInterface(aIID, aInstancePtr); } @@ -1637,6 +1645,15 @@ nsListControlFrame::SetOptionSelected(PRInt32 aIndex, PRBool aValue) return NS_OK; } +//--------------------------------------------------------- +// Determine if the specified item in the listbox is selected. +NS_IMETHODIMP +nsListControlFrame::GetOptionSelected(PRInt32 aIndex, PRBool* aValue) +{ + *aValue = IsContentSelectedByIndex(aIndex); + return NS_OK; +} + //---------------------------------------------------------------------- // End nsISelectControlFrame //---------------------------------------------------------------------- @@ -2145,3 +2162,78 @@ nsListControlFrame::KeyDown(nsIDOMEvent* aKeyEvent) return NS_OK; } +//---------------------------------------------------------------------- +// nsIStatefulFrame +//---------------------------------------------------------------------- +NS_IMETHODIMP +nsListControlFrame::GetStateType(StateType* aStateType) +{ + *aStateType = eSelectType; + return NS_OK; +} + +NS_IMETHODIMP +nsListControlFrame::SaveState(nsISupports** aState) +{ + nsISupportsArray* value = nsnull; + nsresult res = NS_NewISupportsArray(&value); + if (NS_SUCCEEDED(res) && value) { + PRInt32 j=0; + PRInt32 length = 0; + GetNumberOfOptions(&length); + PRInt32 i; + for (i=0; iSetData(i); + if (NS_SUCCEEDED(res)) { + PRBool okay = value->InsertElementAt((nsISupports *)thisVal, j++); + if (!okay) res = NS_ERROR_OUT_OF_MEMORY; // Most likely cause; + } + if (!NS_SUCCEEDED(res)) NS_RELEASE(thisVal); + } + } + if (!NS_SUCCEEDED(res)) break; + } + if (iCount(&count); + if (NS_SUCCEEDED(res)) { + nsISupportsPRInt32* thisVal = nsnull; + PRInt32 j=0; + for (PRUint32 i=0; iElementAt(i); + if (thisVal) { + res = thisVal->GetData(&j); + if (NS_SUCCEEDED(res)) { + res = SetOptionSelected(j, PR_TRUE); + } + } else { + res = NS_ERROR_UNEXPECTED; + } + if (!NS_SUCCEEDED(res)) break; + } + } + } + } + return res; +} diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.h b/mozilla/layout/html/forms/src/nsListControlFrame.h index fccf099fe46..24581a604c7 100644 --- a/mozilla/layout/html/forms/src/nsListControlFrame.h +++ b/mozilla/layout/html/forms/src/nsListControlFrame.h @@ -26,6 +26,7 @@ #include "nsIDOMMouseListener.h" #include "nsIDOMMouseMotionListener.h" #include "nsIDOMKeyListener.h" +#include "nsIStatefulFrame.h" class nsIDOMHTMLSelectElement; class nsIDOMHTMLCollection; @@ -44,7 +45,8 @@ class nsListControlFrame : public nsScrollFrame, public nsIDOMMouseListener, public nsIDOMMouseMotionListener, public nsIDOMKeyListener, - public nsISelectControlFrame + public nsISelectControlFrame, + public nsIStatefulFrame { public: friend nsresult NS_NewListControlFrame(nsIFrame** aNewFrame); @@ -120,6 +122,12 @@ public: NS_IMETHOD AddOption(PRInt32 index); NS_IMETHOD RemoveOption(PRInt32 index); NS_IMETHOD SetOptionSelected(PRInt32 aIndex, PRBool aValue); + NS_IMETHOD GetOptionSelected(PRInt32 aIndex, PRBool* aValue); + + //nsIStatefulFrame + NS_IMETHOD GetStateType(StateType* aStateType); + NS_IMETHOD SaveState(nsISupports** aState); + NS_IMETHOD RestoreState(nsISupports* aState); //nsIDOMEventListener virtual nsresult MouseDown(nsIDOMEvent* aMouseEvent); diff --git a/mozilla/layout/html/forms/src/nsNativeSelectControlFrame.cpp b/mozilla/layout/html/forms/src/nsNativeSelectControlFrame.cpp index 5758a9c29d8..304fed1e97e 100644 --- a/mozilla/layout/html/forms/src/nsNativeSelectControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsNativeSelectControlFrame.cpp @@ -50,6 +50,10 @@ #include "nsILookAndFeel.h" #include "nsIComponentManager.h" #include "nsISelectControlFrame.h" +#include "nsIStatefulFrame.h" +#include "nsISupportsArray.h" +#include "nsISupportsPrimitives.h" +#include "nsIComponentManager.h" static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID); static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); @@ -63,12 +67,12 @@ static NS_DEFINE_IID(kListCID, NS_LISTBOX_CID); static NS_DEFINE_IID(kLookAndFeelCID, NS_LOOKANDFEEL_CID); static NS_DEFINE_IID(kILookAndFeelIID, NS_ILOOKANDFEEL_IID); static NS_DEFINE_IID(kISelectControlFrameIID, NS_ISELECTCONTROLFRAME_IID); - class nsOption; class nsNativeSelectControlFrame : public nsNativeFormControlFrame, - public nsISelectControlFrame + public nsISelectControlFrame, + public nsIStatefulFrame { private: typedef nsNativeFormControlFrame Inherited; @@ -149,6 +153,12 @@ public: NS_IMETHOD AddOption(PRInt32 aIndex); NS_IMETHOD RemoveOption(PRInt32 aIndex); NS_IMETHOD SetOptionSelected(PRInt32 aIndex, PRBool aValue); + NS_IMETHOD GetOptionSelected(PRInt32 aIndex, PRBool* aValue); + + //nsIStatefulFrame + NS_IMETHOD GetStateType(StateType* aStateType); + NS_IMETHOD SaveState(nsISupports** aState); + NS_IMETHOD RestoreState(nsISupports* aState); protected: PRInt32 mNumRows; @@ -159,6 +169,7 @@ protected: PRBool GetOptionValue(nsIDOMHTMLCollection& aCollecton, PRUint32 aIndex, nsString& aValue); PRInt32 GetSelectedIndex(); nsresult UpdateWidgetToCache(PRBool aDeselectFirst = PR_TRUE); + nsresult Deselect(); virtual void GetDesiredSize(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, @@ -174,6 +185,7 @@ protected: // GFX-rendered or not. This is used to detect changes in MouseClicked PRInt32 mNumOptions; PRBool* mOptionSelected; + PRBool mCachedState; // A flag meaning "Don't reset state on PostCreateWidget" // Accessor methods for mOptionsSelected and mNumOptions void GetOptionSelectedCache(PRInt32 index, PRBool* aValue); @@ -214,6 +226,7 @@ nsNativeSelectControlFrame::nsNativeSelectControlFrame() mNumRows = 0; mNumOptions = 0; mOptionSelected = nsnull; + mCachedState = PR_FALSE; } // XXX is this the right way to clean up? @@ -229,11 +242,16 @@ nsNativeSelectControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePt NS_PRECONDITION(0 != aInstancePtr, "null ptr"); if (NULL == aInstancePtr) { return NS_ERROR_NULL_POINTER; - } - if (aIID.Equals(kISelectControlFrameIID)) { - *aInstancePtr = (void*) ((nsISelectControlFrame*) this); + } else if (aIID.Equals(NS_GET_IID(nsISelectControlFrame))) { + *aInstancePtr = (void*)(nsISelectControlFrame*) this; + NS_ADDREF_THIS(); + return NS_OK; + } else if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) { + *aInstancePtr = (void*)(nsIStatefulFrame*) this; + NS_ADDREF_THIS(); return NS_OK; } + return Inherited::QueryInterface(aIID, aInstancePtr); } @@ -748,21 +766,26 @@ nsNativeSelectControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumV void nsNativeSelectControlFrame::Reset() { - // Reset selection to default - nsIDOMHTMLCollection* options = GetOptions(); - if (!options) return; // XXX NS_ERROR_UNEXPECTED; - PRUint32 numOptions; - options->GetLength(&numOptions); - for (PRUint32 i = 0; i < numOptions; i++) { - nsIDOMHTMLOptionElement* option = GetOption(*options, i); - if (option) { - // Cache the state of each option locally - PRBool selected = PR_FALSE; - option->GetDefaultSelected(&selected); - SetOptionSelectedCache(i, selected); + if (mCachedState) { + mCachedState = PR_FALSE; + } else { + // Reset selection to default + nsIDOMHTMLCollection* options = GetOptions(); + if (!options) return; // XXX NS_ERROR_UNEXPECTED; + PRUint32 numOptions; + options->GetLength(&numOptions); + for (PRUint32 i = 0; i < numOptions; i++) { + nsIDOMHTMLOptionElement* option = GetOption(*options, i); + if (option) { + // Cache the state of each option locally + PRBool selected = PR_FALSE; + option->GetDefaultSelected(&selected); + SetOptionSelectedCache(i, selected); + NS_RELEASE(option); + } } + NS_RELEASE(options); } - NS_RELEASE(options); UpdateWidgetToCache(); } @@ -1193,7 +1216,7 @@ void nsNativeSelectControlFrame::GetOptionSelectedWidget(PRInt32 indx, PRBool* a void nsNativeSelectControlFrame::SetOptionSelectedCache(PRInt32 indx, PRBool aValue) { if (nsnull != mOptionSelected) { - if (mNumOptions >= indx) { + if ((-1 < indx) && (mNumOptions >= indx)) { mOptionSelected[indx] = aValue; } } @@ -1225,9 +1248,10 @@ NS_IMETHODIMP nsNativeSelectControlFrame::SetProperty(nsIAtom* aName, const nsSt return NS_ERROR_INVALID_ARG; // Couldn't convert to integer // Update local cache of selected values - for (PRInt32 i=0; i < mNumOptions; i++) // Deselect all options - SetOptionSelectedCache(i, PR_FALSE); - SetOptionSelectedCache(selectedIndex, PR_TRUE); // Select selectedIndex + nsresult res = Deselect(); + if (NS_SUCCEEDED(res)) { + SetOptionSelectedCache(selectedIndex, PR_TRUE); // Select selectedIndex + } // Update widget UpdateWidgetToCache(); @@ -1267,7 +1291,12 @@ NS_IMETHODIMP nsNativeSelectControlFrame::AddOption(PRInt32 aIndex) // Get the correct selected value and text of the option nsIDOMHTMLOptionElement* option = GetOption(*options, i); - option->GetDefaultSelected(&selected); + if (option) { + option->GetDefaultSelected(&selected); + NS_RELEASE(option); + } else { + selected = PR_FALSE; // XXX failure case. + } mOptionSelected[j]=selected; j++; } @@ -1342,7 +1371,12 @@ NS_IMETHODIMP nsNativeSelectControlFrame::RemoveOption(PRInt32 aIndex) // Get the default (XXXincorrect) selected value and text of the option nsIDOMHTMLOptionElement* option = GetOption(*options, i); - option->GetDefaultSelected(&selected); // Should be sel, not defsel :( + if (option) { + option->GetDefaultSelected(&selected); // Should be sel, not defsel :( + NS_RELEASE(option); + } else { + selected = PR_FALSE; // XXX failure case + } mOptionSelected[i]=selected; } } @@ -1364,38 +1398,38 @@ NS_IMETHODIMP nsNativeSelectControlFrame::GetProperty(nsIAtom* aName, nsString& PRInt32 error = 0; PRBool selected = PR_FALSE; PRInt32 indx = aValue.ToInteger(&error, 10); // Get index from aValue -// if (error == 0) -// GetOptionSelectedWidget(indx, &selected); GetOptionSelectedCache(indx, &selected); nsFormControlHelper::GetBoolString(selected, aValue); // For selectedIndex, get the value from the widget } else if (nsHTMLAtoms::selectedindex == aName) { PRInt32 selectedIndex = -1; - PRBool multiple; - GetMultiple(&multiple); - if (!multiple) { - nsIListWidget* listWidget; - nsresult result = mWidget->QueryInterface(kListWidgetIID, (void **) &listWidget); - if ((NS_OK == result) && (nsnull != listWidget)) { - selectedIndex = listWidget->GetSelectedIndex(); - NS_RELEASE(listWidget); - } - } else { - // Listboxes don't do GetSelectedIndex on windows. Use GetSelectedIndices - nsIListBox* listBox; - nsresult result = mWidget->QueryInterface(kListBoxIID, (void **) &listBox); - if ((NS_OK == result) && (nsnull != listBox)) { - PRUint32 numSelected = listBox->GetSelectedCount(); - PRInt32* selOptions = nsnull; - if (numSelected > 0) { - // Could we set numSelected to 1 here? (memory, speed optimization) - selOptions = new PRInt32[numSelected]; - listBox->GetSelectedIndices(selOptions, numSelected); - selectedIndex = selOptions[0]; - delete[] selOptions; + if (mWidget) { + PRBool multiple; + GetMultiple(&multiple); + if (!multiple) { + nsIListWidget* listWidget; + nsresult result = mWidget->QueryInterface(kListWidgetIID, (void **) &listWidget); + if ((NS_OK == result) && (nsnull != listWidget)) { + selectedIndex = listWidget->GetSelectedIndex(); + NS_RELEASE(listWidget); + } + } else { + // Listboxes don't do GetSelectedIndex on windows. Use GetSelectedIndices + nsIListBox* listBox; + nsresult result = mWidget->QueryInterface(kListBoxIID, (void **) &listBox); + if ((NS_OK == result) && (nsnull != listBox)) { + PRUint32 numSelected = listBox->GetSelectedCount(); + PRInt32* selOptions = nsnull; + if (numSelected > 0) { + // Could we set numSelected to 1 here? (memory, speed optimization) + selOptions = new PRInt32[numSelected]; + listBox->GetSelectedIndices(selOptions, numSelected); + selectedIndex = selOptions[0]; + delete[] selOptions; + } + NS_RELEASE(listBox); } - NS_RELEASE(listBox); } } aValue.Append(selectedIndex, 10); @@ -1409,8 +1443,6 @@ NS_IMETHODIMP nsNativeSelectControlFrame::GetProperty(nsIAtom* aName, nsString& NS_IMETHODIMP nsNativeSelectControlFrame::SetOptionSelected(PRInt32 aIndex, PRBool aValue) { - // Get Selected index out of Content model - PRInt32 selectedIndex = GetSelectedIndex(); PRBool multiple = PR_FALSE; GetMultiple(&multiple); @@ -1418,18 +1450,38 @@ nsNativeSelectControlFrame::SetOptionSelected(PRInt32 aIndex, PRBool aValue) SetOptionSelectedCache(aIndex, aValue); } else { if (aValue) { - SetOptionSelectedCache(selectedIndex, PR_FALSE); + // Get Selected index out of Content model + PRInt32 selectedIndex = GetSelectedIndex(); + if (-1 < selectedIndex) + SetOptionSelectedCache(selectedIndex, PR_FALSE); SetOptionSelectedCache(aIndex, PR_TRUE); } else { SetOptionSelectedCache(aIndex, PR_FALSE); } } - return UpdateWidgetToCache(!aValue); // Don't deselect all if adding selection + // Note that UpdateWidgetToCache may return NS_ERROR_UNEXPECTED if the + // widget is not created yet. We can safely ignore this as when Reset is + // called, it will update the widget to the cache's state. + UpdateWidgetToCache(!aValue); // Don't deselect all if adding selection + return NS_OK; +} + +NS_IMETHODIMP +nsNativeSelectControlFrame::GetOptionSelected(PRInt32 aIndex, PRBool* aValue) +{ + // Determine if option is selected in local cache + GetOptionSelectedCache(aIndex, aValue); + return NS_OK; } nsresult nsNativeSelectControlFrame::UpdateWidgetToCache(PRBool aDeselectFirst) { + if (!mWidget) { + mCachedState = PR_TRUE; // Handle this update later when widget is created. + return NS_OK; + } + // Grab the list widget nsIListWidget* listWidget; nsresult result = mWidget->QueryInterface(kListWidgetIID, (void **) &listWidget); @@ -1469,3 +1521,86 @@ nsNativeSelectControlFrame::AppendFrames(nsIPresContext& aPresContext, //NS_PRECONDITION(PR_FALSE, "not a container"); return NS_ERROR_UNEXPECTED; } + +nsresult +nsNativeSelectControlFrame::Deselect() +{ + nsresult res = NS_OK; + for (PRInt32 i=0; (iSetData(i); + if (NS_SUCCEEDED(res)) { + PRBool okay = value->InsertElementAt((nsISupports *)thisVal, j++); + if (!okay) res = NS_ERROR_OUT_OF_MEMORY; // Most likely cause; + } + if (!NS_SUCCEEDED(res)) NS_RELEASE(thisVal); + } + } + if (!NS_SUCCEEDED(res)) break; + } + if (iCount(&count); + if (NS_SUCCEEDED(res)) { + nsISupportsPRInt32* thisVal = nsnull; + PRInt32 j=0; + for (PRUint32 k=0; kElementAt(k); + if (thisVal) { + res = thisVal->GetData(&j); + if (NS_SUCCEEDED(res)) { + res = SetOptionSelected(j, PR_TRUE); + } + } else { + res = NS_ERROR_UNEXPECTED; + } + if (!NS_SUCCEEDED(res)) break; + } + } + } + } + return res; +}