diff --git a/mozilla/content/html/content/src/nsHTMLAtoms.cpp b/mozilla/content/html/content/src/nsHTMLAtoms.cpp index a49ce9e2461..9d29d08d1e7 100644 --- a/mozilla/content/html/content/src/nsHTMLAtoms.cpp +++ b/mozilla/content/html/content/src/nsHTMLAtoms.cpp @@ -75,9 +75,7 @@ nsIAtom* nsHTMLAtoms::colgroup; nsIAtom* nsHTMLAtoms::cols; nsIAtom* nsHTMLAtoms::colspan; nsIAtom* nsHTMLAtoms::columnPseudo; -nsIAtom* nsHTMLAtoms::comboText; -nsIAtom* nsHTMLAtoms::comboTextSelected; -nsIAtom* nsHTMLAtoms::comboTextSelectedFocus; +nsIAtom* nsHTMLAtoms::combobox; nsIAtom* nsHTMLAtoms::commentPseudo; nsIAtom* nsHTMLAtoms::compact; nsIAtom* nsHTMLAtoms::content; @@ -93,11 +91,7 @@ nsIAtom* nsHTMLAtoms::dir; nsIAtom* nsHTMLAtoms::disabled; nsIAtom* nsHTMLAtoms::div; nsIAtom* nsHTMLAtoms::dl; -nsIAtom* nsHTMLAtoms::dropDownVisible; -nsIAtom* nsHTMLAtoms::dropDownHidden; -nsIAtom* nsHTMLAtoms::dropDownBtnOut; -nsIAtom* nsHTMLAtoms::dropDownBtnPressed; -nsIAtom* nsHTMLAtoms::dropDownList; +nsIAtom* nsHTMLAtoms::dropDownListPseudo; nsIAtom* nsHTMLAtoms::embed; nsIAtom* nsHTMLAtoms::encoding; nsIAtom* nsHTMLAtoms::enctype; @@ -343,10 +337,8 @@ void nsHTMLAtoms::AddrefAtoms() colgroup = NS_NewAtom("colgroup"); cols = NS_NewAtom("cols"); colspan = NS_NewAtom("colspan"); + combobox = NS_NewAtom("combobox"); columnPseudo = NS_NewAtom(":body-column"); - comboText = NS_NewAtom(":-moz-combobox-text"); - comboTextSelected = NS_NewAtom(":-moz-combobox-textselected"); - comboTextSelectedFocus = NS_NewAtom(":-moz-combobox-textselectedfocus"); commentPseudo = NS_NewAtom(":-moz-comment"); compact = NS_NewAtom("compact"); content = NS_NewAtom("content"); @@ -360,11 +352,7 @@ void nsHTMLAtoms::AddrefAtoms() div = NS_NewAtom("div"); disabled = NS_NewAtom("disabled"); dl = NS_NewAtom("dl"); - dropDownVisible = NS_NewAtom(":-moz-dropdown-visible"); - dropDownHidden = NS_NewAtom(":-moz-dropdown-hidden"); - dropDownBtnOut = NS_NewAtom(":-moz-dropdown-btn-out"); - dropDownBtnPressed = NS_NewAtom(":-moz-dropdown-btn-pressed"); - dropDownList = NS_NewAtom(":-moz-dropdown-list"); + dropDownListPseudo = NS_NewAtom(":-moz-dropdown-list"); datetime = NS_NewAtom("datetime"); data = NS_NewAtom("data"); @@ -611,10 +599,8 @@ void nsHTMLAtoms::ReleaseAtoms() NS_RELEASE(colgroup); NS_RELEASE(cols); NS_RELEASE(colspan); + NS_RELEASE(combobox); NS_RELEASE(columnPseudo); - NS_RELEASE(comboText); - NS_RELEASE(comboTextSelected); - NS_RELEASE(comboTextSelectedFocus); NS_RELEASE(commentPseudo); NS_RELEASE(compact); NS_RELEASE(content); @@ -630,11 +616,7 @@ void nsHTMLAtoms::ReleaseAtoms() NS_RELEASE(disabled); NS_RELEASE(div); NS_RELEASE(dl); - NS_RELEASE(dropDownVisible); - NS_RELEASE(dropDownHidden); - NS_RELEASE(dropDownBtnOut); - NS_RELEASE(dropDownBtnPressed); - NS_RELEASE(dropDownList); + NS_RELEASE(dropDownListPseudo); NS_RELEASE(embed); NS_RELEASE(encoding); NS_RELEASE(face); diff --git a/mozilla/content/html/content/src/nsHTMLAtoms.h b/mozilla/content/html/content/src/nsHTMLAtoms.h index 9dff9cbb1e6..8c8e459e413 100644 --- a/mozilla/content/html/content/src/nsHTMLAtoms.h +++ b/mozilla/content/html/content/src/nsHTMLAtoms.h @@ -96,9 +96,7 @@ public: static nsIAtom* cols; static nsIAtom* colspan; static nsIAtom* columnPseudo; - static nsIAtom* comboText; - static nsIAtom* comboTextSelected; - static nsIAtom* comboTextSelectedFocus; + static nsIAtom* combobox; static nsIAtom* commentPseudo; static nsIAtom* compact; static nsIAtom* content; @@ -115,11 +113,7 @@ public: static nsIAtom* disabled; static nsIAtom* div; static nsIAtom* dl; - static nsIAtom* dropDownVisible; - static nsIAtom* dropDownHidden; - static nsIAtom* dropDownBtnOut; - static nsIAtom* dropDownBtnPressed; - static nsIAtom* dropDownList; + static nsIAtom* dropDownListPseudo; static nsIAtom* embed; static nsIAtom* encoding; diff --git a/mozilla/content/shared/public/nsHTMLAtoms.h b/mozilla/content/shared/public/nsHTMLAtoms.h index 9dff9cbb1e6..8c8e459e413 100644 --- a/mozilla/content/shared/public/nsHTMLAtoms.h +++ b/mozilla/content/shared/public/nsHTMLAtoms.h @@ -96,9 +96,7 @@ public: static nsIAtom* cols; static nsIAtom* colspan; static nsIAtom* columnPseudo; - static nsIAtom* comboText; - static nsIAtom* comboTextSelected; - static nsIAtom* comboTextSelectedFocus; + static nsIAtom* combobox; static nsIAtom* commentPseudo; static nsIAtom* compact; static nsIAtom* content; @@ -115,11 +113,7 @@ public: static nsIAtom* disabled; static nsIAtom* div; static nsIAtom* dl; - static nsIAtom* dropDownVisible; - static nsIAtom* dropDownHidden; - static nsIAtom* dropDownBtnOut; - static nsIAtom* dropDownBtnPressed; - static nsIAtom* dropDownList; + static nsIAtom* dropDownListPseudo; static nsIAtom* embed; static nsIAtom* encoding; diff --git a/mozilla/content/shared/public/nsLayoutAtoms.h b/mozilla/content/shared/public/nsLayoutAtoms.h index d949fce3f2f..81769d9c977 100644 --- a/mozilla/content/shared/public/nsLayoutAtoms.h +++ b/mozilla/content/shared/public/nsLayoutAtoms.h @@ -56,6 +56,7 @@ public: static nsIAtom* colGroupList; static nsIAtom* fixedList; static nsIAtom* floaterList; + static nsIAtom* popupList; // Alphabetical list of pseudo tag names for non-element content static nsIAtom* commentTagName; diff --git a/mozilla/content/shared/src/nsHTMLAtoms.cpp b/mozilla/content/shared/src/nsHTMLAtoms.cpp index a49ce9e2461..9d29d08d1e7 100644 --- a/mozilla/content/shared/src/nsHTMLAtoms.cpp +++ b/mozilla/content/shared/src/nsHTMLAtoms.cpp @@ -75,9 +75,7 @@ nsIAtom* nsHTMLAtoms::colgroup; nsIAtom* nsHTMLAtoms::cols; nsIAtom* nsHTMLAtoms::colspan; nsIAtom* nsHTMLAtoms::columnPseudo; -nsIAtom* nsHTMLAtoms::comboText; -nsIAtom* nsHTMLAtoms::comboTextSelected; -nsIAtom* nsHTMLAtoms::comboTextSelectedFocus; +nsIAtom* nsHTMLAtoms::combobox; nsIAtom* nsHTMLAtoms::commentPseudo; nsIAtom* nsHTMLAtoms::compact; nsIAtom* nsHTMLAtoms::content; @@ -93,11 +91,7 @@ nsIAtom* nsHTMLAtoms::dir; nsIAtom* nsHTMLAtoms::disabled; nsIAtom* nsHTMLAtoms::div; nsIAtom* nsHTMLAtoms::dl; -nsIAtom* nsHTMLAtoms::dropDownVisible; -nsIAtom* nsHTMLAtoms::dropDownHidden; -nsIAtom* nsHTMLAtoms::dropDownBtnOut; -nsIAtom* nsHTMLAtoms::dropDownBtnPressed; -nsIAtom* nsHTMLAtoms::dropDownList; +nsIAtom* nsHTMLAtoms::dropDownListPseudo; nsIAtom* nsHTMLAtoms::embed; nsIAtom* nsHTMLAtoms::encoding; nsIAtom* nsHTMLAtoms::enctype; @@ -343,10 +337,8 @@ void nsHTMLAtoms::AddrefAtoms() colgroup = NS_NewAtom("colgroup"); cols = NS_NewAtom("cols"); colspan = NS_NewAtom("colspan"); + combobox = NS_NewAtom("combobox"); columnPseudo = NS_NewAtom(":body-column"); - comboText = NS_NewAtom(":-moz-combobox-text"); - comboTextSelected = NS_NewAtom(":-moz-combobox-textselected"); - comboTextSelectedFocus = NS_NewAtom(":-moz-combobox-textselectedfocus"); commentPseudo = NS_NewAtom(":-moz-comment"); compact = NS_NewAtom("compact"); content = NS_NewAtom("content"); @@ -360,11 +352,7 @@ void nsHTMLAtoms::AddrefAtoms() div = NS_NewAtom("div"); disabled = NS_NewAtom("disabled"); dl = NS_NewAtom("dl"); - dropDownVisible = NS_NewAtom(":-moz-dropdown-visible"); - dropDownHidden = NS_NewAtom(":-moz-dropdown-hidden"); - dropDownBtnOut = NS_NewAtom(":-moz-dropdown-btn-out"); - dropDownBtnPressed = NS_NewAtom(":-moz-dropdown-btn-pressed"); - dropDownList = NS_NewAtom(":-moz-dropdown-list"); + dropDownListPseudo = NS_NewAtom(":-moz-dropdown-list"); datetime = NS_NewAtom("datetime"); data = NS_NewAtom("data"); @@ -611,10 +599,8 @@ void nsHTMLAtoms::ReleaseAtoms() NS_RELEASE(colgroup); NS_RELEASE(cols); NS_RELEASE(colspan); + NS_RELEASE(combobox); NS_RELEASE(columnPseudo); - NS_RELEASE(comboText); - NS_RELEASE(comboTextSelected); - NS_RELEASE(comboTextSelectedFocus); NS_RELEASE(commentPseudo); NS_RELEASE(compact); NS_RELEASE(content); @@ -630,11 +616,7 @@ void nsHTMLAtoms::ReleaseAtoms() NS_RELEASE(disabled); NS_RELEASE(div); NS_RELEASE(dl); - NS_RELEASE(dropDownVisible); - NS_RELEASE(dropDownHidden); - NS_RELEASE(dropDownBtnOut); - NS_RELEASE(dropDownBtnPressed); - NS_RELEASE(dropDownList); + NS_RELEASE(dropDownListPseudo); NS_RELEASE(embed); NS_RELEASE(encoding); NS_RELEASE(face); diff --git a/mozilla/content/shared/src/nsLayoutAtoms.cpp b/mozilla/content/shared/src/nsLayoutAtoms.cpp index 27bf14d20c1..77e1f429362 100644 --- a/mozilla/content/shared/src/nsLayoutAtoms.cpp +++ b/mozilla/content/shared/src/nsLayoutAtoms.cpp @@ -42,6 +42,7 @@ nsIAtom* nsLayoutAtoms::bulletList; nsIAtom* nsLayoutAtoms::colGroupList; nsIAtom* nsLayoutAtoms::fixedList; nsIAtom* nsLayoutAtoms::floaterList; +nsIAtom* nsLayoutAtoms::popupList; // pseudo tag names for non-element content nsIAtom* nsLayoutAtoms::commentTagName; @@ -96,6 +97,7 @@ void nsLayoutAtoms::AddrefAtoms() colGroupList = NS_NewAtom("ColGroup-list"); fixedList = NS_NewAtom("Fixed-list"); floaterList = NS_NewAtom("Floater-list"); + popupList = NS_NewAtom("Popup-list"); commentTagName = NS_NewAtom("__moz_comment"); textTagName = NS_NewAtom("__moz_text"); @@ -150,6 +152,7 @@ void nsLayoutAtoms::ReleaseAtoms() NS_RELEASE(colGroupList); NS_RELEASE(fixedList); NS_RELEASE(floaterList); + NS_RELEASE(popupList); NS_RELEASE(commentTagName); NS_RELEASE(textTagName); diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 34d8bc46839..75a5ab705f7 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -2397,140 +2397,88 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresContext* aPresContex if (eWidgetRendering_Gfx == mode) { // Construct a frame-based listbox or combobox - nsIDOMHTMLSelectElement* dselect = nsnull; + nsIDOMHTMLSelectElement* select = nsnull; PRInt32 size = 1; - nsresult result = aContent->QueryInterface(kIDOMHTMLSelectElementIID, (void**)&dselect); - if (NS_OK == result) { - result = dselect->GetSize(&size); + nsresult result = aContent->QueryInterface(kIDOMHTMLSelectElementIID, (void**)&select); + if (NS_SUCCEEDED(result)) { + result = select->GetSize(&size); if ((1 == size) || (kNoSizeSpecified == size)) { - // Construct a frame-based combo box - nsIFrame * comboboxFrame; - rv = NS_NewComboboxControlFrame(&comboboxFrame); + // Construct a frame-based combo box. + // The frame-based combo box is built out of tree parts. A display area, a button and + // a dropdown list. The display area and button are created through anonymous content. + // The drop-down list's frame is created explicitly. The combobox frame shares it's content + // with the drop-down list. + nsIFrame * comboboxFrame; + rv = NS_NewComboboxControlFrame(&comboboxFrame); - nsIFrame* geometricParent = aParentFrame; - if (aIsAbsolutelyPositioned) { - geometricParent = aState.mAbsoluteItems.containingBlock; - } else if (aIsFixedPositioned) { - geometricParent = aState.mFixedItems.containingBlock; + // Determine geometric parent for the combobox frame + nsIFrame* geometricParent = aParentFrame; + if (aIsAbsolutelyPositioned) { + geometricParent = aState.mAbsoluteItems.containingBlock; + } else if (aIsFixedPositioned) { + geometricParent = aState.mFixedItems.containingBlock; + } + // Initialize the combobox frame + comboboxFrame->Init(*aPresContext, aContent, geometricParent, aStyleContext, nsnull); + nsIComboboxControlFrame* comboBox = nsnull; + if (NS_SUCCEEDED(comboboxFrame->QueryInterface(kIComboboxControlFrameIID, (void**)&comboBox))) { + // Create a listbox + nsIFrame * listFrame; + rv = NS_NewListControlFrame(&listFrame); + + // Notify the listbox that it is being used as a dropdown list. + nsIListControlFrame * listControlFrame; + if (NS_SUCCEEDED(listFrame->QueryInterface(kIListControlFrameIID, (void**)&listControlFrame))) { + listControlFrame->SetComboboxFrame(comboboxFrame); } - - comboboxFrame->Init(*aPresContext, aContent, geometricParent, aStyleContext, nsnull); - nsIComboboxControlFrame* comboBox = nsnull; - if (NS_OK == comboboxFrame->QueryInterface(kIComboboxControlFrameIID, (void**)&comboBox)) { - nsIFrame * listFrame; - rv = NS_NewListControlFrame(&listFrame); - - // Get the style context that has been set for the combo box so it can be passed used - // to create the style context's for the drop down list. - nsIStyleContext* comboStyleContext; - comboboxFrame->GetStyleContext(&comboStyleContext); - - // This is important to do before it is initialized - // it tells it that it is in "DropDown Mode" - nsIListControlFrame * listControlFrame; - if (NS_OK == listFrame->QueryInterface(kIListControlFrameIID, (void**)&listControlFrame)) { - listControlFrame->SetComboboxFrame(comboboxFrame); - } - - //XXX: TODO: Make sure that a failure to resolve the following - //pseudo style will still work. - - // Set up the Pseudo Style contents - - // Dropdown list style - nsCOMPtr listStyle; - aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::dropDownList, comboStyleContext, PR_FALSE, - getter_AddRefs(listStyle)); + // Notify combobox that it should use the listbox as it's popup + comboBox->SetDropDown(listFrame); - // Dropdown list visible style - nsCOMPtr visiblePseudoStyle; - aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::dropDownVisible, comboStyleContext, PR_FALSE, - getter_AddRefs(visiblePseudoStyle)); - - // Dropdown list hidden style - nsCOMPtr hiddenPseudoStyle; - aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::dropDownHidden, comboStyleContext, PR_FALSE, - getter_AddRefs(hiddenPseudoStyle)); + // Resolve psuedo element style for the dropdown list + nsCOMPtr listStyle; + rv = aPresContext->ResolvePseudoStyleContextFor(aContent, + nsHTMLAtoms::dropDownListPseudo, + aStyleContext, + PR_FALSE, + getter_AddRefs(listStyle)); - // Done creating drop-down list style contexts - NS_RELEASE(comboStyleContext); + // Initialize the scroll frame positioned. Note that it is NOT initialized as + // absolutely positioned. + nsIFrame* newFrame = nsnull; + InitializeScrollFrame(aPresContext, aState, listFrame, aContent, comboboxFrame, + listStyle, newFrame, PR_FALSE, PR_FALSE, PR_TRUE); - // Initialize the scroll frame as absolutely positioned. - InitializeScrollFrame(aPresContext, aState, listFrame, aContent, comboboxFrame, - listStyle, aNewFrame, PR_TRUE, PR_FALSE, PR_TRUE); + // Set flag so the events go to the listFrame not child frames. + // XXX: We should replace this with a real widget manager similar + // to how the nsFormControlFrame works. Re-directing events is a temporary Kludge. + nsIView *listView; + listFrame->GetView(&listView); + NS_ASSERTION(nsnull != listView,"ListFrame's view is nsnull"); + listView->SetViewFlags(NS_VIEW_PUBLIC_FLAG_DONT_CHECK_CHILDREN); - - // Set flag so the events go to the listFrame not child frames. - // XXX: We should replace this with a real widget manager similar - // to how the nsFormControlFrame works. - // Re-directing events is a temporary Kludge. - nsIView *listView; - listFrame->GetView(&listView); - NS_ASSERTION(nsnull != listView,"ListFrame's view is nsnull"); - listView->SetViewFlags(NS_VIEW_PUBLIC_FLAG_DONT_CHECK_CHILDREN); - - // Set initial visibility to hidden for the drop-down list - // XXX: This should not be necessary. Need to restructure the combo box as follows: - // Derive nsComboboxFrame from nsAreaFrame. Attach the placeholder frame, a label frame and - // a button frame. Override reresolve style context and reresolve the style on the ListBox. - // The event state manager should then be asked to set active and non-active based on - // The mouse click this would get rid of all of the ugly code here. The setting of the active - // Should cause re-resolution of the AreaFrame which will re-sync it. KMM. - listFrame->ReResolveStyleContext(aPresContext, hiddenPseudoStyle, NS_STYLE_HINT_NONE, nsnull, nsnull); - listView->SetVisibility(nsViewVisibility_kHide); - - - // Create a place holder frame for the dropdown list - nsIFrame* placeholderFrame = nsnull; - CreatePlaceholderFrameFor(aPresContext, aContent, aNewFrame, aStyleContext, - aParentFrame, &placeholderFrame); - aFrameItems.AddChild(placeholderFrame); - - // Add the absolutely positioned frame to its containing block's list - // of child frames - aState.mAbsoluteItems.AddChild(listFrame); - - listFrame = aNewFrame; - - // This needs to be done "after" the ListFrame has it's ChildList set - // because the SetInitChildList intializes the ListBox selection state - // and this method initializes the ComboBox's selection state - comboBox->SetDropDown(placeholderFrame, listFrame); - - - // Set up the Pseudo Style contents for combo box button pressed and - // out. - //XXX: TODO: Make this work even if resolving the pseudo style fails. - - nsCOMPtr outPseudoStyle; - aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::dropDownBtnOut, aStyleContext, PR_FALSE, - getter_AddRefs(outPseudoStyle)); - - nsCOMPtr pressPseudoStyle; - aPresContext->ResolvePseudoStyleContextFor(aContent, nsHTMLAtoms::dropDownBtnPressed, - aStyleContext, PR_FALSE, getter_AddRefs(pressPseudoStyle)); - - comboBox->SetDropDownStyleContexts(visiblePseudoStyle, hiddenPseudoStyle); - comboBox->SetButtonStyleContexts(outPseudoStyle, pressPseudoStyle); + nsIFrame* frame = nsnull; + if (NS_SUCCEEDED(comboboxFrame->QueryInterface(kIFrameIID, (void**)&frame))) { + nsFrameItems childItems; - nsIFrame* frame = nsnull; - if (NS_OK == comboboxFrame->QueryInterface(kIFrameIID, (void**)&frame)) { - nsFrameItems childItems; - frame->SetInitialChildList(*aPresContext, nsnull, - childItems.childList); - } - aProcessChildren = PR_FALSE; - //XXX: TODO: Need to set an option on the view that was created for the dropdown list - //to be a borderless top-level window. - - aNewFrame = comboboxFrame; - aFrameHasBeenInitialized = PR_TRUE; - } + // Create display and button frames from the combobox'es anonymous content + CreateAnonymousFrames(aPresContext, nsHTMLAtoms::combobox, aState, aContent, frame, + childItems); + + frame->SetInitialChildList(*aPresContext, nsnull, + childItems.childList); + // Initialize the additional popup child list which contains the dropdown list frame. + nsFrameItems popupItems; + popupItems.AddChild(listFrame); + frame->SetInitialChildList(*aPresContext, nsLayoutAtoms::popupList, + popupItems.childList); + } + // Don't process, the children, They are already processed by the InitializeScrollFrame + // call above. + aProcessChildren = PR_FALSE; + aNewFrame = comboboxFrame; + aFrameHasBeenInitialized = PR_TRUE; + } } else { // Construct a frame-based list box nsIFrame * listFrame; @@ -2550,7 +2498,7 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresContext* aPresContex listView->SetViewFlags(NS_VIEW_PUBLIC_FLAG_DONT_CHECK_CHILDREN); aFrameHasBeenInitialized = PR_TRUE; } - NS_RELEASE(dselect); + NS_RELEASE(select); } else { rv = NS_NewSelectControlFrame(&aNewFrame); } @@ -2739,6 +2687,7 @@ nsCSSFrameConstructor::ConstructFrameByTag(nsIPresContext* aPresContext PR_TRUE, childItems); } + // if there are any anonymous children create frames for them CreateAnonymousFrames(aPresContext, aTag, aState, aContent, newFrame, childItems); @@ -2818,14 +2767,21 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresContext* aPresConte // only these tags types can have anonymous content. We do this check for performance // reasons. If we did a query interface on every tag it would be very inefficient. if (aTag != nsHTMLAtoms::input && + aTag != nsHTMLAtoms::combobox && aTag != nsXULAtoms::slider && aTag != nsXULAtoms::splitter && - aTag != nsXULAtoms::scrollbar) { + aTag != nsXULAtoms::scrollbar + ) { return NS_OK; } - + // get the document + nsIDocument* doc = nsnull; + nsresult rv = aContent->GetDocument(doc); + if (NS_FAILED(rv) || !doc) + return rv; + nsCOMPtr creator(do_QueryInterface(aNewFrame)); if (!creator) @@ -2849,6 +2805,8 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresContext* aPresConte nsCOMPtr content(do_QueryInterface(node)); content->SetParent(aContent); + content->SetDocument(doc, PR_TRUE); + // create the frame and attach it to our frame ConstructFrame(aPresContext, aState, content, aNewFrame, PR_FALSE, aChildItems); } diff --git a/mozilla/layout/base/nsCSSFrameConstructor.h b/mozilla/layout/base/nsCSSFrameConstructor.h index 29b85b2444b..93584718afc 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.h +++ b/mozilla/layout/base/nsCSSFrameConstructor.h @@ -407,6 +407,7 @@ protected: nsresult ConstructTextControlFrame(nsIPresContext* aPresContext, nsIFrame*& aNewFrame); + nsresult ConstructSelectFrame(nsIPresContext* aPresContext, nsFrameConstructorState& aState, nsIContent* aContent, diff --git a/mozilla/layout/base/nsLayoutAtoms.cpp b/mozilla/layout/base/nsLayoutAtoms.cpp index 27bf14d20c1..77e1f429362 100644 --- a/mozilla/layout/base/nsLayoutAtoms.cpp +++ b/mozilla/layout/base/nsLayoutAtoms.cpp @@ -42,6 +42,7 @@ nsIAtom* nsLayoutAtoms::bulletList; nsIAtom* nsLayoutAtoms::colGroupList; nsIAtom* nsLayoutAtoms::fixedList; nsIAtom* nsLayoutAtoms::floaterList; +nsIAtom* nsLayoutAtoms::popupList; // pseudo tag names for non-element content nsIAtom* nsLayoutAtoms::commentTagName; @@ -96,6 +97,7 @@ void nsLayoutAtoms::AddrefAtoms() colGroupList = NS_NewAtom("ColGroup-list"); fixedList = NS_NewAtom("Fixed-list"); floaterList = NS_NewAtom("Floater-list"); + popupList = NS_NewAtom("Popup-list"); commentTagName = NS_NewAtom("__moz_comment"); textTagName = NS_NewAtom("__moz_text"); @@ -150,6 +152,7 @@ void nsLayoutAtoms::ReleaseAtoms() NS_RELEASE(colGroupList); NS_RELEASE(fixedList); NS_RELEASE(floaterList); + NS_RELEASE(popupList); NS_RELEASE(commentTagName); NS_RELEASE(textTagName); diff --git a/mozilla/layout/base/nsLayoutAtoms.h b/mozilla/layout/base/nsLayoutAtoms.h index d949fce3f2f..81769d9c977 100644 --- a/mozilla/layout/base/nsLayoutAtoms.h +++ b/mozilla/layout/base/nsLayoutAtoms.h @@ -56,6 +56,7 @@ public: static nsIAtom* colGroupList; static nsIAtom* fixedList; static nsIAtom* floaterList; + static nsIAtom* popupList; // Alphabetical list of pseudo tag names for non-element content static nsIAtom* commentTagName; diff --git a/mozilla/layout/base/public/nsLayoutAtoms.h b/mozilla/layout/base/public/nsLayoutAtoms.h index d949fce3f2f..81769d9c977 100644 --- a/mozilla/layout/base/public/nsLayoutAtoms.h +++ b/mozilla/layout/base/public/nsLayoutAtoms.h @@ -56,6 +56,7 @@ public: static nsIAtom* colGroupList; static nsIAtom* fixedList; static nsIAtom* floaterList; + static nsIAtom* popupList; // Alphabetical list of pseudo tag names for non-element content static nsIAtom* commentTagName; diff --git a/mozilla/layout/base/src/nsLayoutAtoms.cpp b/mozilla/layout/base/src/nsLayoutAtoms.cpp index 27bf14d20c1..77e1f429362 100644 --- a/mozilla/layout/base/src/nsLayoutAtoms.cpp +++ b/mozilla/layout/base/src/nsLayoutAtoms.cpp @@ -42,6 +42,7 @@ nsIAtom* nsLayoutAtoms::bulletList; nsIAtom* nsLayoutAtoms::colGroupList; nsIAtom* nsLayoutAtoms::fixedList; nsIAtom* nsLayoutAtoms::floaterList; +nsIAtom* nsLayoutAtoms::popupList; // pseudo tag names for non-element content nsIAtom* nsLayoutAtoms::commentTagName; @@ -96,6 +97,7 @@ void nsLayoutAtoms::AddrefAtoms() colGroupList = NS_NewAtom("ColGroup-list"); fixedList = NS_NewAtom("Fixed-list"); floaterList = NS_NewAtom("Floater-list"); + popupList = NS_NewAtom("Popup-list"); commentTagName = NS_NewAtom("__moz_comment"); textTagName = NS_NewAtom("__moz_text"); @@ -150,6 +152,7 @@ void nsLayoutAtoms::ReleaseAtoms() NS_RELEASE(colGroupList); NS_RELEASE(fixedList); NS_RELEASE(floaterList); + NS_RELEASE(popupList); NS_RELEASE(commentTagName); NS_RELEASE(textTagName); diff --git a/mozilla/layout/forms/nsComboboxControlFrame.cpp b/mozilla/layout/forms/nsComboboxControlFrame.cpp index ddb75962403..0202a7ef1aa 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.cpp +++ b/mozilla/layout/forms/nsComboboxControlFrame.cpp @@ -18,51 +18,32 @@ #include "nsCOMPtr.h" #include "nsComboboxControlFrame.h" #include "nsFormFrame.h" -#include "nsButtonControlFrame.h" -#include "nsTextControlFrame.h" -#include "nsIContent.h" -#include "prtypes.h" -#include "nsIAtom.h" -#include "nsIPresContext.h" +#include "nsFormControlFrame.h" #include "nsIHTMLContent.h" #include "nsHTMLIIDs.h" #include "nsHTMLAtoms.h" -#include "nsIFileWidget.h" -#include "nsITextWidget.h" -#include "nsWidgetsCID.h" -#include "nsIComponentManager.h" -#include "nsIView.h" #include "nsHTMLParts.h" -#include "nsIDOMHTMLInputElement.h" #include "nsIFormControl.h" #include "nsINameSpaceManager.h" -#include "nsITextContent.h" - -// Used for Paint -#include "nsCSSRendering.h" -#include "nsIDeviceContext.h" - -#include "nsIPresShell.h" -#include "nsIView.h" -#include "nsIViewManager.h" -#include "nsViewsCID.h" +#include "nsIDOMEventReceiver.h" +#include "nsLayoutAtoms.h" #include "nsIDOMElement.h" #include "nsListControlFrame.h" #include "nsIListControlFrame.h" #include "nsIDOMHTMLCollection.h" #include "nsIDOMHTMLSelectElement.h" #include "nsIDOMHTMLOptionElement.h" +#include "nsIPresShell.h" +#include "nsISupportsArray.h" +#include "nsIDeviceContext.h" +#include "nsIView.h" -static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); -static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); -static NS_DEFINE_IID(kCFileWidgetCID, NS_FILEWIDGET_CID); -static NS_DEFINE_IID(kIFileWidgetIID, NS_IFILEWIDGET_IID); -static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID); static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); static NS_DEFINE_IID(kIComboboxControlFrameIID, NS_ICOMBOBOXCONTROLFRAME_IID); -static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID); -static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); static NS_DEFINE_IID(kIListControlFrameIID, NS_ILISTCONTROLFRAME_IID); +static NS_DEFINE_IID(kIDOMMouseListenerIID, NS_IDOMMOUSELISTENER_IID); +static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); +static NS_DEFINE_IID(kIAnonymousContentCreatorIID, NS_IANONYMOUS_CONTENT_CREATOR_IID); // Drop down list event management. // The combo box uses the following strategy for managing the @@ -76,6 +57,11 @@ static NS_DEFINE_IID(kIListControlFrameIID, NS_ILISTCONTROLFRAME_IID); // The ListWasSelected code will turn off mouse-capture for the drop-down list. // The drop-down list does not explicitly set capture when it is in the drop-down mode. + +//XXX: This is temporary. It simulates psuedo states by using a attribute selector on + +const char * kMozDropdownActive = "-moz-dropdown-active"; + nsresult NS_NewComboboxControlFrame(nsIFrame** aNewFrame) { @@ -92,29 +78,30 @@ NS_NewComboboxControlFrame(nsIFrame** aNewFrame) } nsComboboxControlFrame::nsComboboxControlFrame() - : nsHTMLContainerFrame() + : nsAreaFrame() { - mFormFrame = nsnull; - mListFrame = nsnull; + mPresContext = nsnull; + mFormFrame = nsnull; mListControlFrame = nsnull; - mPlaceHolderFrame = nsnull; - mVisibleStyleContext = nsnull; - mHiddenStyleContext = nsnull; - mCurrentStyleContext = nsnull; - mBlockTextStyle = nsnull; - mBlockTextSelectedStyle = nsnull; - mBlockTextSelectedFocusStyle = nsnull; - mFirstTime = PR_TRUE; - mGotFocus = PR_FALSE; + mTextStr = ""; + mDisplayContent = nsnull; + mButtonContent = nsnull; + mDroppedDown = PR_FALSE; + mDisplayFrame = nsnull; + mButtonFrame = nsnull; + mDropdownFrame = nsnull; + + //Shrink the area around it's contents + SetFlags(NS_BLOCK_SHRINK_WRAP); } //-------------------------------------------------------------- nsComboboxControlFrame::~nsComboboxControlFrame() { - NS_IF_RELEASE(mVisibleStyleContext); - NS_IF_RELEASE(mHiddenStyleContext); - NS_IF_RELEASE(mBlockTextStyle); mFormFrame = nsnull; + NS_IF_RELEASE(mPresContext); + NS_IF_RELEASE(mDisplayContent); + NS_IF_RELEASE(mButtonContent); } //-------------------------------------------------------------- @@ -132,9 +119,32 @@ nsComboboxControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) if (aIID.Equals(kIFormControlFrameIID)) { *aInstancePtr = (void*) ((nsIFormControlFrame*) this); return NS_OK; + } else if (aIID.Equals(kIDOMMouseListenerIID)) { + *aInstancePtr = (void*)(nsIDOMMouseListener*) this; + NS_ADDREF_THIS(); + return NS_OK; + } else if (aIID.Equals(kIAnonymousContentCreatorIID)) { + *aInstancePtr = (void*)(nsIAnonymousContentCreator*) this; + NS_ADDREF_THIS(); + return NS_OK; } - return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr); + return nsAreaFrame::QueryInterface(aIID, aInstancePtr); +} + + +NS_IMETHODIMP +nsComboboxControlFrame::Init(nsIPresContext& aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) +{ + // Need to hold on the pres context because it is used later in methods + // which don't have it passed in. + mPresContext = &aPresContext; + NS_ADDREF(mPresContext); + return nsAreaFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); } //-------------------------------------------------------------- @@ -149,15 +159,22 @@ nsComboboxControlFrame::IsSuccessful(nsIFormControlFrame* aSubmitter) // Initialize the text string in the combobox using either the current // selection in the list box or the first item item in the list box. -void nsComboboxControlFrame::InitTextStr() +void +nsComboboxControlFrame::InitTextStr(PRBool aUpdate) { + nsIFormControlFrame* fcFrame = nsnull; + nsIFrame* dropdownFrame = GetDropdownFrame(); + nsresult result = dropdownFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + + // Reset the list, so we can ask it for it's selected item. + fcFrame->Reset(); + // Update the selected text string mListControlFrame->GetSelectedItem(mTextStr); if (mTextStr == "") { // No selection so use the first item in the list box - nsIFormControlFrame* fcFrame = nsnull; - nsresult result = mListFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + if ((NS_OK == result) && (nsnull != fcFrame)) { // Set listbox selection to first item in the list box fcFrame->SetProperty(nsHTMLAtoms::selectedindex, "0"); @@ -165,21 +182,28 @@ void nsComboboxControlFrame::InitTextStr() mListControlFrame->GetSelectedItem(mTextStr); } } + + // Update the display by setting the value attribute + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, mTextStr, aUpdate); } //-------------------------------------------------------------- +// Reset the combo box back to it original state. + void nsComboboxControlFrame::Reset() { - SetFocus(PR_TRUE, PR_TRUE); + // Reset the dropdown list to its original state nsIFormControlFrame* fcFrame = nsnull; - nsresult result = mListFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + nsIFrame* dropdownFrame = GetDropdownFrame(); + nsresult result = dropdownFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); if ((NS_OK == result) && (nsnull != fcFrame)) { fcFrame->Reset(); } - InitTextStr(); + // Update the combobox using the text string returned from the dropdown list + InitTextStr(PR_TRUE); } void @@ -190,7 +214,6 @@ nsComboboxControlFrame::PostCreateWidget(nsIPresContext* aPresContext, Reset(); } - //-------------------------------------------------------------- NS_IMETHODIMP nsComboboxControlFrame::GetType(PRInt32* aType) const @@ -224,7 +247,7 @@ nsComboboxControlFrame::GetFont(nsIPresContext* aPresContext, nscoord nsComboboxControlFrame::GetVerticalBorderWidth(float aPixToTwip) const { - return NSIntPixelsToTwips(3, aPixToTwip); + return 0; } @@ -232,7 +255,7 @@ nsComboboxControlFrame::GetVerticalBorderWidth(float aPixToTwip) const nscoord nsComboboxControlFrame::GetHorizontalBorderWidth(float aPixToTwip) const { - return GetVerticalBorderWidth(aPixToTwip); + return 0; } @@ -255,335 +278,421 @@ nsComboboxControlFrame::GetHorizontalInsidePadding(nsIPresContext& aPresContext, } -//-------------------------------------------------------------- + void nsComboboxControlFrame::SetFocus(PRBool aOn, PRBool aRepaint) { - //XXX: TODO Make set focus work - //mContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, "SELECTED", PR_TRUE); - mGotFocus = aOn; - if (aRepaint) { - nsFormControlHelper::ForceDrawFrame(this); + //XXX: TODO Implement focus for combobox. +} + +// Toggle dropdown list. + +void +nsComboboxControlFrame::ToggleList(nsIPresContext* aPresContext) +{ + if (PR_TRUE == mDroppedDown) { + ShowList(aPresContext, PR_FALSE); + } else { + ShowList(aPresContext, PR_TRUE); } } -//-------------------------------------------------------------- + +void +nsComboboxControlFrame::ShowPopup(PRBool aShowPopup) +{ + //XXX: This is temporary. It simulates a psuedo dropdown states by using a attribute selector + // This will not be need if the event state supports active states for use with the dropdown list + // Currently, the event state manager will reset the active state to the content which has focus + // which causes the active state to be removed from the event state manager immediately after it + // it the select is set to the active state. + + nsCOMPtr activeAtom ( dont_QueryInterface(NS_NewAtom(kMozDropdownActive))); + if (PR_TRUE == aShowPopup) { + mContent->SetAttribute(kNameSpaceID_None, activeAtom, "", PR_TRUE); + } else { + mContent->UnsetAttribute(kNameSpaceID_None, activeAtom, PR_TRUE); + } +} + +// Show the dropdown list + +void +nsComboboxControlFrame::ShowList(nsIPresContext* aPresContext, PRBool aShowList) +{ + if (PR_TRUE == aShowList) { + mListControlFrame->AboutToDropDown(); + ShowPopup(PR_TRUE); + mDroppedDown = PR_TRUE; + // The listcontrol frame will call back to the nsComboboxControlFrame's ListWasSelected + // which will stop the capture. + mListControlFrame->CaptureMouseEvents(PR_TRUE); + } else { + ShowPopup(PR_FALSE); + mDroppedDown = PR_FALSE; + } +} + + +//------------------------------------------------------------- // this is in response to the MouseClick from the containing browse button // XXX: TODO still need to get filters from accept attribute -void nsComboboxControlFrame::MouseClicked(nsIPresContext* aPresContext) +void +nsComboboxControlFrame::MouseClicked(nsIPresContext* aPresContext) { - if (nsnull != mListControlFrame) { - //XXX: Make this work SetFocus(PR_FALSE, PR_TRUE); - mCurrentStyleContext = (mCurrentStyleContext == mHiddenStyleContext ? mVisibleStyleContext : mHiddenStyleContext); - if (mCurrentStyleContext == mVisibleStyleContext) { - mListControlFrame->AboutToDropDown(); - - nsIFormControlFrame* fcFrame = nsnull; - nsresult result = mListFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); - if ((NS_OK == result) && (nsnull != fcFrame)) { - //XXX: Make this work fcFrame->SetFocus(PR_TRUE, PR_FALSE); - } + ToggleList(aPresContext); +} - } else { - //XXX: Make this work SetFocus(PR_TRUE, PR_TRUE); - } - //XXX: This should not be necessary. Need to restructure the combo box as follows: - // Derive nsComboboxFrame from nsAreaFrame. Attach the placeholder frame, a label frame and - // a button frame. Override reresolve style context and reresolve the style on the ListBox. - // The event state manager should then be asked to set active and non-active based on - // The mouse click this would get rid of all of the ugly code here. The setting of the active - // Should cause re-resolution of the AreaFrame which will re-sync it. KMM. - mListFrame->ReResolveStyleContext(aPresContext, mCurrentStyleContext, NS_STYLE_HINT_NONE, nsnull, nsnull); - - // Resync view with frame. - const nsStyleDisplay* disp = (const - nsStyleDisplay*)mCurrentStyleContext->GetStyleData(eStyleStruct_Display); - nsIView * view; - mListFrame->GetView(&view); - if (view) { - view->SetVisibility(NS_STYLE_VISIBILITY_HIDDEN == disp->mVisible ? - nsViewVisibility_kHide:nsViewVisibility_kShow); - } - nsFormControlHelper::ForceDrawFrame(mListFrame); - //XXX: End of the ugly code. - +nsresult +nsComboboxControlFrame::ReflowComboChildFrame(nsIFrame* aFrame, + nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus, + nscoord aAvailableWidth, + nscoord aAvailableHeight) +{ + // Constrain the child's width and height to aAvailableWidth and aAvailableHeight + nsSize availSize(aAvailableWidth, aAvailableHeight); + nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aFrame, + availSize); + kidReflowState.computedWidth = aAvailableWidth; + kidReflowState.computedHeight = aAvailableHeight; + + // Reflow child + nsresult rv = ReflowChild(aFrame, aPresContext, aDesiredSize, kidReflowState, aStatus); + + // Set the child's width and height to it's desired size + nsRect rect; + aFrame->GetRect(rect); + rect.width = aDesiredSize.width; + rect.height = aDesiredSize.height; + aFrame->SetRect(rect); + return rv; +} + +// Suggest a size for the child frame. +// Only frames which implement the nsIFormControlFrame interface and +// honor the SetSuggestedSize method will be placed and sized correctly. + +void +nsComboboxControlFrame::SetChildFrameSize(nsIFrame* aFrame, nscoord aWidth, nscoord aHeight) +{ + nsIFormControlFrame* fcFrame = nsnull; + nsresult result = aFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + if (NS_SUCCEEDED(result) && (nsnull != fcFrame)) { + fcFrame->SetSuggestedSize(aWidth, aHeight); } } -//-------------------------------------------------------------- -NS_IMETHODIMP nsComboboxControlFrame::Reflow(nsIPresContext& aPresContext, +nsresult +nsComboboxControlFrame::GetPrimaryComboFrame(nsIPresContext& aPresContext, nsIContent* aContent, nsIFrame** aFrame) +{ + nsresult rv = NS_OK; + // Get the primary frame from the presentation shell. + nsCOMPtr presShell; + rv = aPresContext.GetShell(getter_AddRefs(presShell)); + if (NS_SUCCEEDED(rv) && presShell) { + presShell->GetPrimaryFrameFor(aContent, aFrame); + } + return rv; +} + +nsIFrame* +nsComboboxControlFrame::GetButtonFrame(nsIPresContext& aPresContext) +{ + if (mButtonFrame == nsnull) { + NS_ASSERTION(mButtonContent != nsnull, "nsComboboxControlFrame mButtonContent is null"); + GetPrimaryComboFrame(aPresContext, mButtonContent, &mButtonFrame); + } + + return mButtonFrame; +} + +nsIFrame* +nsComboboxControlFrame::GetDisplayFrame(nsIPresContext& aPresContext) +{ + if (mDisplayFrame == nsnull) { + NS_ASSERTION(mDisplayContent != nsnull, "nsComboboxControlFrame mDisplayContent is null"); + GetPrimaryComboFrame(aPresContext, mDisplayContent, &mDisplayFrame); + } + + return mDisplayFrame; +} + +nsIFrame* +nsComboboxControlFrame::GetDropdownFrame() +{ + return mDropdownFrame; +} + + +nsresult +nsComboboxControlFrame::GetScreenHeight(nsIPresContext& aPresContext, + nscoord& aHeight) +{ + aHeight = 0; + nsIDeviceContext* context; + aPresContext.GetDeviceContext( &context ); + if ( nsnull != context ) + { + PRInt32 height; + PRInt32 width; + context->GetDeviceSurfaceDimensions(width, height); + float devUnits; + context->GetDevUnitsToAppUnits(devUnits); + aHeight = NSToIntRound(float( height) / devUnits ); + NS_RELEASE( context ); + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + + +nsresult +nsComboboxControlFrame::PositionDropdown(nsIPresContext& aPresContext, + nscoord aHeight, + nsRect aAbsoluteTwipsRect, + nsRect aAbsolutePixelRect) +{ + // Position the dropdown list. It is positioned below the display frame if there is enough + // room on the screen to display the entire list. Otherwise it is placed above the display + // frame. + + // Note: As first glance, it appears that you could simply get the absolute bounding box for the + // dropdown list by first getting it's view, then getting the view's nsIWidget, then asking the nsIWidget + // for it's AbsoluteBounds. The problem with this approach, is that the dropdown lists y location can + // change based on whether the dropdown is placed below or above the display frame. + // The approach, taken here is to get use the absolute position of the display frame and use it's location + // to determine if the dropdown will go offscreen. + + // Use the height calculated for the area frame so it includes both + // the display and button heights. + nsresult rv = NS_OK; + nsIFrame* dropdownFrame = GetDropdownFrame(); + nscoord dropdownYOffset = aHeight; +/* XXX: Enable this code to debug popping up above the display frame, rather than below it + nscoord screenHeightInPixels = 0; + if (NS_SUCCEEDED(GetScreenHeight(aPresContext, screenHeightInPixels))) { + nsRect absoluteRect; + + // Get the height of the dropdown list in pixels. + nsRect dropdownRect; + dropdownFrame->GetRect(dropdownRect); + float t2p; + aPresContext.GetTwipsToPixels(&t2p); + nscoord absoluteDropDownHeight = NSTwipsToIntPixels(dropdownRect.height, t2p); + + // Check to see if the drop-down list will go offscreen + if (NS_SUCCEEDED(rv) && ((aAbsolutePixelRect.y + aAbsolutePixelRect.height + absoluteDropDownHeight) > screenHeightInPixels)) { + // move the dropdown list up + dropdownYOffset = - (aAbsoluteTwipsRect.height); + } + } +*/ + + nsRect dropdownRect; + dropdownFrame->GetRect(dropdownRect); + dropdownRect.x = 0; + dropdownRect.y = dropdownYOffset; + dropdownFrame->SetRect(dropdownRect); + + return rv; +} + + +// Calculate a frame's position in screen coordinates +nsresult +nsComboboxControlFrame::GetAbsoluteFramePosition(nsIPresContext& aPresContext, + nsIFrame *aFrame, + nsRect& aAbsoluteTwipsRect, + nsRect& aAbsolutePixelRect) +{ + //XXX: This code needs to take the view's offset into account when calculating + //the absolute coordinate of the frame. + nsresult rv = NS_OK; + + aFrame->GetRect(aAbsoluteTwipsRect); + + // Get conversions between twips and pixels + float t2p; + float p2t; + aPresContext.GetTwipsToPixels(&t2p); + aPresContext.GetPixelsToTwips(&p2t); + + // Add in frame's offset from it it's containing view + nsIView *containingView = nsnull; + nsPoint offset; + rv = aFrame->GetOffsetFromView(offset, &containingView); + if (NS_SUCCEEDED(rv) && (nsnull != containingView)) { + aAbsoluteTwipsRect.x += offset.x; + aAbsoluteTwipsRect.y += offset.y; + // Addin the containing view's offset form it's containing widget + nsIWidget* widget = nsnull; + nscoord widgetx = 0; + nscoord widgety = 0; + rv = containingView->GetOffsetFromWidget(&widgetx, &widgety, widget); + if (NS_SUCCEEDED(rv) && (nsnull != widget)) { + aAbsoluteTwipsRect.x += widgetx; + aAbsoluteTwipsRect.y += widgety; + + // Add in the absolute offset of the widget. + nsRect absBounds; + widget->GetAbsoluteBounds(absBounds); + + // Convert widget coordinates to twips + aAbsoluteTwipsRect.x += NSIntPixelsToTwips(absBounds.x, p2t); + aAbsoluteTwipsRect.y += NSIntPixelsToTwips(absBounds.y, p2t); + NS_RELEASE(widget); + } + } + + // convert to pixel coordinates + if (NS_SUCCEEDED(rv)) { + aAbsolutePixelRect.x = NSTwipsToIntPixels(aAbsoluteTwipsRect.x, t2p); + aAbsolutePixelRect.y = NSTwipsToIntPixels(aAbsoluteTwipsRect.y, t2p); + aAbsolutePixelRect.width = NSTwipsToIntPixels(aAbsoluteTwipsRect.width, t2p); + aAbsolutePixelRect.height = NSTwipsToIntPixels(aAbsoluteTwipsRect.height, t2p); + } + + return rv; +} + + +NS_IMETHODIMP +nsComboboxControlFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - // XXX Combo box should be changed to be implemented as a label and button frame. - // This would eliminate all of this Reflow code. KMM + nsresult rv = NS_OK; + nsIFrame* buttonFrame = GetButtonFrame(aPresContext); + nsIFrame* displayFrame = GetDisplayFrame(aPresContext); + nsIFrame* dropdownFrame = GetDropdownFrame(); - // add ourself as an nsIFormControlFrame + // Don't try to do any special sizing and positioning unless all of the frames + // have been created. + if ((nsnull == displayFrame) || + (nsnull == buttonFrame) || + (nsnull == dropdownFrame)) + { + // Since combobox frames are missing just do a normal area frame reflow + return nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + } + + // size of each part of the combo box + nsRect displayRect; + nsRect buttonRect; + nsRect dropdownRect; + + if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { nsFormFrame::AddFormControlFrame(aPresContext, *this); } + // Get the current sizes of the combo box child frames + displayFrame->GetRect(displayRect); + buttonFrame->GetRect(buttonRect); + dropdownFrame->GetRect(dropdownRect); - if (mFirstTime) { - ReResolveStyleContext(&aPresContext, mStyleContext, NS_STYLE_HINT_REFLOW, nsnull, nsnull); // XXX This temporary - mListFrame->ReResolveStyleContext(&aPresContext, mCurrentStyleContext, NS_STYLE_HINT_REFLOW, nsnull, nsnull); - mFirstTime = PR_FALSE; - InitTextStr(); - } + nsHTMLReflowState firstPassState(aReflowState); - PRInt32 numChildren = mFrames.GetLength(); - - if (1 == numChildren) { - aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::comboText, - mStyleContext, PR_FALSE, - &mBlockTextStyle); - - // XXX This code should move to Init(), someday when the frame construction - // changes are all done and Init() is always getting called... - /*PRBool disabled = */nsFormFrame::GetDisabled(this); - } - - nsIDOMHTMLSelectElement* select = nsListControlFrame::GetSelect(mContent); - if (!select) { - return NS_OK; - } - nsIDOMHTMLCollection* options = nsListControlFrame::GetOptions(mContent, select); - if (!options) { - NS_RELEASE(select); - return NS_OK; - } - - // get the css size - nsSize styleSize; - nsFormControlFrame::GetStyleSize(aPresContext, aReflowState, styleSize); - - // get the size of the longest option - PRInt32 maxWidth = 1; - PRUint32 numOptions; - options->GetLength(&numOptions); - for (PRUint32 i = 0; i < numOptions; i++) { - nsIDOMHTMLOptionElement* option = nsListControlFrame::GetOption(*options, i); - if (option) { - nsAutoString text; - if (NS_CONTENT_ATTR_HAS_VALUE != option->GetText(text)) { - continue; + // Only reflow the display and button if they are the target of + // the incremental reflow, unless they change size. If they do + // then everything needs to be reflowed. + if (eReflowReason_Incremental == firstPassState.reason) { + nsIFrame* targetFrame; + firstPassState.reflowCommand->GetTarget(targetFrame); + if ((targetFrame == buttonFrame) || (targetFrame == displayFrame)) { + nsRect oldDisplayRect = displayRect; + nsRect oldButtonRect = buttonRect; + rv = nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + displayFrame->GetRect(displayRect); + buttonFrame->GetRect(buttonRect); + if ((oldDisplayRect == displayRect) && (oldButtonRect == buttonRect)) { + // Reposition the popup. + nsRect absoluteTwips; + nsRect absolutePixels; + GetAbsoluteFramePosition(aPresContext, displayFrame, absoluteTwips, absolutePixels); + PositionDropdown(aPresContext, displayRect.height, absoluteTwips, absolutePixels); + return rv; } - nsSize textSize; - // use the style for the select rather that the option, since widgets don't support it - nsFormControlHelper::GetTextSize(aPresContext, this, text, textSize, aReflowState.rendContext); - if (textSize.width > maxWidth) { - maxWidth = textSize.width; - } - NS_RELEASE(option); } + nsIReflowCommand::ReflowType type; + aReflowState.reflowCommand->GetType(type); + firstPassState.reason = eReflowReason_StyleChange; + firstPassState.reflowCommand = nsnull; } - PRInt32 rowHeight = 0; - nsSize desiredSize; - nsSize minSize; - PRBool widthExplicit, heightExplicit; - nsInputDimensionSpec textSpec(nsnull, PR_FALSE, nsnull, nsnull, - maxWidth, PR_TRUE, nsHTMLAtoms::size, 1); - // XXX fix CalculateSize to return PRUint32 - PRUint32 numRows = - (PRUint32)nsFormControlHelper::CalculateSize(&aPresContext, aReflowState.rendContext, this, - styleSize, textSpec, desiredSize, minSize, - widthExplicit, heightExplicit, rowHeight); - float sp2t; - float p2t; - aPresContext.GetPixelsToTwips(&p2t); - aPresContext.GetScaledPixelsToTwips(&sp2t); - nscoord onePixel = NSIntPixelsToTwips(1, sp2t); - nscoord extra = desiredSize.height - (rowHeight * numRows); - numRows = (numOptions > 20 ? 20 : numOptions); - desiredSize.height = (numRows * rowHeight) + extra; - aDesiredSize.descent = 0; - nsMargin border; - const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); - mySpacing->CalcBorderFor(this, border); + //Set the desired size for the button and display frame + if (NS_UNCONSTRAINEDSIZE == firstPassState.computedWidth) { + // 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. - float scale; - float sbWidth; - float sbHeight; - nsCOMPtr context; - aPresContext.GetDeviceContext(getter_AddRefs(context)); - context->GetCanonicalPixelScale(scale); - context->GetScrollBarDimensions(sbWidth, sbHeight); - PRInt32 scrollbarScaledWidth = PRInt32(sbWidth * scale); + // Reflow the dropdown shrink-wrapped. + nsHTMLReflowMetrics dropdownDesiredSize(aDesiredSize); + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + dropdownFrame->GetRect(dropdownRect); + // Get maximum size and height of a option in the dropdown - nsFont font(aPresContext.GetDefaultFixedFontDeprecated()); - SystemAttrStruct sis; - sis.mFont = &font; - context->GetSystemAttribute(eSystemAttr_Font_Tooltips, &sis); + nsSize size; + mListControlFrame->GetMaximumSize(size); - //XXX: This 14 pixel hardcode value here is bad. The style system should control - //everyting. KMM - nscoord horKludgeAdjustment = NSIntPixelsToTwips(14, p2t); - nscoord horAdjustment = scrollbarScaledWidth + border.left + border.right + horKludgeAdjustment; + // Set width of display to match width of the drop down + SetChildFrameSize(displayFrame, dropdownRect.width, size.height); - aDesiredSize.width = desiredSize.width + horAdjustment; + // Size the button to be the same height as the displayFrame + SetChildFrameSize(buttonFrame, size.height, size.height); - nscoord verKludgeAdjustment = onePixel; - nscoord verAdjustment = border.top + border.bottom + verKludgeAdjustment; + // Reflow display + button + nsAreaFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); + displayFrame->GetRect(displayRect); - aDesiredSize.height = rowHeight + verAdjustment; + // Reflow the dropdown list to match the width of the display + button + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, aDesiredSize.width, NS_UNCONSTRAINEDSIZE); + dropdownFrame->GetRect(dropdownRect); - mButtonRect.SetRect(aDesiredSize.width-scrollbarScaledWidth-border.right, border.top, - scrollbarScaledWidth, aDesiredSize.height - verAdjustment); - - if (nsnull != aDesiredSize.maxElementSize) { - aDesiredSize.maxElementSize->width = minSize.width + verAdjustment; - aDesiredSize.maxElementSize->height = minSize.height + horAdjustment; - } - - nsRect frameRect; - GetRect(frameRect); - nsRect curRect; - mPlaceHolderFrame->GetRect(curRect); - curRect.x = 0; - - curRect.y = frameRect.y + aDesiredSize.height; - mPlaceHolderFrame->SetRect(curRect); - mListFrame->GetRect(frameRect); - - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; - aStatus = NS_FRAME_COMPLETE; - - return NS_OK; -} - -//------------------------------------------------------------------------------ -void -nsComboboxControlFrame::PaintComboboxControl(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) -{ - //XXX Combo box should be changed to be implemented as a label and button frame. - //This would eliminate all of this rendering code. KMM - const nsStyleDisplay* disp = (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display); - if (!disp->mVisible) { - return; - } - aRenderingContext.PushState(); - - const nsStyleColor* myColor = (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color); - const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); - const nsStyleFont* myFont = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); - - nsIStyleContext * blkStyle; - if (mGotFocus) { - blkStyle = mTextStr.Length() > 0?mBlockTextSelectedFocusStyle:mBlockTextStyle; - } else { - blkStyle = mTextStr.Length() > 0?mBlockTextSelectedStyle:mBlockTextStyle; - } - const nsStyleColor* blkColor = (const nsStyleColor*)blkStyle->GetStyleData(eStyleStruct_Color); - const nsStyleSpacing* blkSpacing = (const nsStyleSpacing*)blkStyle->GetStyleData(eStyleStruct_Spacing); -// const nsStyleFont* blkFont = (const nsStyleFont*)blkStyle->GetStyleData(eStyleStruct_Font); - - nsRect rect(0, 0, mRect.width, mRect.height); - nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this, - aDirtyRect, rect, *myColor, *mySpacing, 0, 0); - - nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, - aDirtyRect, rect, *mySpacing, mStyleContext, 0); - - nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); - - const nsStyleSpacing* spacing =(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); - nsMargin border; - spacing->CalcBorderFor(this, border); - - float p2t; - aPresContext.GetScaledPixelsToTwips(&p2t); - nscoord onePixel = NSIntPixelsToTwips(1, p2t); - - nsRect outside(0, 0, mRect.width, mRect.height); - outside.Deflate(border); - - nsRect inside(outside); - outside.Deflate(onePixel, onePixel); - - aRenderingContext.SetColor(blkColor->mBackgroundColor); - aRenderingContext.FillRect(inside.x, inside.y, inside.width, inside.height); - - float appUnits; - float devUnits; - float scale; - nsIDeviceContext * context; - aRenderingContext.GetDeviceContext(context); - - context->GetCanonicalPixelScale(scale); - context->GetAppUnitsToDevUnits(devUnits); - context->GetDevUnitsToAppUnits(appUnits); - - float sbWidth; - float sbHeight; - context->GetScrollBarDimensions(sbWidth, sbHeight); - PRInt32 scrollbarScaledWidth = PRInt32(sbWidth * scale); - PRInt32 scrollbarScaledHeight = PRInt32(sbWidth * scale); - - nsFont font(aPresContext.GetDefaultFixedFontDeprecated()); - GetFont(&aPresContext, font); - - aRenderingContext.SetFont(myFont->mFont); - - inside.width -= scrollbarScaledWidth; - PRBool clipEmpty; - aRenderingContext.PushState(); - aRenderingContext.SetClipRect(inside, nsClipCombine_kReplace, clipEmpty); - - nscoord x = inside.x + (onePixel * 4); - nscoord y = inside.y; - - aRenderingContext.SetColor(blkColor->mColor); - - aRenderingContext.DrawString(mTextStr, x, y); - nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, - aDirtyRect, inside, *blkSpacing, blkStyle, 0); - - aRenderingContext.PopState(clipEmpty); - - inside.width -= scrollbarScaledWidth; - inside.height -= scrollbarScaledHeight; - - const nsStyleSpacing* arrowSpacing = (const nsStyleSpacing*)mArrowStyle->GetStyleData(eStyleStruct_Spacing); - - nsRect srect(0,0,0,0); - srect = mButtonRect; - nsFormControlHelper::PaintArrow(nsFormControlHelper::eArrowDirection_Down, aRenderingContext,aPresContext, - aDirtyRect, srect, onePixel, mArrowStyle, *arrowSpacing, this, mRect); + } else { + // A width has been specified for the select. + // Make the display frame's width + button frame width = the width specified. + nsHTMLReflowMetrics dropdownDesiredSize(aDesiredSize); + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + // Get unconstrained size of the dropdown list. + nsSize size; + mListControlFrame->GetMaximumSize(size); - NS_RELEASE(context); + // Size the button to be the same height as the displayFrame + SetChildFrameSize(buttonFrame, size.height, size.height); - PRBool status; - aRenderingContext.PopState(status); -} + // Compute display width + buttonFrame->GetRect(buttonRect); + nscoord displayWidth; + displayWidth = firstPassState.computedWidth - buttonRect.width; -NS_METHOD -nsComboboxControlFrame::Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) -{ - if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { - PaintComboboxControl(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + // Set the displayFrame to match the displayWidth computed above + SetChildFrameSize(displayFrame, displayWidth, size.height); + + // Reflow again with the width of the display frame set. + nsAreaFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); + + // Reflow the dropdown list to match the width of the display + button + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, aDesiredSize.width, NS_UNCONSTRAINEDSIZE); + } - return NS_OK; -} + + nsRect absoluteTwips; + nsRect absolutePixels; + GetAbsoluteFramePosition(aPresContext, displayFrame, absoluteTwips, absolutePixels); + PositionDropdown(aPresContext, aDesiredSize.height, absoluteTwips, absolutePixels); -//-------------------------------------------------------------- -PRIntn -nsComboboxControlFrame::GetSkipSides() const -{ - return 0; -} + return rv; +} //-------------------------------------------------------------- NS_IMETHODIMP @@ -607,14 +716,12 @@ nsComboboxControlFrame::GetName(nsString* aResult) return result; } -//-------------------------------------------------------------- PRInt32 nsComboboxControlFrame::GetMaxNumValues() { return 1; } -//-------------------------------------------------------------- PRBool nsComboboxControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, nsString* aValues, nsString* aNames) @@ -641,27 +748,6 @@ nsComboboxControlFrame::GetFrameName(nsString& aResult) const } -void -nsComboboxControlFrame::RefreshStyleContext(nsIPresContext* aPresContext, - nsIAtom * aNewContentPseudo, - nsIStyleContext*& aCurrentStyle, - nsIContent * aContent, - nsIStyleContext* aParentStyle) - -{ - nsIStyleContext* newStyleContext; - aPresContext->ProbePseudoStyleContextFor(aContent, - aNewContentPseudo, - aParentStyle, - PR_FALSE, - &newStyleContext); - if (newStyleContext != aCurrentStyle) { - NS_IF_RELEASE(aCurrentStyle); - aCurrentStyle = newStyleContext; - } else { - NS_IF_RELEASE(newStyleContext); - } -} NS_IMETHODIMP nsComboboxControlFrame::ReResolveStyleContext(nsIPresContext* aPresContext, @@ -670,162 +756,83 @@ nsComboboxControlFrame::ReResolveStyleContext(nsIPresContext* aPresContext, nsStyleChangeList* aChangeList, PRInt32* aLocalChange) { + PRInt32 ourChange = aParentChange; + nsresult rv = nsAreaFrame::ReResolveStyleContext(aPresContext, aParentContext, aParentChange, aChangeList, aLocalChange); + + if (NS_FAILED(rv)) { + return rv; + } - // NOTE: using nsFrame's ReResolveStyleContext method to avoid - // useless version in base classes. - PRInt32 ourChange = aParentChange; - nsresult rv = nsHTMLContainerFrame::ReResolveStyleContext(aPresContext, aParentContext, - ourChange, aChangeList, &ourChange); - if (NS_FAILED(rv)) { - return rv; - } - - if (aLocalChange) { + if (aLocalChange) { *aLocalChange = ourChange; - } + } - if (NS_COMFALSE != rv) { - PRInt32 childChange; - PRBool currentIsVisible = (mCurrentStyleContext == mVisibleStyleContext?PR_TRUE:PR_FALSE); - - RefreshStyleContext(aPresContext, nsHTMLAtoms::dropDownVisible, mVisibleStyleContext, mContent, mStyleContext); - - RefreshStyleContext(aPresContext, nsHTMLAtoms::dropDownHidden, mHiddenStyleContext, mContent, mStyleContext); - mCurrentStyleContext = (currentIsVisible?mVisibleStyleContext:mHiddenStyleContext); - - mListFrame->ReResolveStyleContext(aPresContext, - (nsnull != mCurrentStyleContext? mCurrentStyleContext : mStyleContext), - ourChange, aChangeList, &childChange); - - // Button Style - RefreshStyleContext(aPresContext, nsHTMLAtoms::dropDownBtnOut, mBtnOutStyleContext, mContent, mStyleContext); - RefreshStyleContext(aPresContext, nsHTMLAtoms::dropDownBtnPressed, mBtnPressedStyleContext, mContent, mStyleContext); - - //Need to reset the mArrowStyle here, otherwise it might end up pointing - //to memory that has been freed, by the RefreshStyleContext above. - mArrowStyle = mBtnOutStyleContext; - - RefreshStyleContext(aPresContext, nsHTMLAtoms::comboText, mBlockTextStyle, mContent, mStyleContext); - RefreshStyleContext(aPresContext, nsHTMLAtoms::comboTextSelected, mBlockTextSelectedStyle, mContent, mStyleContext); - RefreshStyleContext(aPresContext, nsHTMLAtoms::comboTextSelectedFocus, mBlockTextSelectedFocusStyle, mContent, mStyleContext); - } - - return rv; + if (NS_COMFALSE != rv) { + PRInt32 childChange; + // Update child list + nsIFrame* dropdownFrame = GetDropdownFrame(); + dropdownFrame->ReResolveStyleContext(aPresContext, mStyleContext, ourChange, aChangeList, &childChange); + } + return rv; } -//---------------------------------------------------------------------- -NS_IMETHODIMP nsComboboxControlFrame::HandleEvent(nsIPresContext& aPresContext, - nsGUIEvent* aEvent, - nsEventStatus& aEventStatus) + +nsresult +nsComboboxControlFrame::MouseDown(nsIDOMEvent* aMouseEvent) { - if (aEvent->message == NS_MOUSE_EXIT) { - // If dropdown is visible and we have exited the combo box then leave the - // list up and have the listbox capture all of the mouse events. - if (mCurrentStyleContext == mVisibleStyleContext) { - mListControlFrame->CaptureMouseEvents(PR_TRUE); - } - } - - if (nsEventStatus_eConsumeNoDefault == aEventStatus) { - return NS_OK; - } - - aEventStatus = nsEventStatus_eConsumeNoDefault; - - if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) { - mArrowStyle = mBtnOutStyleContext; - nsFormControlHelper::ForceDrawFrame(this); - } else if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) { - mArrowStyle = mBtnPressedStyleContext; - nsFormControlHelper::ForceDrawFrame(this); - MouseClicked(&aPresContext); - } + ToggleList(mPresContext); return NS_OK; } -//---------------------------------------------------------------------- -NS_IMETHODIMP -nsComboboxControlFrame::GetFrameForPoint(const nsPoint& aPoint, nsIFrame** aFrame) -{ - *aFrame = this; - return NS_OK; -} - - //---------------------------------------------------------------------- // nsIComboboxControlFrame //---------------------------------------------------------------------- NS_IMETHODIMP -nsComboboxControlFrame::SetDropDown(nsIFrame* aPlaceHolderFrame, nsIFrame* aDropDownFrame) +nsComboboxControlFrame::SetDropDown(nsIFrame* aDropDownFrame) { - mPlaceHolderFrame = aPlaceHolderFrame; - mListFrame = aDropDownFrame; - - if (NS_OK != mListFrame->QueryInterface(kIListControlFrameIID, (void**)&mListControlFrame)) { + mDropdownFrame = aDropDownFrame; + + if (NS_OK != mDropdownFrame->QueryInterface(kIListControlFrameIID, (void**)&mListControlFrame)) { return NS_ERROR_FAILURE; } - - // Ok, since we now know we have the ListFrame, and we are assuming at this point it has been initialized - // Let's get the currently selected item, but we make the call using the Interface - mListControlFrame->GetSelectedItem(mTextStr); return NS_OK; } -//-------------------------------------------------------------- -NS_IMETHODIMP -nsComboboxControlFrame::SetDropDownStyleContexts(nsIStyleContext * aVisible, nsIStyleContext * aHidden) -{ - mVisibleStyleContext = aVisible; - mHiddenStyleContext = aHidden; - mCurrentStyleContext = mHiddenStyleContext; - - NS_ADDREF(mVisibleStyleContext); - NS_ADDREF(mHiddenStyleContext); - return NS_OK; -} - -//-------------------------------------------------------------- -NS_IMETHODIMP -nsComboboxControlFrame::SetButtonStyleContexts(nsIStyleContext * aOut, nsIStyleContext * aPressed) -{ - mBtnOutStyleContext = aOut; - mBtnPressedStyleContext = aPressed; - mArrowStyle = aOut; - - NS_ADDREF(mBtnOutStyleContext); - NS_ADDREF(mBtnPressedStyleContext); - return NS_OK; -} - void nsComboboxControlFrame::SelectionChanged() { - // Generate a NS_ONCHANGE event. + if (nsnull != mDisplayContent) { + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, mTextStr, PR_TRUE); + } - //XXX: Todo complete the implementation of selection changed -// nsIViewManager *vm; -// view->GetViewManager(vm); -// nsGUIEvent event; -// event.eventStructType = NS_GUI_EVENT; -// event.widget = this; //XXX: How do I get a widget -// NS_ADDREF(event.widget); -// NS_CONTROL_CHANGE -// InitEvent(event, aMsg); -// vm->DispatchEvent(&event, result); -// NS_RELEASE(event.widget); -// NS_RELEASE(vm); + // Dispatch the NS_FORM_CHANGE event + nsEventStatus status = nsEventStatus_eIgnore; + nsGUIEvent event; + event.eventStructType = NS_GUI_EVENT; + event.widget = nsnull; + event.message = NS_FORM_CHANGE; + // Have the content handle the event. + mContent->HandleDOMEvent(*mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, status); + // Now have the frame handle the event + nsIFrame* frame = nsnull; + nsIFrame* dropdownFrame = GetDropdownFrame(); + nsresult result = dropdownFrame->QueryInterface(kIFrameIID, (void**)&frame); + if ((NS_SUCCEEDED(result)) && (nsnull != frame)) { + frame->HandleEvent(*mPresContext, &event, status); + } + } -//-------------------------------------------------------------- + NS_IMETHODIMP nsComboboxControlFrame::ListWasSelected(nsIPresContext* aPresContext) { - mArrowStyle = mBtnOutStyleContext; - MouseClicked(aPresContext); + ShowList(aPresContext, PR_FALSE); + mListControlFrame->CaptureMouseEvents(PR_FALSE); nsString str; if (nsnull != mListControlFrame) { @@ -833,46 +840,184 @@ nsComboboxControlFrame::ListWasSelected(nsIPresContext* aPresContext) // Check to see if the selection changed if (PR_FALSE == str.Equals(mTextStr)) { mTextStr = str; + //XXX:TODO look at the ordinal position of the selected content in the listbox to tell + // if the selection has changed, rather than looking at the text string. + // There may be more than one item in the dropdown list with the same label. SelectionChanged(); } - nsIFormControlFrame* fcFrame = nsnull; - nsresult result = mListFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); - if ((NS_OK == result) && (nsnull != fcFrame)) { - fcFrame->SetFocus(PR_FALSE, PR_FALSE); - } - SetFocus(PR_TRUE, PR_TRUE); } - - mListControlFrame->CaptureMouseEvents(PR_FALSE); return NS_OK; } -nsresult nsComboboxControlFrame::RequiresWidget(PRBool& aRequiresWidget) +nsresult +nsComboboxControlFrame::RequiresWidget(PRBool& aRequiresWidget) { aRequiresWidget = PR_FALSE; return NS_OK; } -NS_IMETHODIMP nsComboboxControlFrame::SetProperty(nsIAtom* aName, const nsString& aValue) +NS_IMETHODIMP +nsComboboxControlFrame::SetProperty(nsIAtom* aName, const nsString& aValue) { nsIFormControlFrame* fcFrame = nsnull; - nsresult result = mListFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + nsIFrame* dropdownFrame = GetDropdownFrame(); + nsresult result = dropdownFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); if ((NS_SUCCEEDED(result)) && (nsnull != fcFrame)) { return fcFrame->SetProperty(aName, aValue); } return result; } -NS_IMETHODIMP nsComboboxControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) +NS_IMETHODIMP +nsComboboxControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) { nsIFormControlFrame* fcFrame = nsnull; - nsresult result = mListFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + nsIFrame* dropdownFrame = GetDropdownFrame(); + nsresult result = dropdownFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); if ((NS_SUCCEEDED(result)) && (nsnull != fcFrame)) { return fcFrame->GetProperty(aName, aValue); } return result; } + +NS_IMETHODIMP +nsComboboxControlFrame::CreateAnonymousContent(nsISupportsArray& aChildList) +{ + // The frames used to display the combo box and the button used to popup the dropdown list + // are created through anonymous content. The dropdown list is not created through anonymous + // content because it's frame is initialized specifically for the drop-down case and it is placed + // a special list referenced through NS_COMBO_FRAME_POPUP_LIST_INDEX to keep separate from the + // layout of the display and button. + // + // Note: The value attribute of the display content is set when an item is selected in the dropdown list. + // If the content specified below does not honor the value attribute than nothing will be displayed. + // In addition, if the frame created by content below for does not implement the nsIFormControlFrame + // interface and honor the SetSuggestedSize method the placement and size of the display area will not + // match what is normally desired for a combobox. + + + // For now the content that is created corresponds to two input buttons. It would be better to create the + // tag as something other than input, but then there isn't any way to create a button frame since it + // isn't possible to set the display type in CSS2 to create a button frame. + + // create content used for display + nsIAtom* tag = NS_NewAtom("input"); + NS_NewHTMLInputElement(&mDisplayContent, tag); + NS_ADDREF(mDisplayContent); + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, nsAutoString("button"), PR_FALSE); + //XXX: Do not use nsHTMLAtoms::id use nsHTMLAtoms::kClass instead. There will end up being multiple + //ids set to the same value which is illegal. + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, nsAutoString("-moz-display"), PR_FALSE); + aChildList.AppendElement(mDisplayContent); + + // create button which drops the list down + tag = NS_NewAtom("input"); + NS_NewHTMLInputElement(&mButtonContent, tag); + NS_ADDREF(mButtonContent); + mButtonContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, nsAutoString("button"), PR_FALSE); + aChildList.AppendElement(mButtonContent); + + // get the reciever interface from the browser button's content node + nsCOMPtr reciever(do_QueryInterface(mButtonContent)); + + // we shouldn't have to unregister this listener because when + // our frame goes away all these content node go away as well + // because our frame is the only one who references them. + reciever->AddEventListenerByIID(this, kIDOMMouseListenerIID); + + // get the reciever interface from the browser button's content node + nsCOMPtr displayReciever(do_QueryInterface(mDisplayContent)); + + // we shouldn't have to unregister this listener because when + // our frame goes away all these content node go away as well + // because our frame is the only one who references them. + displayReciever->AddEventListenerByIID(this, kIDOMMouseListenerIID); + + return NS_OK; +} + +NS_IMETHODIMP +nsComboboxControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight) +{ + return NS_OK; +} + + + +NS_IMETHODIMP +nsComboboxControlFrame::DeleteFrame(nsIPresContext& aPresContext) +{ + // Cleanup frames in popup child list + mPopupFrames.DeleteFrames(aPresContext); + return nsAreaFrame::DeleteFrame(aPresContext); +} + + +NS_IMETHODIMP +nsComboboxControlFrame::FirstChild(nsIAtom* aListName, + nsIFrame** aFirstChild) const +{ + if (nsLayoutAtoms::popupList == aListName) { + *aFirstChild = mPopupFrames.FirstChild(); + } else { + nsAreaFrame::FirstChild(aListName, aFirstChild); + } + return NS_OK; +} + +NS_IMETHODIMP +nsComboboxControlFrame::SetInitialChildList(nsIPresContext& aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList) +{ + nsresult rv = NS_OK; + if (nsLayoutAtoms::popupList == aListName) { + mPopupFrames.SetFrames(aChildList); + } else { + rv = nsAreaFrame::SetInitialChildList(aPresContext, aListName, aChildList); + InitTextStr(PR_FALSE); + } + return rv; +} + +NS_IMETHODIMP +nsComboboxControlFrame::GetAdditionalChildListName(PRInt32 aIndex, + nsIAtom** aListName) const +{ + // Maintain a seperate child list for the dropdown list (i.e. popup listbox) + // This is necessary because we don't want the listbox to be included in the layout + // of the combox's children because it would take up space, when it is suppose to + // be floating above the display. + NS_PRECONDITION(nsnull != aListName, "null OUT parameter pointer"); + if (aIndex <= NS_AREA_FRAME_ABSOLUTE_LIST_INDEX) { + return nsAreaFrame::GetAdditionalChildListName(aIndex, aListName); + } + + *aListName = nsnull; + if (NS_COMBO_FRAME_POPUP_LIST_INDEX == aIndex) { + *aListName = nsLayoutAtoms::popupList; + NS_ADDREF(*aListName); + } + return NS_OK; +} + +PRIntn +nsComboboxControlFrame::GetSkipSides() const +{ + // Don't skip any sides during border rendering + return 0; +} + + + + + + + + + + diff --git a/mozilla/layout/forms/nsComboboxControlFrame.h b/mozilla/layout/forms/nsComboboxControlFrame.h index 18249aad5b9..5a411f98d7b 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.h +++ b/mozilla/layout/forms/nsComboboxControlFrame.h @@ -20,10 +20,12 @@ #define nsComboboxControlFrame_h___ -#include "nsHTMLContainerFrame.h" +#include "nsAreaFrame.h" #include "nsIFormControlFrame.h" #include "nsIComboboxControlFrame.h" - +#include "nsIDOMMouseListener.h" +#include "nsVoidArray.h" +#include "nsIAnonymousContentCreator.h" class nsButtonControlFrame; class nsTextControlFrame; @@ -33,19 +35,36 @@ class nsStyleContext; class nsIHTMLContent; class nsIListControlFrame; -class nsComboboxControlFrame : public nsHTMLContainerFrame, +/** + * Child list name indices + * @see #GetAdditionalChildListName() + */ +#define NS_COMBO_FRAME_POPUP_LIST_INDEX (NS_AREA_FRAME_ABSOLUTE_LIST_INDEX + 1) + +class nsComboboxControlFrame : public nsAreaFrame, public nsIFormControlFrame, - public nsIComboboxControlFrame + public nsIComboboxControlFrame, + public nsIDOMMouseListener, + public nsIAnonymousContentCreator { public: nsComboboxControlFrame(); ~nsComboboxControlFrame(); + // nsISupports NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + + // nsIAnonymousContentCreator + NS_IMETHOD CreateAnonymousContent(nsISupportsArray& aChildList); + + // nsIFrame + NS_IMETHOD Init(nsIPresContext& aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow); - // nsIFrame - NS_IMETHOD Reflow(nsIPresContext& aCX, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, @@ -57,45 +76,31 @@ public: nsStyleChangeList* aChangeList, PRInt32* aLocalChange); - NS_IMETHOD Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); - - NS_IMETHOD HandleEvent(nsIPresContext& aPresContext, - nsGUIEvent* aEvent, - nsEventStatus& aEventStatus); - NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD DeleteFrame(nsIPresContext& aPresContext); + NS_IMETHOD FirstChild(nsIAtom* aListName, nsIFrame** aFirstChild) const; + NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList); + NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex, + nsIAtom** aListName) const; - - virtual PRInt32 GetMaxNumValues(); - - virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames); - - // nsIFormControLFrame + // nsIFormControlFrame + NS_IMETHOD SetSuggestedSize(nscoord aWidth, nscoord aHeight); + NS_IMETHOD GetName(nsString* aName); + NS_IMETHOD GetType(PRInt32* aType) const; NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); void SetFocus(PRBool aOn, PRBool aRepaint); - virtual void PostCreateWidget(nsIPresContext* aPresContext, nscoord& aWidth, nscoord& aHeight); - - - //nsTextControlFrame* GetTextFrame() { return mTextFrame; } - - //void SetTextFrame(nsTextControlFrame* aFrame) { mTextFrame = aFrame; } - - //nsButtonControlFrame* GetBrowseFrame() { return mBrowseFrame; } - //void SetBrowseFrame(nsButtonControlFrame* aFrame) { mBrowseFrame = aFrame; } virtual PRBool IsSuccessful(nsIFormControlFrame* aSubmitter); virtual void SetFormFrame(nsFormFrame* aFormFrame) { mFormFrame = aFormFrame; } virtual void Reset(); - NS_IMETHOD GetName(nsString* aName); - NS_IMETHOD GetType(PRInt32* aType) const; - + virtual PRInt32 GetMaxNumValues(); + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); NS_IMETHOD GetFont(nsIPresContext* aPresContext, nsFont& aFont); NS_IMETHOD GetFormContent(nsIContent*& aContent) const; @@ -107,69 +112,73 @@ public: float aPixToTwip, nscoord aInnerWidth, nscoord aCharWidth) const; - - virtual nsresult RequiresWidget(PRBool &aRequiresWidget); - - - NS_IMETHOD GetFrameForPoint(const nsPoint& aPoint, nsIFrame** aFrame); - - // A Static Helper Functions - - // This refreshes a particular pseudo style content when a "ReResolveStyleContent" happens - static void RefreshStyleContext(nsIPresContext* aPresContext, - nsIAtom * aNewContentPseudo, - nsIStyleContext*& aCurrentStyle, - nsIContent * aContent, - nsIStyleContext* aParentStyle); - // nsIFormMouseListener virtual void MouseClicked(nsIPresContext* aPresContext); //nsIComboboxControlFrame - NS_IMETHOD SetDropDown(nsIFrame* aPlaceHolderFrame, nsIFrame* aDropDownFrame); - NS_IMETHOD SetDropDownStyleContexts(nsIStyleContext * aVisible, nsIStyleContext * aHidden); - NS_IMETHOD SetButtonStyleContexts(nsIStyleContext * aOut, nsIStyleContext * aPressed); + NS_IMETHOD SetDropDown(nsIFrame* aDropDownFrame); NS_IMETHOD ListWasSelected(nsIPresContext* aPresContext); + //nsIDOMEventListener + virtual nsresult MouseDown(nsIDOMEvent* aMouseEvent); + virtual nsresult MouseUp(nsIDOMEvent* aMouseEvent) { return NS_OK; } + virtual nsresult MouseClick(nsIDOMEvent* aMouseEvent) { printf("mouse clock\n"); return NS_OK; }; + virtual nsresult MouseDblClick(nsIDOMEvent* aMouseEvent) { return NS_OK; } + virtual nsresult MouseOver(nsIDOMEvent* aMouseEvent) { return NS_OK; } + virtual nsresult MouseOut(nsIDOMEvent* aMouseEvent) { return NS_OK; } + virtual nsresult HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; } -protected: - virtual void PaintComboboxControl(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); +protected: + + // nsHTMLContainerFrame virtual PRIntn GetSkipSides() const; - void InitTextStr(); + + // Utilities + nsresult ReflowComboChildFrame(nsIFrame* aFrame, + nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus, + nscoord aAvailableWidth, + nscoord aAvailableHeight); + + nsresult GetScreenHeight(nsIPresContext& aPresContext, nscoord& aHeight); + nsresult PositionDropdown(nsIPresContext& aPresContext, + nscoord aHeight, + nsRect aAbsoluteTwipsRect, + nsRect aAbsolutePixelRect); + nsresult GetAbsoluteFramePosition(nsIPresContext& aPresContext, + nsIFrame *aFrame, + nsRect& aAbsoluteTwipsRect, + nsRect& aAbsolutePixelRect); + void ToggleList(nsIPresContext* aPresContext); + void ShowPopup(PRBool aShowPopup); + void ShowList(nsIPresContext* aPresContext, PRBool aShowList); + void SetChildFrameSize(nsIFrame* aFrame, nscoord aWidth, nscoord aHeight); + void InitTextStr(PRBool aUpdate); + nsresult GetPrimaryComboFrame(nsIPresContext& aPresContext, nsIContent* aContent, nsIFrame** aFrame); + nsIFrame* GetButtonFrame(nsIPresContext& aPresContext); + nsIFrame* GetDisplayFrame(nsIPresContext& aPresContext); + nsIFrame* GetDropdownFrame(); + + // Called when the selection has changed. If the the same item in the list is selected + // it is NOT called. void SelectionChanged(); + nsFrameList mPopupFrames; // additional named child list + nsIPresContext* mPresContext; // XXX: Remove the need to cache the pres context. nsFormFrame* mFormFrame; // Parent Form Frame - nsIFrame * mPlaceHolderFrame; - nsIFrame * mListFrame; // Generic nsIFrame - nsIListControlFrame * mListControlFrame; // Specific ListControl Interface - nsRect mButtonRect; // The Arrow Button's Rect cached for Painting - - // DropDown List Visibility Styles - nsIStyleContext * mVisibleStyleContext; // Style for the DropDown List to make it visible - nsIStyleContext * mHiddenStyleContext; // Style for the DropDown List to make it hidden - nsIStyleContext * mCurrentStyleContext; // The current Style state of the DropDown List - - // Arrow Button Styles - nsIStyleContext * mBtnOutStyleContext; // Style when not pressed - nsIStyleContext * mBtnPressedStyleContext; // Style When Pressed - nsIStyleContext * mArrowStyle; // Arrows currrent style (for painting) - - // Combobox Text Styles - nsIStyleContext * mBlockTextStyle; // Style when there is no selection and it doesn't have focus - nsIStyleContext * mBlockTextSelectedStyle; // Style when selected and it doesn't have focus - nsIStyleContext * mBlockTextSelectedFocusStyle; // Style when selected and it has focus - - PRBool mFirstTime; - - // State data members - nsString mTextStr; - PRBool mGotFocus; + nsString mTextStr; // Current Combo box selection + nsIHTMLContent* mDisplayContent; // Anonymous content used to display the current selection + nsIHTMLContent* mButtonContent; // Anonymous content used to popup the dropdown list + PRBool mDroppedDown; // Current state of the dropdown list, PR_TRUE is dropped down + nsIFrame* mDisplayFrame; // frame to display selection + nsIFrame* mButtonFrame; // button frame + nsIFrame* mDropdownFrame; // dropdown list frame + nsIListControlFrame * mListControlFrame; // ListControl Interface for the dropdown frame private: NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } diff --git a/mozilla/layout/forms/nsFileControlFrame.cpp b/mozilla/layout/forms/nsFileControlFrame.cpp index b851e9005de..d21f30f0642 100644 --- a/mozilla/layout/forms/nsFileControlFrame.cpp +++ b/mozilla/layout/forms/nsFileControlFrame.cpp @@ -70,6 +70,8 @@ NS_NewFileControlFrame(nsIFrame** aNewFrame) nsFileControlFrame::nsFileControlFrame():mTextFrame(nsnull), mFormFrame(nsnull) { + //Shrink the area around it's contents + SetFlags(NS_BLOCK_SHRINK_WRAP); } NS_IMETHODIMP diff --git a/mozilla/layout/forms/nsFileControlFrame.h b/mozilla/layout/forms/nsFileControlFrame.h index ad04d5611a8..eef454d3327 100644 --- a/mozilla/layout/forms/nsFileControlFrame.h +++ b/mozilla/layout/forms/nsFileControlFrame.h @@ -50,7 +50,6 @@ public: // nsIFormControlFrame NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); - NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); NS_IMETHOD Reflow(nsIPresContext& aCX, @@ -59,6 +58,7 @@ public: nsReflowStatus& aStatus); NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SetSuggestedSize(nscoord aWidth, nscoord aHeight) { return NS_OK; }; virtual PRInt32 GetMaxNumValues(); diff --git a/mozilla/layout/forms/nsFormControlFrame.cpp b/mozilla/layout/forms/nsFormControlFrame.cpp index 4e66e5f974a..7c6b6ac783b 100644 --- a/mozilla/layout/forms/nsFormControlFrame.cpp +++ b/mozilla/layout/forms/nsFormControlFrame.cpp @@ -67,6 +67,8 @@ nsFormControlFrame::nsFormControlFrame() mDidInit = PR_FALSE; mWidget = nsnull; mFormFrame = nsnull; + mSuggestedWidth = NS_FORMSIZE_NOTSET; + mSuggestedHeight = NS_FORMSIZE_NOTSET; } nsFormControlFrame::~nsFormControlFrame() @@ -735,3 +737,10 @@ nsresult nsFormControlFrame::RequiresWidget(PRBool & aRequiresWidget) } +NS_IMETHODIMP nsFormControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight) +{ + mSuggestedWidth = aWidth; + mSuggestedHeight = aHeight; + return NS_OK; +} + diff --git a/mozilla/layout/forms/nsFormControlFrame.h b/mozilla/layout/forms/nsFormControlFrame.h index dd21114c59e..b68bc0979b5 100644 --- a/mozilla/layout/forms/nsFormControlFrame.h +++ b/mozilla/layout/forms/nsFormControlFrame.h @@ -36,6 +36,8 @@ class nsFormFrame; #define CSS_NOTSET -1 #define ATTR_NOTSET -1 +#define NS_FORMSIZE_NOTSET -1 + /** * nsFormControlFrame is the base class for frames of form controls. It * provides a uniform way of creating widgets, resizing, and painting. @@ -227,6 +229,8 @@ protected: nsHTMLReflowMetrics& aDesiredLayoutSize, nsSize& aDesiredWidgetSize); + NS_IMETHOD nsFormControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight); + // //------------------------------------------------------------------------------------- // Utility methods for managing checkboxes and radiobuttons @@ -274,6 +278,8 @@ protected: PRBool mDidInit; nsPoint mLastClickPoint; nsFormFrame* mFormFrame; + nscoord mSuggestedWidth; + nscoord mSuggestedHeight; private: NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } diff --git a/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp b/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp index 4af6f406631..ba199cbceb2 100644 --- a/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp +++ b/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp @@ -592,6 +592,13 @@ nsHTMLButtonControlFrame::ReResolveStyleContext ( nsIPresContext* aPresContext, } // ReResolveStyleContext +NS_IMETHODIMP nsHTMLButtonControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight) +{ +// mSuggestedWidth = aWidth; +// mSuggestedHeight = aHeight; + return NS_OK; +} + diff --git a/mozilla/layout/forms/nsHTMLButtonControlFrame.h b/mozilla/layout/forms/nsHTMLButtonControlFrame.h index a51107f7f8c..e8c5a3c3884 100644 --- a/mozilla/layout/forms/nsHTMLButtonControlFrame.h +++ b/mozilla/layout/forms/nsHTMLButtonControlFrame.h @@ -131,6 +131,7 @@ public: // nsIFormControlFrame NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); + NS_IMETHOD SetSuggestedSize(nscoord aWidth, nscoord aHeight); protected: NS_IMETHOD_(nsrefcnt) AddRef(void); diff --git a/mozilla/layout/forms/nsIComboboxControlFrame.h b/mozilla/layout/forms/nsIComboboxControlFrame.h index c021d02b13b..8c2cfb2b5e6 100644 --- a/mozilla/layout/forms/nsIComboboxControlFrame.h +++ b/mozilla/layout/forms/nsIComboboxControlFrame.h @@ -21,10 +21,12 @@ #include "nsISupports.h" #include "nsFont.h" + class nsFormFrame; class nsIPresContext; class nsString; class nsIContent; +class nsVoidArray; // IID for the nsIComboboxControlFrame class @@ -45,19 +47,7 @@ public: * Sets the Drop Down List * */ - NS_IMETHOD SetDropDown(nsIFrame* aPlaceHolderFrame, nsIFrame* aDropDownFrame) = 0; - - /** - * Sets the Pseudo Style Contexts for the DropDown - * - */ - NS_IMETHOD SetDropDownStyleContexts(nsIStyleContext * aVisible, nsIStyleContext * aHidden) = 0; - - /** - * Sets the Pseudo Style Contexts for the Button - * - */ - NS_IMETHOD SetButtonStyleContexts(nsIStyleContext * aOut, nsIStyleContext * aPressed) = 0; + NS_IMETHOD SetDropDown(nsIFrame* aDropDownFrame) = 0; /** * Notifies the Combobox the List was selected @@ -65,6 +55,7 @@ public: */ NS_IMETHOD ListWasSelected(nsIPresContext* aPresContext) = 0; + }; #endif diff --git a/mozilla/layout/forms/nsIFormControlFrame.h b/mozilla/layout/forms/nsIFormControlFrame.h index 82f30663c81..1f5de7a509e 100644 --- a/mozilla/layout/forms/nsIFormControlFrame.h +++ b/mozilla/layout/forms/nsIFormControlFrame.h @@ -67,6 +67,25 @@ public: nscoord aInnerWidth, nscoord aCharWidth) const = 0; + + /** + * Set the suggested size for the form element. + * This is used to control the size of the element during reflow if it hasn't had it's size + * explicitly set. + * @param aWidth width of the form element + * @param aHeight height of the form element + * @returns NS_OK + */ + + NS_IMETHOD SetSuggestedSize(nscoord aWidth, nscoord aHeight) = 0; + + /** + * Determine if the control uses a native widget for rendering + * @param aRequiresWidget is set to PR_TRUE if it has a native widget, PR_FALSE otherwise. + * @returns NS_OK + */ + + /** * Determine if the control uses a native widget for rendering * @param aRequiresWidget is set to PR_TRUE if it has a native widget, PR_FALSE otherwise. diff --git a/mozilla/layout/forms/nsIListControlFrame.h b/mozilla/layout/forms/nsIListControlFrame.h index 908a34bd68d..f17224a6a5a 100644 --- a/mozilla/layout/forms/nsIListControlFrame.h +++ b/mozilla/layout/forms/nsIListControlFrame.h @@ -63,6 +63,12 @@ public: */ NS_IMETHOD CaptureMouseEvents(PRBool aGrabMouseEvents) = 0; + /** + * Returns the maximum width and height of an item in the listbox + */ + + NS_IMETHOD GetMaximumSize(nsSize &aSize) = 0; + }; diff --git a/mozilla/layout/forms/nsImageControlFrame.cpp b/mozilla/layout/forms/nsImageControlFrame.cpp index b659bf1837c..5847fee0c5c 100644 --- a/mozilla/layout/forms/nsImageControlFrame.cpp +++ b/mozilla/layout/forms/nsImageControlFrame.cpp @@ -117,6 +117,7 @@ public: // nsIFormControlFrame NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); + NS_IMETHOD SetSuggestedSize(nscoord aWidth, nscoord aHeight); protected: void GetTranslatedRect(nsRect& aRect); // XXX this implementation is a copy of nsHTMLButtonControlFrame @@ -452,3 +453,10 @@ NS_IMETHODIMP nsImageControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) { return NS_OK; } + +NS_IMETHODIMP nsImageControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight) +{ +// mSuggestedWidth = aWidth; +// mSuggestedHeight = aHeight; + return NS_OK; +} \ No newline at end of file diff --git a/mozilla/layout/forms/nsListControlFrame.cpp b/mozilla/layout/forms/nsListControlFrame.cpp index 8f121a517df..8fc1c86149e 100644 --- a/mozilla/layout/forms/nsListControlFrame.cpp +++ b/mozilla/layout/forms/nsListControlFrame.cpp @@ -37,7 +37,7 @@ #include "nsIReflowCommand.h" // Constants -const nscoord kMaxDropDownRows = 20; // This matches the setting for 4.x browsers +const nscoord kMaxDropDownRows = 20; // This matches the setting for 4.x browsers const PRInt32 kNothingSelected = -1; const PRInt32 kMaxZ= 0x7fffffff; //XXX: Shouldn't there be a define somewhere for MaxInt for PRInt32 @@ -54,7 +54,6 @@ static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID); static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); -//---------------------------------------------------------------------- nsresult NS_NewListControlFrame(nsIFrame** aNewFrame) @@ -71,7 +70,7 @@ NS_NewListControlFrame(nsIFrame** aNewFrame) return NS_OK; } -//---------------------------------------------------------------------- + nsListControlFrame::nsListControlFrame() { mHitFrame = nsnull; @@ -83,20 +82,20 @@ nsListControlFrame::nsListControlFrame() mDisplayed = PR_FALSE; mButtonDown = PR_FALSE; mLastFrame = nsnull; + mMaxWidth = 0; + mMaxHeight = 0; + mIsCapturingMouseEvents = PR_FALSE; } -//---------------------------------------------------------------------- nsListControlFrame::~nsListControlFrame() { mComboboxFrame = nsnull; mFormFrame = nsnull; } -//---------------------------------------------------------------------- NS_IMPL_ADDREF(nsListControlFrame) NS_IMPL_RELEASE(nsListControlFrame) -//---------------------------------------------------------------------- NS_IMETHODIMP nsListControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) { @@ -108,7 +107,6 @@ nsListControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) return NS_OK; } if (aIID.Equals(kIListControlFrameIID)) { - NS_ADDREF_THIS(); // Increase reference count for caller *aInstancePtr = (void *)((nsIListControlFrame*)this); return NS_OK; } @@ -116,7 +114,7 @@ nsListControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) return nsScrollFrame::QueryInterface(aIID, aInstancePtr); } -//---------------------------------------------------------------------- + NS_IMETHODIMP nsListControlFrame::GetFrameForPoint(const nsPoint& aPoint, nsIFrame** aFrame) { @@ -147,7 +145,7 @@ nsListControlFrame::GetFrameForPoint(const nsPoint& aPoint, nsIFrame** aFrame) } -//---------------------------------------------------------------------- + nsresult nsListControlFrame::GetFrameForPointUsing(const nsPoint& aPoint, nsIAtom* aList, @@ -194,7 +192,7 @@ nsListControlFrame::GetFrameForPointUsing(const nsPoint& aPoint, scrollableView->GetScrollPosition(offsetx, offsety); tmp.x += offsetx; tmp.y += offsety; - // Note: scrollableView is not ref counted so it's interface is not NS_RELEASE'd + // Note: scrollableView is not ref counted } } @@ -238,14 +236,13 @@ nsListControlFrame::GetFrameForPointUsing(const nsPoint& aPoint, } *aFrame = this; return NS_ERROR_FAILURE; - + } -//---------------------------------------------------------------------- // Reflow is overriden to constrain the listbox height to the number of rows and columns // specified. -// + NS_IMETHODIMP nsListControlFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -284,10 +281,9 @@ nsListControlFrame::Reflow(nsIPresContext& aPresContext, nsSize scrolledAreaSize(0,0); nsHTMLReflowMetrics scrolledAreaDesiredSize(&scrolledAreaSize); + if (eReflowReason_Incremental == firstPassState.reason) { - //XXX: Why do we have to change the reflow type in this - //case? If we don't an assert in the nsScrollFrame::Reflow prevents - //execution from continuing. Is the assertion in nsScrollFrame bogus? + // When incremental, Reflow everything nsIFrame* targetFrame; firstPassState.reflowCommand->GetTarget(targetFrame); if (this == targetFrame) { @@ -308,6 +304,8 @@ nsListControlFrame::Reflow(nsIPresContext& aPresContext, nscoord scrolledAreaWidth = scrolledAreaDesiredSize.maxElementSize->width; nscoord scrolledAreaHeight = scrolledAreaDesiredSize.height; + mMaxWidth = scrolledAreaWidth; + mMaxHeight = scrolledAreaDesiredSize.maxElementSize->height; // The first reflow produces a box with the scrollbar width and borders // added in so we need to subtract them out. @@ -342,20 +340,12 @@ nsListControlFrame::Reflow(nsIPresContext& aPresContext, nscoord visibleWidth = 0; if (IsInDropDownMode() == PR_TRUE) { - // Always set the width to be - // XXX: TODO The width of the list should be passed in so it can - // be set to the same as the text box + dropdown arrow. - visibleWidth = scrolledAreaWidth; - if (nsnull != mComboboxFrame) { - nsRect comboRect; - nsIFrame *comboFrame = nsnull; - if (NS_SUCCEEDED(mComboboxFrame->QueryInterface(kIFrameIID, (void **)&comboFrame))) { - comboFrame->GetRect(comboRect); - visibleWidth = comboRect.width; - visibleWidth -= (border.left + border.right); - } - } - + // Calculate visible width for dropdown + if (NS_UNCONSTRAINEDSIZE == aReflowState.computedWidth) { + visibleWidth = scrolledAreaWidth; + } else { + visibleWidth = aReflowState.computedWidth - (border.left + border.right); + } } else { if (NS_UNCONSTRAINEDSIZE == aReflowState.computedWidth) { visibleWidth = scrolledAreaWidth; @@ -364,11 +354,11 @@ nsListControlFrame::Reflow(nsIPresContext& aPresContext, } } - // Determine if a scrollbar will be needed, If so we need to add - // enough the width to allow for the scrollbar. - // The scrollbar will be needed under two conditions: - // (size * heightOfaRow) < scrolledAreaHeight or - // the height set through Style < scrolledAreaHeight. + // Determine if a scrollbar will be needed, If so we need to add + // enough the width to allow for the scrollbar. + // The scrollbar will be needed under two conditions: + // (size * heightOfaRow) < scrolledAreaHeight or + // the height set through Style < scrolledAreaHeight. // Calculate the height of a single row in the listbox or dropdown list // Note: It is calculated based on what layout returns for the maxElement @@ -428,7 +418,6 @@ nsListControlFrame::Reflow(nsIPresContext& aPresContext, return NS_OK; } -//-------------------------------------------------------------- NS_IMETHODIMP nsListControlFrame::GetFormContent(nsIContent*& aContent) const { @@ -440,7 +429,7 @@ nsListControlFrame::GetFormContent(nsIContent*& aContent) const return rv; } -//-------------------------------------------------------------- + NS_IMETHODIMP nsListControlFrame::GetFont(nsIPresContext* aPresContext, nsFont& aFont) @@ -450,7 +439,8 @@ nsListControlFrame::GetFont(nsIPresContext* aPresContext, } -PRBool nsListControlFrame::IsOptionElement(nsIContent* aContent) +PRBool +nsListControlFrame::IsOptionElement(nsIContent* aContent) { PRBool result = PR_FALSE; @@ -466,7 +456,8 @@ PRBool nsListControlFrame::IsOptionElement(nsIContent* aContent) } -PRBool nsListControlFrame::IsOptionElementFrame(nsIFrame *aFrame) +PRBool +nsListControlFrame::IsOptionElementFrame(nsIFrame *aFrame) { nsIContent *content = nsnull; aFrame->GetContent(&content); @@ -482,7 +473,8 @@ PRBool nsListControlFrame::IsOptionElementFrame(nsIFrame *aFrame) // Go up the frame tree looking for the first ancestor that has content // which is selectable -nsIFrame *nsListControlFrame::GetSelectableFrame(nsIFrame *aFrame) +nsIFrame * +nsListControlFrame::GetSelectableFrame(nsIFrame *aFrame) { nsIFrame* selectedFrame = aFrame; @@ -494,7 +486,8 @@ nsIFrame *nsListControlFrame::GetSelectableFrame(nsIFrame *aFrame) return(selectedFrame); } -void nsListControlFrame::ForceRedraw() +void +nsListControlFrame::ForceRedraw() { //XXX: Hack. This should not be needed. The problem is DisplaySelected //and DisplayDeselected set and unset an attribute on generic HTML content @@ -508,11 +501,12 @@ void nsListControlFrame::ForceRedraw() // XXX: Here we introduce a new -moz-option-selected attribute so a attribute // selecitor n the ua.css can change the style when the option is selected. -void nsListControlFrame::DisplaySelected(nsIContent* aContent) +void +nsListControlFrame::DisplaySelected(nsIContent* aContent) { //XXX: This is temporary. It simulates psuedo states by using a attribute selector on // -moz-option-selected in the ua.css style sheet. This will not be needed when - // The event state manager is functional. KMM + // The event state manager supports selected states. KMM nsCOMPtr selectedAtom ( dont_QueryInterface(NS_NewAtom(kMozSelected))); if (PR_TRUE == mDisplayed) { @@ -523,7 +517,8 @@ void nsListControlFrame::DisplaySelected(nsIContent* aContent) } } -void nsListControlFrame::DisplayDeselected(nsIContent* aContent) +void +nsListControlFrame::DisplayDeselected(nsIContent* aContent) { //XXX: This is temporary. It simulates psuedo states by using a attribute selector on // -moz-option-selected in the ua.css style sheet. This will not be needed when @@ -540,8 +535,9 @@ void nsListControlFrame::DisplayDeselected(nsIContent* aContent) } -//---------------------------------------------------------------------- -PRInt32 nsListControlFrame::GetSelectedIndex(nsIFrame *aHitFrame) + +PRInt32 +nsListControlFrame::GetSelectedIndex(nsIFrame *aHitFrame) { PRInt32 index = kNothingSelected; // Get the content of the frame that was selected @@ -575,19 +571,20 @@ PRInt32 nsListControlFrame::GetSelectedIndex(nsIFrame *aHitFrame) return index; } -//---------------------------------------------------------------------- -void nsListControlFrame::ClearSelection() + +void +nsListControlFrame::ClearSelection() { PRUint32 length = GetNumberOfOptions(); - for (PRInt32 i = 0; i < (PRInt32)length; i++) { - if (i != mSelectedIndex) { - SetFrameSelected(i, PR_FALSE); - } - } + for (PRInt32 i = 0; i < (PRInt32)length; i++) { + if (i != mSelectedIndex) { + SetFrameSelected(i, PR_FALSE); + } + } } -//---------------------------------------------------------------------- -void nsListControlFrame::ExtendedSelection(PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aDoInvert, PRBool aSetValue) +void +nsListControlFrame::ExtendedSelection(PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aDoInvert, PRBool aSetValue) { PRInt32 startInx; PRInt32 endInx; @@ -621,7 +618,8 @@ void nsListControlFrame::ExtendedSelection(PRInt32 aStartIndex, PRInt32 aEndInde } } -void nsListControlFrame::SingleSelection() +void +nsListControlFrame::SingleSelection() { if (nsnull != mHitFrame) { // Store previous selection @@ -644,7 +642,8 @@ void nsListControlFrame::SingleSelection() } } -void nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) +void +nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) { if (nsnull != mHitFrame) { mSelectedIndex = (PRInt32)GetSelectedIndex(mHitFrame); @@ -696,15 +695,13 @@ void nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) ClearSelection(); } } - - //XXX Fix this mHitContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, (selected?kSelectedFocus:kNormal), PR_TRUE); } - } -void nsListControlFrame::HandleListSelection(nsIPresContext& aPresContext, - nsGUIEvent* aEvent, - nsEventStatus& aEventStatus) +void +nsListControlFrame::HandleListSelection(nsIPresContext& aPresContext, + nsGUIEvent* aEvent, + nsEventStatus& aEventStatus) { if (mMultipleSelections) { MultipleSelection(((nsMouseEvent *)aEvent)->isShift, ((nsMouseEvent *)aEvent)->isControl); @@ -713,7 +710,8 @@ void nsListControlFrame::HandleListSelection(nsIPresContext& aPresContext, } } -PRBool nsListControlFrame::HasSameContent(nsIFrame* aFrame1, nsIFrame* aFrame2) +PRBool +nsListControlFrame::HasSameContent(nsIFrame* aFrame1, nsIFrame* aFrame2) { // Quick check, if the frames are equal they must have // the same content @@ -735,8 +733,8 @@ PRBool nsListControlFrame::HasSameContent(nsIFrame* aFrame1, nsIFrame* aFrame2) } -//---------------------------------------------------------------------- -NS_IMETHODIMP nsListControlFrame::HandleLikeListEvent(nsIPresContext& aPresContext, +nsresult +nsListControlFrame::HandleLikeListEvent(nsIPresContext& aPresContext, nsGUIEvent* aEvent, nsEventStatus& aEventStatus) { @@ -762,6 +760,7 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeListEvent(nsIPresContext& aPresConte NS_IMETHODIMP nsListControlFrame :: CaptureMouseEvents(PRBool aGrabMouseEvents) { + // get its view nsIView* view = nsnull; GetView(&view); @@ -773,8 +772,10 @@ nsListControlFrame :: CaptureMouseEvents(PRBool aGrabMouseEvents) if (viewMan) { if (aGrabMouseEvents) { viewMan->GrabMouseEvents(view,result); + mIsCapturingMouseEvents = PR_TRUE; } else { viewMan->GrabMouseEvents(nsnull,result); + mIsCapturingMouseEvents = PR_FALSE; } } } @@ -782,7 +783,8 @@ nsListControlFrame :: CaptureMouseEvents(PRBool aGrabMouseEvents) return NS_OK; } -nsIView* nsListControlFrame::GetViewFor(nsIWidget* aWidget) +nsIView* +nsListControlFrame::GetViewFor(nsIWidget* aWidget) { nsIView* view = nsnull; void* clientData; @@ -799,7 +801,8 @@ nsIView* nsListControlFrame::GetViewFor(nsIWidget* aWidget) // Determine if a view is an ancestor of another view. -PRBool nsListControlFrame::IsAncestor(nsIView* aAncestor, nsIView* aChild) +PRBool +nsListControlFrame::IsAncestor(nsIView* aAncestor, nsIView* aChild) { nsIView* view = aChild; while (nsnull != view) { @@ -814,10 +817,11 @@ PRBool nsListControlFrame::IsAncestor(nsIView* aAncestor, nsIView* aChild) return(PR_FALSE); } -//---------------------------------------------------------------------- -NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aPresContext, - nsGUIEvent* aEvent, - nsEventStatus& aEventStatus) + +nsresult +nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aPresContext, + nsGUIEvent* aEvent, + nsEventStatus& aEventStatus) { if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) { if (nsnull == mHitFrame) { @@ -883,12 +887,14 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aP return NS_OK; } -//---------------------------------------------------------------------- -NS_IMETHODIMP nsListControlFrame::HandleEvent(nsIPresContext& aPresContext, + +NS_IMETHODIMP +nsListControlFrame::HandleEvent(nsIPresContext& aPresContext, nsGUIEvent* aEvent, nsEventStatus& aEventStatus) { -/* const char * desc[] = {"NS_MOUSE_MOVE", +/* + const char * desc[] = {"NS_MOUSE_MOVE", "NS_MOUSE_LEFT_BUTTON_UP", "NS_MOUSE_LEFT_BUTTON_DOWN", "","","","","","","", @@ -910,8 +916,8 @@ NS_IMETHODIMP nsListControlFrame::HandleEvent(nsIPresContext& aPresContext, printf("Mouse in ListFrame %s [%d]\n", desc[inx], aEvent->message); } else { printf("Mouse in ListFrame [%d]\n", aEvent->message); - }*/ - + } +*/ if (nsEventStatus_eConsumeNoDefault == aEventStatus) { return NS_OK; } @@ -930,7 +936,7 @@ NS_IMETHODIMP nsListControlFrame::HandleEvent(nsIPresContext& aPresContext, return NS_OK; } -//---------------------------------------------------------------------- + NS_IMETHODIMP nsListControlFrame::SetInitialChildList(nsIPresContext& aPresContext, nsIAtom* aListName, @@ -945,7 +951,7 @@ nsListControlFrame::SetInitialChildList(nsIPresContext& aPresContext, return nsScrollFrame::SetInitialChildList(aPresContext, aListName, aChildList); } -//---------------------------------------------------------------------- + NS_IMETHODIMP nsListControlFrame::Init(nsIPresContext& aPresContext, nsIContent* aContent, @@ -977,7 +983,7 @@ nsListControlFrame::Init(nsIPresContext& aPresContext, return result; } -//---------------------------------------------------------------------- + nscoord nsListControlFrame::GetVerticalInsidePadding(float aPixToTwip, nscoord aInnerHeight) const @@ -985,7 +991,7 @@ nsListControlFrame::GetVerticalInsidePadding(float aPixToTwip, return NSIntPixelsToTwips(0, aPixToTwip); } -//---------------------------------------------------------------------- + nscoord nsListControlFrame::GetHorizontalInsidePadding(nsIPresContext& aPresContext, float aPixToTwip, @@ -996,7 +1002,6 @@ nsListControlFrame::GetHorizontalInsidePadding(nsIPresContext& aPresContext, } -//---------------------------------------------------------------------- NS_IMETHODIMP nsListControlFrame::GetMultiple(PRBool* aMultiple, nsIDOMHTMLSelectElement* aSelect) { @@ -1013,7 +1018,7 @@ nsListControlFrame::GetMultiple(PRBool* aMultiple, nsIDOMHTMLSelectElement* aSel } } -//---------------------------------------------------------------------- + nsIDOMHTMLSelectElement* nsListControlFrame::GetSelect(nsIContent * aContent) { @@ -1026,7 +1031,7 @@ nsListControlFrame::GetSelect(nsIContent * aContent) } } -//---------------------------------------------------------------------- + NS_IMETHODIMP nsListControlFrame::AboutToDropDown() { @@ -1034,7 +1039,6 @@ nsListControlFrame::AboutToDropDown() return(SyncViewWithFrame()); } - nsIContent* nsListControlFrame::GetOptionAsContent(nsIDOMHTMLCollection* aCollection,PRUint32 aIndex) { @@ -1101,7 +1105,6 @@ nsListControlFrame::SetFrameSelected(PRUint32 aIndex, PRBool aSelected) NS_IF_RELEASE(content); } -//---------------------------------------------------------------------- void nsListControlFrame::InitializeFromContent() { @@ -1127,7 +1130,7 @@ nsListControlFrame::InitializeFromContent() } -//---------------------------------------------------------------------- + nsIDOMHTMLCollection* nsListControlFrame::GetOptions(nsIContent * aContent, nsIDOMHTMLSelectElement* aSelect) { @@ -1147,7 +1150,6 @@ nsListControlFrame::GetOptions(nsIContent * aContent, nsIDOMHTMLSelectElement* a } } -//---------------------------------------------------------------------- nsIDOMHTMLOptionElement* nsListControlFrame::GetOption(nsIDOMHTMLCollection& aCollection, PRUint32 aIndex) { @@ -1163,7 +1165,7 @@ nsListControlFrame::GetOption(nsIDOMHTMLCollection& aCollection, PRUint32 aIndex return nsnull; } -//---------------------------------------------------------------------- + PRBool nsListControlFrame::GetOptionValue(nsIDOMHTMLCollection& aCollection, PRUint32 aIndex, nsString& aValue) { @@ -1184,36 +1186,27 @@ nsListControlFrame::GetOptionValue(nsIDOMHTMLCollection& aCollection, PRUint32 a return status; } -//---------------------------------------------------------------------- -NS_IMETHODIMP +nsresult nsListControlFrame::Deselect() { PRInt32 i; PRInt32 max = GetNumberOfOptions(); for (i=0;i libs:: $(LIBRARY) $(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib $(MAKE_INSTALL) ua.css $(DIST)\bin\res + $(MAKE_INSTALL) arrow.gif $(DIST)\bin\res clobber:: rm -f $(DIST)\lib\$(LIBRARY_NAME).lib rm -f $(DIST)\bin\res\ua.css + rm -f $(DIST)\bin\res\arrow.gif diff --git a/mozilla/layout/html/document/src/ua.css b/mozilla/layout/html/document/src/ua.css index 83377947f49..bee93ddf577 100644 --- a/mozilla/layout/html/document/src/ua.css +++ b/mozilla/layout/html/document/src/ua.css @@ -429,6 +429,18 @@ input[type=hidden] { border: none; visibility: hidden; } + + +input[type=file] { + white-space: nowrap; + border:none; +} + +/* browse button for file selector */ +input[type=file] input[type=button] { + height:inherit; +} + input[type=radio] { /* these margins are for NavQuirks, we need a Standard ua.css */ margin-left: 3px; @@ -738,8 +750,8 @@ label { /* Combo box style */ select, select[size="1"] { vertical-align: bottom; - border: 1px inset #c0c0c0; - background-color:rgb(204, 204, 204); + border: none; + background-color:rgb(204, 204, 204); color:black; white-space:nowrap; text-align: left; @@ -751,10 +763,53 @@ select[size] { border: 1px inset rgb(153, 153, 153); } -select:active { - border : 1px solid black; +select[size="1"] { + vertical-align: bottom; + border: none; + background-color:rgb(204, 204, 204); + color:black; + white-space:nowrap; + text-align: left; } + +/* combobox button */ +select input[type=button] { + border: outset 1px rgb(204, 204, 204); + background-image:url("arrow.gif"); + background-repeat:no-repeat; + background-position:center; + width:12px; + height:12px; + -moz-border-radius:0px; +} + +/* combobox display area */ +select input#-moz-display { + border: inset 1px rgb(204, 204, 204); + background-color: white; + background-image: none; + -moz-border-radius:0px; + padding-left: 0px; + padding-right: 0px; + padding-top: 0px; + padding-bottom: 0px; +} + +/* combbox display area - active */ +select input#-moz-display:active { + border: inset 1px rgb(204, 204, 204); + background-color:white; + background-image: none; + -moz-border-radius:0px; + padding-left: 0px; + padding-right: 0px; + padding-top: 0px; + padding-bottom: 0px; + background-color:white; +} + + option { display:block; padding-left:3px; @@ -985,47 +1040,20 @@ sourcetext { /* XXX should not be in HTML namespace */ display: none; } -:-moz-dropdown-visible { - visibility: visible; -} - -:-moz-dropdown-hidden { - visibility: hidden; -} - -:-moz-dropdown-btn-out { - border: 2px outset #c0c0c0; - background-color: rgb(206, 207, 206); -} - -:-moz-dropdown-btn-pressed { -/* border: 2px inset #c0c0c0; */ - background-color: rgb(204, 204, 204); - border: none; -} - +/* combobox dropdown list */ :-moz-dropdown-list { - position:absolute; - background-color:rgb(204, 204, 204); - border: 1px inset rgb(153, 153, 153); + background-color:inherit; + border: 1px inset rgb(153, 153, 153); } - -:-moz-combobox-text { - color: black; - padding-left: 2px; +/* combobox dropdown list hidden */ +select:-moz-dropdown-list { + visibility:hidden; } -:-moz-combobox-textselected { - background-color: rgb(0,0,128); - color: white; - border: 1px solid rgb(0,0,128); -} - -:-moz-combobox-textselectedfocus { - background-color: rgb(0,0,128); - color: white; - border: 1px dotted white; +/* combobox dropdown list visible */ +select[-moz-dropdown-active]:-moz-dropdown-list { + visibility: visible; } :-moz-anonymous-block { diff --git a/mozilla/layout/html/forms/public/nsIComboboxControlFrame.h b/mozilla/layout/html/forms/public/nsIComboboxControlFrame.h index c021d02b13b..8c2cfb2b5e6 100644 --- a/mozilla/layout/html/forms/public/nsIComboboxControlFrame.h +++ b/mozilla/layout/html/forms/public/nsIComboboxControlFrame.h @@ -21,10 +21,12 @@ #include "nsISupports.h" #include "nsFont.h" + class nsFormFrame; class nsIPresContext; class nsString; class nsIContent; +class nsVoidArray; // IID for the nsIComboboxControlFrame class @@ -45,19 +47,7 @@ public: * Sets the Drop Down List * */ - NS_IMETHOD SetDropDown(nsIFrame* aPlaceHolderFrame, nsIFrame* aDropDownFrame) = 0; - - /** - * Sets the Pseudo Style Contexts for the DropDown - * - */ - NS_IMETHOD SetDropDownStyleContexts(nsIStyleContext * aVisible, nsIStyleContext * aHidden) = 0; - - /** - * Sets the Pseudo Style Contexts for the Button - * - */ - NS_IMETHOD SetButtonStyleContexts(nsIStyleContext * aOut, nsIStyleContext * aPressed) = 0; + NS_IMETHOD SetDropDown(nsIFrame* aDropDownFrame) = 0; /** * Notifies the Combobox the List was selected @@ -65,6 +55,7 @@ public: */ NS_IMETHOD ListWasSelected(nsIPresContext* aPresContext) = 0; + }; #endif diff --git a/mozilla/layout/html/forms/public/nsIFormControlFrame.h b/mozilla/layout/html/forms/public/nsIFormControlFrame.h index 82f30663c81..1f5de7a509e 100644 --- a/mozilla/layout/html/forms/public/nsIFormControlFrame.h +++ b/mozilla/layout/html/forms/public/nsIFormControlFrame.h @@ -67,6 +67,25 @@ public: nscoord aInnerWidth, nscoord aCharWidth) const = 0; + + /** + * Set the suggested size for the form element. + * This is used to control the size of the element during reflow if it hasn't had it's size + * explicitly set. + * @param aWidth width of the form element + * @param aHeight height of the form element + * @returns NS_OK + */ + + NS_IMETHOD SetSuggestedSize(nscoord aWidth, nscoord aHeight) = 0; + + /** + * Determine if the control uses a native widget for rendering + * @param aRequiresWidget is set to PR_TRUE if it has a native widget, PR_FALSE otherwise. + * @returns NS_OK + */ + + /** * Determine if the control uses a native widget for rendering * @param aRequiresWidget is set to PR_TRUE if it has a native widget, PR_FALSE otherwise. diff --git a/mozilla/layout/html/forms/public/nsIListControlFrame.h b/mozilla/layout/html/forms/public/nsIListControlFrame.h index 908a34bd68d..f17224a6a5a 100644 --- a/mozilla/layout/html/forms/public/nsIListControlFrame.h +++ b/mozilla/layout/html/forms/public/nsIListControlFrame.h @@ -63,6 +63,12 @@ public: */ NS_IMETHOD CaptureMouseEvents(PRBool aGrabMouseEvents) = 0; + /** + * Returns the maximum width and height of an item in the listbox + */ + + NS_IMETHOD GetMaximumSize(nsSize &aSize) = 0; + }; diff --git a/mozilla/layout/html/forms/src/nsButtonControlFrame.cpp b/mozilla/layout/html/forms/src/nsButtonControlFrame.cpp index 9dca0fbb356..c5838e20f0a 100644 --- a/mozilla/layout/html/forms/src/nsButtonControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsButtonControlFrame.cpp @@ -263,6 +263,11 @@ nsButtonControlFrame::AttributeChanged(nsIPresContext* aPresContext, else { result = nsFormControlFrame::AttributeChanged(aPresContext, aChild, aAttribute, aHint); } + } else { + if (nsHTMLAtoms::value == aAttribute) { + // redraw button with the changed value + Invalidate(mRect, PR_TRUE); + } } return result; } @@ -382,6 +387,28 @@ nsButtonControlFrame::Reflow(nsIPresContext& aPresContext, nsFormFrame::AddFormControlFrame(aPresContext, *this); } + if ((NS_FORMSIZE_NOTSET != mSuggestedWidth) && ( + NS_FORMSIZE_NOTSET != mSuggestedHeight)) + { + aDesiredSize.width = mSuggestedWidth; + aDesiredSize.height = mSuggestedHeight; + aDesiredSize.ascent = mSuggestedHeight; + aDesiredSize.descent = 0; + if (aDesiredSize.maxElementSize) { + aDesiredSize.maxElementSize->width = mSuggestedWidth; + aDesiredSize.maxElementSize->height = mSuggestedWidth; + } + + if (nsnull != aDesiredSize.maxElementSize) { + aDesiredSize.maxElementSize->width = aDesiredSize.width; + aDesiredSize.maxElementSize->height = aDesiredSize.height; + } + + aStatus = NS_FRAME_COMPLETE; + return NS_OK; + + } + nsSize ignore; GetDesiredSize(&aPresContext, aReflowState, aDesiredSize, ignore); @@ -421,6 +448,29 @@ nsButtonControlFrame::GetDesiredSize(nsIPresContext* aPresContext, PRInt32 type; GetType(&type); + +#if 0 + if ((NS_FORM_INPUT_HIDDEN != type) && ((NS_FORMSIZE_NOTSET != mSuggestedWidth) && ( + NS_FORMSIZE_NOTSET != mSuggestedHeight))) + { + aDesiredLayoutSize.width = mSuggestedWidth; + aDesiredLayoutSize.height = mSuggestedHeight; + aDesiredLayoutSize.ascent = mSuggestedHeight; + aDesiredLayoutSize.descent = 0; + if (aDesiredLayoutSize.maxElementSize) { + aDesiredLayoutSize.maxElementSize->width = mSuggestedWidth; + aDesiredLayoutSize.maxElementSize->height = mSuggestedWidth; + } + aDesiredWidgetSize.width = aDesiredLayoutSize.width; + aDesiredWidgetSize.height= aDesiredLayoutSize.height; + + return; + } +#endif + + + + if (NS_FORM_INPUT_HIDDEN == type) { // there is no physical rep aDesiredLayoutSize.width = 0; aDesiredLayoutSize.height = 0; diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp index ddb75962403..0202a7ef1aa 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp @@ -18,51 +18,32 @@ #include "nsCOMPtr.h" #include "nsComboboxControlFrame.h" #include "nsFormFrame.h" -#include "nsButtonControlFrame.h" -#include "nsTextControlFrame.h" -#include "nsIContent.h" -#include "prtypes.h" -#include "nsIAtom.h" -#include "nsIPresContext.h" +#include "nsFormControlFrame.h" #include "nsIHTMLContent.h" #include "nsHTMLIIDs.h" #include "nsHTMLAtoms.h" -#include "nsIFileWidget.h" -#include "nsITextWidget.h" -#include "nsWidgetsCID.h" -#include "nsIComponentManager.h" -#include "nsIView.h" #include "nsHTMLParts.h" -#include "nsIDOMHTMLInputElement.h" #include "nsIFormControl.h" #include "nsINameSpaceManager.h" -#include "nsITextContent.h" - -// Used for Paint -#include "nsCSSRendering.h" -#include "nsIDeviceContext.h" - -#include "nsIPresShell.h" -#include "nsIView.h" -#include "nsIViewManager.h" -#include "nsViewsCID.h" +#include "nsIDOMEventReceiver.h" +#include "nsLayoutAtoms.h" #include "nsIDOMElement.h" #include "nsListControlFrame.h" #include "nsIListControlFrame.h" #include "nsIDOMHTMLCollection.h" #include "nsIDOMHTMLSelectElement.h" #include "nsIDOMHTMLOptionElement.h" +#include "nsIPresShell.h" +#include "nsISupportsArray.h" +#include "nsIDeviceContext.h" +#include "nsIView.h" -static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); -static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); -static NS_DEFINE_IID(kCFileWidgetCID, NS_FILEWIDGET_CID); -static NS_DEFINE_IID(kIFileWidgetIID, NS_IFILEWIDGET_IID); -static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID); static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); static NS_DEFINE_IID(kIComboboxControlFrameIID, NS_ICOMBOBOXCONTROLFRAME_IID); -static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID); -static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); static NS_DEFINE_IID(kIListControlFrameIID, NS_ILISTCONTROLFRAME_IID); +static NS_DEFINE_IID(kIDOMMouseListenerIID, NS_IDOMMOUSELISTENER_IID); +static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); +static NS_DEFINE_IID(kIAnonymousContentCreatorIID, NS_IANONYMOUS_CONTENT_CREATOR_IID); // Drop down list event management. // The combo box uses the following strategy for managing the @@ -76,6 +57,11 @@ static NS_DEFINE_IID(kIListControlFrameIID, NS_ILISTCONTROLFRAME_IID); // The ListWasSelected code will turn off mouse-capture for the drop-down list. // The drop-down list does not explicitly set capture when it is in the drop-down mode. + +//XXX: This is temporary. It simulates psuedo states by using a attribute selector on + +const char * kMozDropdownActive = "-moz-dropdown-active"; + nsresult NS_NewComboboxControlFrame(nsIFrame** aNewFrame) { @@ -92,29 +78,30 @@ NS_NewComboboxControlFrame(nsIFrame** aNewFrame) } nsComboboxControlFrame::nsComboboxControlFrame() - : nsHTMLContainerFrame() + : nsAreaFrame() { - mFormFrame = nsnull; - mListFrame = nsnull; + mPresContext = nsnull; + mFormFrame = nsnull; mListControlFrame = nsnull; - mPlaceHolderFrame = nsnull; - mVisibleStyleContext = nsnull; - mHiddenStyleContext = nsnull; - mCurrentStyleContext = nsnull; - mBlockTextStyle = nsnull; - mBlockTextSelectedStyle = nsnull; - mBlockTextSelectedFocusStyle = nsnull; - mFirstTime = PR_TRUE; - mGotFocus = PR_FALSE; + mTextStr = ""; + mDisplayContent = nsnull; + mButtonContent = nsnull; + mDroppedDown = PR_FALSE; + mDisplayFrame = nsnull; + mButtonFrame = nsnull; + mDropdownFrame = nsnull; + + //Shrink the area around it's contents + SetFlags(NS_BLOCK_SHRINK_WRAP); } //-------------------------------------------------------------- nsComboboxControlFrame::~nsComboboxControlFrame() { - NS_IF_RELEASE(mVisibleStyleContext); - NS_IF_RELEASE(mHiddenStyleContext); - NS_IF_RELEASE(mBlockTextStyle); mFormFrame = nsnull; + NS_IF_RELEASE(mPresContext); + NS_IF_RELEASE(mDisplayContent); + NS_IF_RELEASE(mButtonContent); } //-------------------------------------------------------------- @@ -132,9 +119,32 @@ nsComboboxControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) if (aIID.Equals(kIFormControlFrameIID)) { *aInstancePtr = (void*) ((nsIFormControlFrame*) this); return NS_OK; + } else if (aIID.Equals(kIDOMMouseListenerIID)) { + *aInstancePtr = (void*)(nsIDOMMouseListener*) this; + NS_ADDREF_THIS(); + return NS_OK; + } else if (aIID.Equals(kIAnonymousContentCreatorIID)) { + *aInstancePtr = (void*)(nsIAnonymousContentCreator*) this; + NS_ADDREF_THIS(); + return NS_OK; } - return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr); + return nsAreaFrame::QueryInterface(aIID, aInstancePtr); +} + + +NS_IMETHODIMP +nsComboboxControlFrame::Init(nsIPresContext& aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) +{ + // Need to hold on the pres context because it is used later in methods + // which don't have it passed in. + mPresContext = &aPresContext; + NS_ADDREF(mPresContext); + return nsAreaFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); } //-------------------------------------------------------------- @@ -149,15 +159,22 @@ nsComboboxControlFrame::IsSuccessful(nsIFormControlFrame* aSubmitter) // Initialize the text string in the combobox using either the current // selection in the list box or the first item item in the list box. -void nsComboboxControlFrame::InitTextStr() +void +nsComboboxControlFrame::InitTextStr(PRBool aUpdate) { + nsIFormControlFrame* fcFrame = nsnull; + nsIFrame* dropdownFrame = GetDropdownFrame(); + nsresult result = dropdownFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + + // Reset the list, so we can ask it for it's selected item. + fcFrame->Reset(); + // Update the selected text string mListControlFrame->GetSelectedItem(mTextStr); if (mTextStr == "") { // No selection so use the first item in the list box - nsIFormControlFrame* fcFrame = nsnull; - nsresult result = mListFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + if ((NS_OK == result) && (nsnull != fcFrame)) { // Set listbox selection to first item in the list box fcFrame->SetProperty(nsHTMLAtoms::selectedindex, "0"); @@ -165,21 +182,28 @@ void nsComboboxControlFrame::InitTextStr() mListControlFrame->GetSelectedItem(mTextStr); } } + + // Update the display by setting the value attribute + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, mTextStr, aUpdate); } //-------------------------------------------------------------- +// Reset the combo box back to it original state. + void nsComboboxControlFrame::Reset() { - SetFocus(PR_TRUE, PR_TRUE); + // Reset the dropdown list to its original state nsIFormControlFrame* fcFrame = nsnull; - nsresult result = mListFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + nsIFrame* dropdownFrame = GetDropdownFrame(); + nsresult result = dropdownFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); if ((NS_OK == result) && (nsnull != fcFrame)) { fcFrame->Reset(); } - InitTextStr(); + // Update the combobox using the text string returned from the dropdown list + InitTextStr(PR_TRUE); } void @@ -190,7 +214,6 @@ nsComboboxControlFrame::PostCreateWidget(nsIPresContext* aPresContext, Reset(); } - //-------------------------------------------------------------- NS_IMETHODIMP nsComboboxControlFrame::GetType(PRInt32* aType) const @@ -224,7 +247,7 @@ nsComboboxControlFrame::GetFont(nsIPresContext* aPresContext, nscoord nsComboboxControlFrame::GetVerticalBorderWidth(float aPixToTwip) const { - return NSIntPixelsToTwips(3, aPixToTwip); + return 0; } @@ -232,7 +255,7 @@ nsComboboxControlFrame::GetVerticalBorderWidth(float aPixToTwip) const nscoord nsComboboxControlFrame::GetHorizontalBorderWidth(float aPixToTwip) const { - return GetVerticalBorderWidth(aPixToTwip); + return 0; } @@ -255,335 +278,421 @@ nsComboboxControlFrame::GetHorizontalInsidePadding(nsIPresContext& aPresContext, } -//-------------------------------------------------------------- + void nsComboboxControlFrame::SetFocus(PRBool aOn, PRBool aRepaint) { - //XXX: TODO Make set focus work - //mContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, "SELECTED", PR_TRUE); - mGotFocus = aOn; - if (aRepaint) { - nsFormControlHelper::ForceDrawFrame(this); + //XXX: TODO Implement focus for combobox. +} + +// Toggle dropdown list. + +void +nsComboboxControlFrame::ToggleList(nsIPresContext* aPresContext) +{ + if (PR_TRUE == mDroppedDown) { + ShowList(aPresContext, PR_FALSE); + } else { + ShowList(aPresContext, PR_TRUE); } } -//-------------------------------------------------------------- + +void +nsComboboxControlFrame::ShowPopup(PRBool aShowPopup) +{ + //XXX: This is temporary. It simulates a psuedo dropdown states by using a attribute selector + // This will not be need if the event state supports active states for use with the dropdown list + // Currently, the event state manager will reset the active state to the content which has focus + // which causes the active state to be removed from the event state manager immediately after it + // it the select is set to the active state. + + nsCOMPtr activeAtom ( dont_QueryInterface(NS_NewAtom(kMozDropdownActive))); + if (PR_TRUE == aShowPopup) { + mContent->SetAttribute(kNameSpaceID_None, activeAtom, "", PR_TRUE); + } else { + mContent->UnsetAttribute(kNameSpaceID_None, activeAtom, PR_TRUE); + } +} + +// Show the dropdown list + +void +nsComboboxControlFrame::ShowList(nsIPresContext* aPresContext, PRBool aShowList) +{ + if (PR_TRUE == aShowList) { + mListControlFrame->AboutToDropDown(); + ShowPopup(PR_TRUE); + mDroppedDown = PR_TRUE; + // The listcontrol frame will call back to the nsComboboxControlFrame's ListWasSelected + // which will stop the capture. + mListControlFrame->CaptureMouseEvents(PR_TRUE); + } else { + ShowPopup(PR_FALSE); + mDroppedDown = PR_FALSE; + } +} + + +//------------------------------------------------------------- // this is in response to the MouseClick from the containing browse button // XXX: TODO still need to get filters from accept attribute -void nsComboboxControlFrame::MouseClicked(nsIPresContext* aPresContext) +void +nsComboboxControlFrame::MouseClicked(nsIPresContext* aPresContext) { - if (nsnull != mListControlFrame) { - //XXX: Make this work SetFocus(PR_FALSE, PR_TRUE); - mCurrentStyleContext = (mCurrentStyleContext == mHiddenStyleContext ? mVisibleStyleContext : mHiddenStyleContext); - if (mCurrentStyleContext == mVisibleStyleContext) { - mListControlFrame->AboutToDropDown(); - - nsIFormControlFrame* fcFrame = nsnull; - nsresult result = mListFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); - if ((NS_OK == result) && (nsnull != fcFrame)) { - //XXX: Make this work fcFrame->SetFocus(PR_TRUE, PR_FALSE); - } + ToggleList(aPresContext); +} - } else { - //XXX: Make this work SetFocus(PR_TRUE, PR_TRUE); - } - //XXX: This should not be necessary. Need to restructure the combo box as follows: - // Derive nsComboboxFrame from nsAreaFrame. Attach the placeholder frame, a label frame and - // a button frame. Override reresolve style context and reresolve the style on the ListBox. - // The event state manager should then be asked to set active and non-active based on - // The mouse click this would get rid of all of the ugly code here. The setting of the active - // Should cause re-resolution of the AreaFrame which will re-sync it. KMM. - mListFrame->ReResolveStyleContext(aPresContext, mCurrentStyleContext, NS_STYLE_HINT_NONE, nsnull, nsnull); - - // Resync view with frame. - const nsStyleDisplay* disp = (const - nsStyleDisplay*)mCurrentStyleContext->GetStyleData(eStyleStruct_Display); - nsIView * view; - mListFrame->GetView(&view); - if (view) { - view->SetVisibility(NS_STYLE_VISIBILITY_HIDDEN == disp->mVisible ? - nsViewVisibility_kHide:nsViewVisibility_kShow); - } - nsFormControlHelper::ForceDrawFrame(mListFrame); - //XXX: End of the ugly code. - +nsresult +nsComboboxControlFrame::ReflowComboChildFrame(nsIFrame* aFrame, + nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus, + nscoord aAvailableWidth, + nscoord aAvailableHeight) +{ + // Constrain the child's width and height to aAvailableWidth and aAvailableHeight + nsSize availSize(aAvailableWidth, aAvailableHeight); + nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aFrame, + availSize); + kidReflowState.computedWidth = aAvailableWidth; + kidReflowState.computedHeight = aAvailableHeight; + + // Reflow child + nsresult rv = ReflowChild(aFrame, aPresContext, aDesiredSize, kidReflowState, aStatus); + + // Set the child's width and height to it's desired size + nsRect rect; + aFrame->GetRect(rect); + rect.width = aDesiredSize.width; + rect.height = aDesiredSize.height; + aFrame->SetRect(rect); + return rv; +} + +// Suggest a size for the child frame. +// Only frames which implement the nsIFormControlFrame interface and +// honor the SetSuggestedSize method will be placed and sized correctly. + +void +nsComboboxControlFrame::SetChildFrameSize(nsIFrame* aFrame, nscoord aWidth, nscoord aHeight) +{ + nsIFormControlFrame* fcFrame = nsnull; + nsresult result = aFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + if (NS_SUCCEEDED(result) && (nsnull != fcFrame)) { + fcFrame->SetSuggestedSize(aWidth, aHeight); } } -//-------------------------------------------------------------- -NS_IMETHODIMP nsComboboxControlFrame::Reflow(nsIPresContext& aPresContext, +nsresult +nsComboboxControlFrame::GetPrimaryComboFrame(nsIPresContext& aPresContext, nsIContent* aContent, nsIFrame** aFrame) +{ + nsresult rv = NS_OK; + // Get the primary frame from the presentation shell. + nsCOMPtr presShell; + rv = aPresContext.GetShell(getter_AddRefs(presShell)); + if (NS_SUCCEEDED(rv) && presShell) { + presShell->GetPrimaryFrameFor(aContent, aFrame); + } + return rv; +} + +nsIFrame* +nsComboboxControlFrame::GetButtonFrame(nsIPresContext& aPresContext) +{ + if (mButtonFrame == nsnull) { + NS_ASSERTION(mButtonContent != nsnull, "nsComboboxControlFrame mButtonContent is null"); + GetPrimaryComboFrame(aPresContext, mButtonContent, &mButtonFrame); + } + + return mButtonFrame; +} + +nsIFrame* +nsComboboxControlFrame::GetDisplayFrame(nsIPresContext& aPresContext) +{ + if (mDisplayFrame == nsnull) { + NS_ASSERTION(mDisplayContent != nsnull, "nsComboboxControlFrame mDisplayContent is null"); + GetPrimaryComboFrame(aPresContext, mDisplayContent, &mDisplayFrame); + } + + return mDisplayFrame; +} + +nsIFrame* +nsComboboxControlFrame::GetDropdownFrame() +{ + return mDropdownFrame; +} + + +nsresult +nsComboboxControlFrame::GetScreenHeight(nsIPresContext& aPresContext, + nscoord& aHeight) +{ + aHeight = 0; + nsIDeviceContext* context; + aPresContext.GetDeviceContext( &context ); + if ( nsnull != context ) + { + PRInt32 height; + PRInt32 width; + context->GetDeviceSurfaceDimensions(width, height); + float devUnits; + context->GetDevUnitsToAppUnits(devUnits); + aHeight = NSToIntRound(float( height) / devUnits ); + NS_RELEASE( context ); + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + + +nsresult +nsComboboxControlFrame::PositionDropdown(nsIPresContext& aPresContext, + nscoord aHeight, + nsRect aAbsoluteTwipsRect, + nsRect aAbsolutePixelRect) +{ + // Position the dropdown list. It is positioned below the display frame if there is enough + // room on the screen to display the entire list. Otherwise it is placed above the display + // frame. + + // Note: As first glance, it appears that you could simply get the absolute bounding box for the + // dropdown list by first getting it's view, then getting the view's nsIWidget, then asking the nsIWidget + // for it's AbsoluteBounds. The problem with this approach, is that the dropdown lists y location can + // change based on whether the dropdown is placed below or above the display frame. + // The approach, taken here is to get use the absolute position of the display frame and use it's location + // to determine if the dropdown will go offscreen. + + // Use the height calculated for the area frame so it includes both + // the display and button heights. + nsresult rv = NS_OK; + nsIFrame* dropdownFrame = GetDropdownFrame(); + nscoord dropdownYOffset = aHeight; +/* XXX: Enable this code to debug popping up above the display frame, rather than below it + nscoord screenHeightInPixels = 0; + if (NS_SUCCEEDED(GetScreenHeight(aPresContext, screenHeightInPixels))) { + nsRect absoluteRect; + + // Get the height of the dropdown list in pixels. + nsRect dropdownRect; + dropdownFrame->GetRect(dropdownRect); + float t2p; + aPresContext.GetTwipsToPixels(&t2p); + nscoord absoluteDropDownHeight = NSTwipsToIntPixels(dropdownRect.height, t2p); + + // Check to see if the drop-down list will go offscreen + if (NS_SUCCEEDED(rv) && ((aAbsolutePixelRect.y + aAbsolutePixelRect.height + absoluteDropDownHeight) > screenHeightInPixels)) { + // move the dropdown list up + dropdownYOffset = - (aAbsoluteTwipsRect.height); + } + } +*/ + + nsRect dropdownRect; + dropdownFrame->GetRect(dropdownRect); + dropdownRect.x = 0; + dropdownRect.y = dropdownYOffset; + dropdownFrame->SetRect(dropdownRect); + + return rv; +} + + +// Calculate a frame's position in screen coordinates +nsresult +nsComboboxControlFrame::GetAbsoluteFramePosition(nsIPresContext& aPresContext, + nsIFrame *aFrame, + nsRect& aAbsoluteTwipsRect, + nsRect& aAbsolutePixelRect) +{ + //XXX: This code needs to take the view's offset into account when calculating + //the absolute coordinate of the frame. + nsresult rv = NS_OK; + + aFrame->GetRect(aAbsoluteTwipsRect); + + // Get conversions between twips and pixels + float t2p; + float p2t; + aPresContext.GetTwipsToPixels(&t2p); + aPresContext.GetPixelsToTwips(&p2t); + + // Add in frame's offset from it it's containing view + nsIView *containingView = nsnull; + nsPoint offset; + rv = aFrame->GetOffsetFromView(offset, &containingView); + if (NS_SUCCEEDED(rv) && (nsnull != containingView)) { + aAbsoluteTwipsRect.x += offset.x; + aAbsoluteTwipsRect.y += offset.y; + // Addin the containing view's offset form it's containing widget + nsIWidget* widget = nsnull; + nscoord widgetx = 0; + nscoord widgety = 0; + rv = containingView->GetOffsetFromWidget(&widgetx, &widgety, widget); + if (NS_SUCCEEDED(rv) && (nsnull != widget)) { + aAbsoluteTwipsRect.x += widgetx; + aAbsoluteTwipsRect.y += widgety; + + // Add in the absolute offset of the widget. + nsRect absBounds; + widget->GetAbsoluteBounds(absBounds); + + // Convert widget coordinates to twips + aAbsoluteTwipsRect.x += NSIntPixelsToTwips(absBounds.x, p2t); + aAbsoluteTwipsRect.y += NSIntPixelsToTwips(absBounds.y, p2t); + NS_RELEASE(widget); + } + } + + // convert to pixel coordinates + if (NS_SUCCEEDED(rv)) { + aAbsolutePixelRect.x = NSTwipsToIntPixels(aAbsoluteTwipsRect.x, t2p); + aAbsolutePixelRect.y = NSTwipsToIntPixels(aAbsoluteTwipsRect.y, t2p); + aAbsolutePixelRect.width = NSTwipsToIntPixels(aAbsoluteTwipsRect.width, t2p); + aAbsolutePixelRect.height = NSTwipsToIntPixels(aAbsoluteTwipsRect.height, t2p); + } + + return rv; +} + + +NS_IMETHODIMP +nsComboboxControlFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - // XXX Combo box should be changed to be implemented as a label and button frame. - // This would eliminate all of this Reflow code. KMM + nsresult rv = NS_OK; + nsIFrame* buttonFrame = GetButtonFrame(aPresContext); + nsIFrame* displayFrame = GetDisplayFrame(aPresContext); + nsIFrame* dropdownFrame = GetDropdownFrame(); - // add ourself as an nsIFormControlFrame + // Don't try to do any special sizing and positioning unless all of the frames + // have been created. + if ((nsnull == displayFrame) || + (nsnull == buttonFrame) || + (nsnull == dropdownFrame)) + { + // Since combobox frames are missing just do a normal area frame reflow + return nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + } + + // size of each part of the combo box + nsRect displayRect; + nsRect buttonRect; + nsRect dropdownRect; + + if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { nsFormFrame::AddFormControlFrame(aPresContext, *this); } + // Get the current sizes of the combo box child frames + displayFrame->GetRect(displayRect); + buttonFrame->GetRect(buttonRect); + dropdownFrame->GetRect(dropdownRect); - if (mFirstTime) { - ReResolveStyleContext(&aPresContext, mStyleContext, NS_STYLE_HINT_REFLOW, nsnull, nsnull); // XXX This temporary - mListFrame->ReResolveStyleContext(&aPresContext, mCurrentStyleContext, NS_STYLE_HINT_REFLOW, nsnull, nsnull); - mFirstTime = PR_FALSE; - InitTextStr(); - } + nsHTMLReflowState firstPassState(aReflowState); - PRInt32 numChildren = mFrames.GetLength(); - - if (1 == numChildren) { - aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::comboText, - mStyleContext, PR_FALSE, - &mBlockTextStyle); - - // XXX This code should move to Init(), someday when the frame construction - // changes are all done and Init() is always getting called... - /*PRBool disabled = */nsFormFrame::GetDisabled(this); - } - - nsIDOMHTMLSelectElement* select = nsListControlFrame::GetSelect(mContent); - if (!select) { - return NS_OK; - } - nsIDOMHTMLCollection* options = nsListControlFrame::GetOptions(mContent, select); - if (!options) { - NS_RELEASE(select); - return NS_OK; - } - - // get the css size - nsSize styleSize; - nsFormControlFrame::GetStyleSize(aPresContext, aReflowState, styleSize); - - // get the size of the longest option - PRInt32 maxWidth = 1; - PRUint32 numOptions; - options->GetLength(&numOptions); - for (PRUint32 i = 0; i < numOptions; i++) { - nsIDOMHTMLOptionElement* option = nsListControlFrame::GetOption(*options, i); - if (option) { - nsAutoString text; - if (NS_CONTENT_ATTR_HAS_VALUE != option->GetText(text)) { - continue; + // Only reflow the display and button if they are the target of + // the incremental reflow, unless they change size. If they do + // then everything needs to be reflowed. + if (eReflowReason_Incremental == firstPassState.reason) { + nsIFrame* targetFrame; + firstPassState.reflowCommand->GetTarget(targetFrame); + if ((targetFrame == buttonFrame) || (targetFrame == displayFrame)) { + nsRect oldDisplayRect = displayRect; + nsRect oldButtonRect = buttonRect; + rv = nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + displayFrame->GetRect(displayRect); + buttonFrame->GetRect(buttonRect); + if ((oldDisplayRect == displayRect) && (oldButtonRect == buttonRect)) { + // Reposition the popup. + nsRect absoluteTwips; + nsRect absolutePixels; + GetAbsoluteFramePosition(aPresContext, displayFrame, absoluteTwips, absolutePixels); + PositionDropdown(aPresContext, displayRect.height, absoluteTwips, absolutePixels); + return rv; } - nsSize textSize; - // use the style for the select rather that the option, since widgets don't support it - nsFormControlHelper::GetTextSize(aPresContext, this, text, textSize, aReflowState.rendContext); - if (textSize.width > maxWidth) { - maxWidth = textSize.width; - } - NS_RELEASE(option); } + nsIReflowCommand::ReflowType type; + aReflowState.reflowCommand->GetType(type); + firstPassState.reason = eReflowReason_StyleChange; + firstPassState.reflowCommand = nsnull; } - PRInt32 rowHeight = 0; - nsSize desiredSize; - nsSize minSize; - PRBool widthExplicit, heightExplicit; - nsInputDimensionSpec textSpec(nsnull, PR_FALSE, nsnull, nsnull, - maxWidth, PR_TRUE, nsHTMLAtoms::size, 1); - // XXX fix CalculateSize to return PRUint32 - PRUint32 numRows = - (PRUint32)nsFormControlHelper::CalculateSize(&aPresContext, aReflowState.rendContext, this, - styleSize, textSpec, desiredSize, minSize, - widthExplicit, heightExplicit, rowHeight); - float sp2t; - float p2t; - aPresContext.GetPixelsToTwips(&p2t); - aPresContext.GetScaledPixelsToTwips(&sp2t); - nscoord onePixel = NSIntPixelsToTwips(1, sp2t); - nscoord extra = desiredSize.height - (rowHeight * numRows); - numRows = (numOptions > 20 ? 20 : numOptions); - desiredSize.height = (numRows * rowHeight) + extra; - aDesiredSize.descent = 0; - nsMargin border; - const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); - mySpacing->CalcBorderFor(this, border); + //Set the desired size for the button and display frame + if (NS_UNCONSTRAINEDSIZE == firstPassState.computedWidth) { + // 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. - float scale; - float sbWidth; - float sbHeight; - nsCOMPtr context; - aPresContext.GetDeviceContext(getter_AddRefs(context)); - context->GetCanonicalPixelScale(scale); - context->GetScrollBarDimensions(sbWidth, sbHeight); - PRInt32 scrollbarScaledWidth = PRInt32(sbWidth * scale); + // Reflow the dropdown shrink-wrapped. + nsHTMLReflowMetrics dropdownDesiredSize(aDesiredSize); + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + dropdownFrame->GetRect(dropdownRect); + // Get maximum size and height of a option in the dropdown - nsFont font(aPresContext.GetDefaultFixedFontDeprecated()); - SystemAttrStruct sis; - sis.mFont = &font; - context->GetSystemAttribute(eSystemAttr_Font_Tooltips, &sis); + nsSize size; + mListControlFrame->GetMaximumSize(size); - //XXX: This 14 pixel hardcode value here is bad. The style system should control - //everyting. KMM - nscoord horKludgeAdjustment = NSIntPixelsToTwips(14, p2t); - nscoord horAdjustment = scrollbarScaledWidth + border.left + border.right + horKludgeAdjustment; + // Set width of display to match width of the drop down + SetChildFrameSize(displayFrame, dropdownRect.width, size.height); - aDesiredSize.width = desiredSize.width + horAdjustment; + // Size the button to be the same height as the displayFrame + SetChildFrameSize(buttonFrame, size.height, size.height); - nscoord verKludgeAdjustment = onePixel; - nscoord verAdjustment = border.top + border.bottom + verKludgeAdjustment; + // Reflow display + button + nsAreaFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); + displayFrame->GetRect(displayRect); - aDesiredSize.height = rowHeight + verAdjustment; + // Reflow the dropdown list to match the width of the display + button + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, aDesiredSize.width, NS_UNCONSTRAINEDSIZE); + dropdownFrame->GetRect(dropdownRect); - mButtonRect.SetRect(aDesiredSize.width-scrollbarScaledWidth-border.right, border.top, - scrollbarScaledWidth, aDesiredSize.height - verAdjustment); - - if (nsnull != aDesiredSize.maxElementSize) { - aDesiredSize.maxElementSize->width = minSize.width + verAdjustment; - aDesiredSize.maxElementSize->height = minSize.height + horAdjustment; - } - - nsRect frameRect; - GetRect(frameRect); - nsRect curRect; - mPlaceHolderFrame->GetRect(curRect); - curRect.x = 0; - - curRect.y = frameRect.y + aDesiredSize.height; - mPlaceHolderFrame->SetRect(curRect); - mListFrame->GetRect(frameRect); - - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; - aStatus = NS_FRAME_COMPLETE; - - return NS_OK; -} - -//------------------------------------------------------------------------------ -void -nsComboboxControlFrame::PaintComboboxControl(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) -{ - //XXX Combo box should be changed to be implemented as a label and button frame. - //This would eliminate all of this rendering code. KMM - const nsStyleDisplay* disp = (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display); - if (!disp->mVisible) { - return; - } - aRenderingContext.PushState(); - - const nsStyleColor* myColor = (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color); - const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); - const nsStyleFont* myFont = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); - - nsIStyleContext * blkStyle; - if (mGotFocus) { - blkStyle = mTextStr.Length() > 0?mBlockTextSelectedFocusStyle:mBlockTextStyle; - } else { - blkStyle = mTextStr.Length() > 0?mBlockTextSelectedStyle:mBlockTextStyle; - } - const nsStyleColor* blkColor = (const nsStyleColor*)blkStyle->GetStyleData(eStyleStruct_Color); - const nsStyleSpacing* blkSpacing = (const nsStyleSpacing*)blkStyle->GetStyleData(eStyleStruct_Spacing); -// const nsStyleFont* blkFont = (const nsStyleFont*)blkStyle->GetStyleData(eStyleStruct_Font); - - nsRect rect(0, 0, mRect.width, mRect.height); - nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this, - aDirtyRect, rect, *myColor, *mySpacing, 0, 0); - - nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, - aDirtyRect, rect, *mySpacing, mStyleContext, 0); - - nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); - - const nsStyleSpacing* spacing =(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); - nsMargin border; - spacing->CalcBorderFor(this, border); - - float p2t; - aPresContext.GetScaledPixelsToTwips(&p2t); - nscoord onePixel = NSIntPixelsToTwips(1, p2t); - - nsRect outside(0, 0, mRect.width, mRect.height); - outside.Deflate(border); - - nsRect inside(outside); - outside.Deflate(onePixel, onePixel); - - aRenderingContext.SetColor(blkColor->mBackgroundColor); - aRenderingContext.FillRect(inside.x, inside.y, inside.width, inside.height); - - float appUnits; - float devUnits; - float scale; - nsIDeviceContext * context; - aRenderingContext.GetDeviceContext(context); - - context->GetCanonicalPixelScale(scale); - context->GetAppUnitsToDevUnits(devUnits); - context->GetDevUnitsToAppUnits(appUnits); - - float sbWidth; - float sbHeight; - context->GetScrollBarDimensions(sbWidth, sbHeight); - PRInt32 scrollbarScaledWidth = PRInt32(sbWidth * scale); - PRInt32 scrollbarScaledHeight = PRInt32(sbWidth * scale); - - nsFont font(aPresContext.GetDefaultFixedFontDeprecated()); - GetFont(&aPresContext, font); - - aRenderingContext.SetFont(myFont->mFont); - - inside.width -= scrollbarScaledWidth; - PRBool clipEmpty; - aRenderingContext.PushState(); - aRenderingContext.SetClipRect(inside, nsClipCombine_kReplace, clipEmpty); - - nscoord x = inside.x + (onePixel * 4); - nscoord y = inside.y; - - aRenderingContext.SetColor(blkColor->mColor); - - aRenderingContext.DrawString(mTextStr, x, y); - nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, - aDirtyRect, inside, *blkSpacing, blkStyle, 0); - - aRenderingContext.PopState(clipEmpty); - - inside.width -= scrollbarScaledWidth; - inside.height -= scrollbarScaledHeight; - - const nsStyleSpacing* arrowSpacing = (const nsStyleSpacing*)mArrowStyle->GetStyleData(eStyleStruct_Spacing); - - nsRect srect(0,0,0,0); - srect = mButtonRect; - nsFormControlHelper::PaintArrow(nsFormControlHelper::eArrowDirection_Down, aRenderingContext,aPresContext, - aDirtyRect, srect, onePixel, mArrowStyle, *arrowSpacing, this, mRect); + } else { + // A width has been specified for the select. + // Make the display frame's width + button frame width = the width specified. + nsHTMLReflowMetrics dropdownDesiredSize(aDesiredSize); + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + // Get unconstrained size of the dropdown list. + nsSize size; + mListControlFrame->GetMaximumSize(size); - NS_RELEASE(context); + // Size the button to be the same height as the displayFrame + SetChildFrameSize(buttonFrame, size.height, size.height); - PRBool status; - aRenderingContext.PopState(status); -} + // Compute display width + buttonFrame->GetRect(buttonRect); + nscoord displayWidth; + displayWidth = firstPassState.computedWidth - buttonRect.width; -NS_METHOD -nsComboboxControlFrame::Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) -{ - if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { - PaintComboboxControl(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + // Set the displayFrame to match the displayWidth computed above + SetChildFrameSize(displayFrame, displayWidth, size.height); + + // Reflow again with the width of the display frame set. + nsAreaFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); + + // Reflow the dropdown list to match the width of the display + button + ReflowComboChildFrame(dropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, aDesiredSize.width, NS_UNCONSTRAINEDSIZE); + } - return NS_OK; -} + + nsRect absoluteTwips; + nsRect absolutePixels; + GetAbsoluteFramePosition(aPresContext, displayFrame, absoluteTwips, absolutePixels); + PositionDropdown(aPresContext, aDesiredSize.height, absoluteTwips, absolutePixels); -//-------------------------------------------------------------- -PRIntn -nsComboboxControlFrame::GetSkipSides() const -{ - return 0; -} + return rv; +} //-------------------------------------------------------------- NS_IMETHODIMP @@ -607,14 +716,12 @@ nsComboboxControlFrame::GetName(nsString* aResult) return result; } -//-------------------------------------------------------------- PRInt32 nsComboboxControlFrame::GetMaxNumValues() { return 1; } -//-------------------------------------------------------------- PRBool nsComboboxControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, nsString* aValues, nsString* aNames) @@ -641,27 +748,6 @@ nsComboboxControlFrame::GetFrameName(nsString& aResult) const } -void -nsComboboxControlFrame::RefreshStyleContext(nsIPresContext* aPresContext, - nsIAtom * aNewContentPseudo, - nsIStyleContext*& aCurrentStyle, - nsIContent * aContent, - nsIStyleContext* aParentStyle) - -{ - nsIStyleContext* newStyleContext; - aPresContext->ProbePseudoStyleContextFor(aContent, - aNewContentPseudo, - aParentStyle, - PR_FALSE, - &newStyleContext); - if (newStyleContext != aCurrentStyle) { - NS_IF_RELEASE(aCurrentStyle); - aCurrentStyle = newStyleContext; - } else { - NS_IF_RELEASE(newStyleContext); - } -} NS_IMETHODIMP nsComboboxControlFrame::ReResolveStyleContext(nsIPresContext* aPresContext, @@ -670,162 +756,83 @@ nsComboboxControlFrame::ReResolveStyleContext(nsIPresContext* aPresContext, nsStyleChangeList* aChangeList, PRInt32* aLocalChange) { + PRInt32 ourChange = aParentChange; + nsresult rv = nsAreaFrame::ReResolveStyleContext(aPresContext, aParentContext, aParentChange, aChangeList, aLocalChange); + + if (NS_FAILED(rv)) { + return rv; + } - // NOTE: using nsFrame's ReResolveStyleContext method to avoid - // useless version in base classes. - PRInt32 ourChange = aParentChange; - nsresult rv = nsHTMLContainerFrame::ReResolveStyleContext(aPresContext, aParentContext, - ourChange, aChangeList, &ourChange); - if (NS_FAILED(rv)) { - return rv; - } - - if (aLocalChange) { + if (aLocalChange) { *aLocalChange = ourChange; - } + } - if (NS_COMFALSE != rv) { - PRInt32 childChange; - PRBool currentIsVisible = (mCurrentStyleContext == mVisibleStyleContext?PR_TRUE:PR_FALSE); - - RefreshStyleContext(aPresContext, nsHTMLAtoms::dropDownVisible, mVisibleStyleContext, mContent, mStyleContext); - - RefreshStyleContext(aPresContext, nsHTMLAtoms::dropDownHidden, mHiddenStyleContext, mContent, mStyleContext); - mCurrentStyleContext = (currentIsVisible?mVisibleStyleContext:mHiddenStyleContext); - - mListFrame->ReResolveStyleContext(aPresContext, - (nsnull != mCurrentStyleContext? mCurrentStyleContext : mStyleContext), - ourChange, aChangeList, &childChange); - - // Button Style - RefreshStyleContext(aPresContext, nsHTMLAtoms::dropDownBtnOut, mBtnOutStyleContext, mContent, mStyleContext); - RefreshStyleContext(aPresContext, nsHTMLAtoms::dropDownBtnPressed, mBtnPressedStyleContext, mContent, mStyleContext); - - //Need to reset the mArrowStyle here, otherwise it might end up pointing - //to memory that has been freed, by the RefreshStyleContext above. - mArrowStyle = mBtnOutStyleContext; - - RefreshStyleContext(aPresContext, nsHTMLAtoms::comboText, mBlockTextStyle, mContent, mStyleContext); - RefreshStyleContext(aPresContext, nsHTMLAtoms::comboTextSelected, mBlockTextSelectedStyle, mContent, mStyleContext); - RefreshStyleContext(aPresContext, nsHTMLAtoms::comboTextSelectedFocus, mBlockTextSelectedFocusStyle, mContent, mStyleContext); - } - - return rv; + if (NS_COMFALSE != rv) { + PRInt32 childChange; + // Update child list + nsIFrame* dropdownFrame = GetDropdownFrame(); + dropdownFrame->ReResolveStyleContext(aPresContext, mStyleContext, ourChange, aChangeList, &childChange); + } + return rv; } -//---------------------------------------------------------------------- -NS_IMETHODIMP nsComboboxControlFrame::HandleEvent(nsIPresContext& aPresContext, - nsGUIEvent* aEvent, - nsEventStatus& aEventStatus) + +nsresult +nsComboboxControlFrame::MouseDown(nsIDOMEvent* aMouseEvent) { - if (aEvent->message == NS_MOUSE_EXIT) { - // If dropdown is visible and we have exited the combo box then leave the - // list up and have the listbox capture all of the mouse events. - if (mCurrentStyleContext == mVisibleStyleContext) { - mListControlFrame->CaptureMouseEvents(PR_TRUE); - } - } - - if (nsEventStatus_eConsumeNoDefault == aEventStatus) { - return NS_OK; - } - - aEventStatus = nsEventStatus_eConsumeNoDefault; - - if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) { - mArrowStyle = mBtnOutStyleContext; - nsFormControlHelper::ForceDrawFrame(this); - } else if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) { - mArrowStyle = mBtnPressedStyleContext; - nsFormControlHelper::ForceDrawFrame(this); - MouseClicked(&aPresContext); - } + ToggleList(mPresContext); return NS_OK; } -//---------------------------------------------------------------------- -NS_IMETHODIMP -nsComboboxControlFrame::GetFrameForPoint(const nsPoint& aPoint, nsIFrame** aFrame) -{ - *aFrame = this; - return NS_OK; -} - - //---------------------------------------------------------------------- // nsIComboboxControlFrame //---------------------------------------------------------------------- NS_IMETHODIMP -nsComboboxControlFrame::SetDropDown(nsIFrame* aPlaceHolderFrame, nsIFrame* aDropDownFrame) +nsComboboxControlFrame::SetDropDown(nsIFrame* aDropDownFrame) { - mPlaceHolderFrame = aPlaceHolderFrame; - mListFrame = aDropDownFrame; - - if (NS_OK != mListFrame->QueryInterface(kIListControlFrameIID, (void**)&mListControlFrame)) { + mDropdownFrame = aDropDownFrame; + + if (NS_OK != mDropdownFrame->QueryInterface(kIListControlFrameIID, (void**)&mListControlFrame)) { return NS_ERROR_FAILURE; } - - // Ok, since we now know we have the ListFrame, and we are assuming at this point it has been initialized - // Let's get the currently selected item, but we make the call using the Interface - mListControlFrame->GetSelectedItem(mTextStr); return NS_OK; } -//-------------------------------------------------------------- -NS_IMETHODIMP -nsComboboxControlFrame::SetDropDownStyleContexts(nsIStyleContext * aVisible, nsIStyleContext * aHidden) -{ - mVisibleStyleContext = aVisible; - mHiddenStyleContext = aHidden; - mCurrentStyleContext = mHiddenStyleContext; - - NS_ADDREF(mVisibleStyleContext); - NS_ADDREF(mHiddenStyleContext); - return NS_OK; -} - -//-------------------------------------------------------------- -NS_IMETHODIMP -nsComboboxControlFrame::SetButtonStyleContexts(nsIStyleContext * aOut, nsIStyleContext * aPressed) -{ - mBtnOutStyleContext = aOut; - mBtnPressedStyleContext = aPressed; - mArrowStyle = aOut; - - NS_ADDREF(mBtnOutStyleContext); - NS_ADDREF(mBtnPressedStyleContext); - return NS_OK; -} - void nsComboboxControlFrame::SelectionChanged() { - // Generate a NS_ONCHANGE event. + if (nsnull != mDisplayContent) { + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, mTextStr, PR_TRUE); + } - //XXX: Todo complete the implementation of selection changed -// nsIViewManager *vm; -// view->GetViewManager(vm); -// nsGUIEvent event; -// event.eventStructType = NS_GUI_EVENT; -// event.widget = this; //XXX: How do I get a widget -// NS_ADDREF(event.widget); -// NS_CONTROL_CHANGE -// InitEvent(event, aMsg); -// vm->DispatchEvent(&event, result); -// NS_RELEASE(event.widget); -// NS_RELEASE(vm); + // Dispatch the NS_FORM_CHANGE event + nsEventStatus status = nsEventStatus_eIgnore; + nsGUIEvent event; + event.eventStructType = NS_GUI_EVENT; + event.widget = nsnull; + event.message = NS_FORM_CHANGE; + // Have the content handle the event. + mContent->HandleDOMEvent(*mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, status); + // Now have the frame handle the event + nsIFrame* frame = nsnull; + nsIFrame* dropdownFrame = GetDropdownFrame(); + nsresult result = dropdownFrame->QueryInterface(kIFrameIID, (void**)&frame); + if ((NS_SUCCEEDED(result)) && (nsnull != frame)) { + frame->HandleEvent(*mPresContext, &event, status); + } + } -//-------------------------------------------------------------- + NS_IMETHODIMP nsComboboxControlFrame::ListWasSelected(nsIPresContext* aPresContext) { - mArrowStyle = mBtnOutStyleContext; - MouseClicked(aPresContext); + ShowList(aPresContext, PR_FALSE); + mListControlFrame->CaptureMouseEvents(PR_FALSE); nsString str; if (nsnull != mListControlFrame) { @@ -833,46 +840,184 @@ nsComboboxControlFrame::ListWasSelected(nsIPresContext* aPresContext) // Check to see if the selection changed if (PR_FALSE == str.Equals(mTextStr)) { mTextStr = str; + //XXX:TODO look at the ordinal position of the selected content in the listbox to tell + // if the selection has changed, rather than looking at the text string. + // There may be more than one item in the dropdown list with the same label. SelectionChanged(); } - nsIFormControlFrame* fcFrame = nsnull; - nsresult result = mListFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); - if ((NS_OK == result) && (nsnull != fcFrame)) { - fcFrame->SetFocus(PR_FALSE, PR_FALSE); - } - SetFocus(PR_TRUE, PR_TRUE); } - - mListControlFrame->CaptureMouseEvents(PR_FALSE); return NS_OK; } -nsresult nsComboboxControlFrame::RequiresWidget(PRBool& aRequiresWidget) +nsresult +nsComboboxControlFrame::RequiresWidget(PRBool& aRequiresWidget) { aRequiresWidget = PR_FALSE; return NS_OK; } -NS_IMETHODIMP nsComboboxControlFrame::SetProperty(nsIAtom* aName, const nsString& aValue) +NS_IMETHODIMP +nsComboboxControlFrame::SetProperty(nsIAtom* aName, const nsString& aValue) { nsIFormControlFrame* fcFrame = nsnull; - nsresult result = mListFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + nsIFrame* dropdownFrame = GetDropdownFrame(); + nsresult result = dropdownFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); if ((NS_SUCCEEDED(result)) && (nsnull != fcFrame)) { return fcFrame->SetProperty(aName, aValue); } return result; } -NS_IMETHODIMP nsComboboxControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) +NS_IMETHODIMP +nsComboboxControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) { nsIFormControlFrame* fcFrame = nsnull; - nsresult result = mListFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + nsIFrame* dropdownFrame = GetDropdownFrame(); + nsresult result = dropdownFrame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); if ((NS_SUCCEEDED(result)) && (nsnull != fcFrame)) { return fcFrame->GetProperty(aName, aValue); } return result; } + +NS_IMETHODIMP +nsComboboxControlFrame::CreateAnonymousContent(nsISupportsArray& aChildList) +{ + // The frames used to display the combo box and the button used to popup the dropdown list + // are created through anonymous content. The dropdown list is not created through anonymous + // content because it's frame is initialized specifically for the drop-down case and it is placed + // a special list referenced through NS_COMBO_FRAME_POPUP_LIST_INDEX to keep separate from the + // layout of the display and button. + // + // Note: The value attribute of the display content is set when an item is selected in the dropdown list. + // If the content specified below does not honor the value attribute than nothing will be displayed. + // In addition, if the frame created by content below for does not implement the nsIFormControlFrame + // interface and honor the SetSuggestedSize method the placement and size of the display area will not + // match what is normally desired for a combobox. + + + // For now the content that is created corresponds to two input buttons. It would be better to create the + // tag as something other than input, but then there isn't any way to create a button frame since it + // isn't possible to set the display type in CSS2 to create a button frame. + + // create content used for display + nsIAtom* tag = NS_NewAtom("input"); + NS_NewHTMLInputElement(&mDisplayContent, tag); + NS_ADDREF(mDisplayContent); + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, nsAutoString("button"), PR_FALSE); + //XXX: Do not use nsHTMLAtoms::id use nsHTMLAtoms::kClass instead. There will end up being multiple + //ids set to the same value which is illegal. + mDisplayContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, nsAutoString("-moz-display"), PR_FALSE); + aChildList.AppendElement(mDisplayContent); + + // create button which drops the list down + tag = NS_NewAtom("input"); + NS_NewHTMLInputElement(&mButtonContent, tag); + NS_ADDREF(mButtonContent); + mButtonContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, nsAutoString("button"), PR_FALSE); + aChildList.AppendElement(mButtonContent); + + // get the reciever interface from the browser button's content node + nsCOMPtr reciever(do_QueryInterface(mButtonContent)); + + // we shouldn't have to unregister this listener because when + // our frame goes away all these content node go away as well + // because our frame is the only one who references them. + reciever->AddEventListenerByIID(this, kIDOMMouseListenerIID); + + // get the reciever interface from the browser button's content node + nsCOMPtr displayReciever(do_QueryInterface(mDisplayContent)); + + // we shouldn't have to unregister this listener because when + // our frame goes away all these content node go away as well + // because our frame is the only one who references them. + displayReciever->AddEventListenerByIID(this, kIDOMMouseListenerIID); + + return NS_OK; +} + +NS_IMETHODIMP +nsComboboxControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight) +{ + return NS_OK; +} + + + +NS_IMETHODIMP +nsComboboxControlFrame::DeleteFrame(nsIPresContext& aPresContext) +{ + // Cleanup frames in popup child list + mPopupFrames.DeleteFrames(aPresContext); + return nsAreaFrame::DeleteFrame(aPresContext); +} + + +NS_IMETHODIMP +nsComboboxControlFrame::FirstChild(nsIAtom* aListName, + nsIFrame** aFirstChild) const +{ + if (nsLayoutAtoms::popupList == aListName) { + *aFirstChild = mPopupFrames.FirstChild(); + } else { + nsAreaFrame::FirstChild(aListName, aFirstChild); + } + return NS_OK; +} + +NS_IMETHODIMP +nsComboboxControlFrame::SetInitialChildList(nsIPresContext& aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList) +{ + nsresult rv = NS_OK; + if (nsLayoutAtoms::popupList == aListName) { + mPopupFrames.SetFrames(aChildList); + } else { + rv = nsAreaFrame::SetInitialChildList(aPresContext, aListName, aChildList); + InitTextStr(PR_FALSE); + } + return rv; +} + +NS_IMETHODIMP +nsComboboxControlFrame::GetAdditionalChildListName(PRInt32 aIndex, + nsIAtom** aListName) const +{ + // Maintain a seperate child list for the dropdown list (i.e. popup listbox) + // This is necessary because we don't want the listbox to be included in the layout + // of the combox's children because it would take up space, when it is suppose to + // be floating above the display. + NS_PRECONDITION(nsnull != aListName, "null OUT parameter pointer"); + if (aIndex <= NS_AREA_FRAME_ABSOLUTE_LIST_INDEX) { + return nsAreaFrame::GetAdditionalChildListName(aIndex, aListName); + } + + *aListName = nsnull; + if (NS_COMBO_FRAME_POPUP_LIST_INDEX == aIndex) { + *aListName = nsLayoutAtoms::popupList; + NS_ADDREF(*aListName); + } + return NS_OK; +} + +PRIntn +nsComboboxControlFrame::GetSkipSides() const +{ + // Don't skip any sides during border rendering + return 0; +} + + + + + + + + + + diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.h b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h index 18249aad5b9..5a411f98d7b 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.h +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h @@ -20,10 +20,12 @@ #define nsComboboxControlFrame_h___ -#include "nsHTMLContainerFrame.h" +#include "nsAreaFrame.h" #include "nsIFormControlFrame.h" #include "nsIComboboxControlFrame.h" - +#include "nsIDOMMouseListener.h" +#include "nsVoidArray.h" +#include "nsIAnonymousContentCreator.h" class nsButtonControlFrame; class nsTextControlFrame; @@ -33,19 +35,36 @@ class nsStyleContext; class nsIHTMLContent; class nsIListControlFrame; -class nsComboboxControlFrame : public nsHTMLContainerFrame, +/** + * Child list name indices + * @see #GetAdditionalChildListName() + */ +#define NS_COMBO_FRAME_POPUP_LIST_INDEX (NS_AREA_FRAME_ABSOLUTE_LIST_INDEX + 1) + +class nsComboboxControlFrame : public nsAreaFrame, public nsIFormControlFrame, - public nsIComboboxControlFrame + public nsIComboboxControlFrame, + public nsIDOMMouseListener, + public nsIAnonymousContentCreator { public: nsComboboxControlFrame(); ~nsComboboxControlFrame(); + // nsISupports NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + + // nsIAnonymousContentCreator + NS_IMETHOD CreateAnonymousContent(nsISupportsArray& aChildList); + + // nsIFrame + NS_IMETHOD Init(nsIPresContext& aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow); - // nsIFrame - NS_IMETHOD Reflow(nsIPresContext& aCX, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, @@ -57,45 +76,31 @@ public: nsStyleChangeList* aChangeList, PRInt32* aLocalChange); - NS_IMETHOD Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); - - NS_IMETHOD HandleEvent(nsIPresContext& aPresContext, - nsGUIEvent* aEvent, - nsEventStatus& aEventStatus); - NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD DeleteFrame(nsIPresContext& aPresContext); + NS_IMETHOD FirstChild(nsIAtom* aListName, nsIFrame** aFirstChild) const; + NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList); + NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex, + nsIAtom** aListName) const; - - virtual PRInt32 GetMaxNumValues(); - - virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames); - - // nsIFormControLFrame + // nsIFormControlFrame + NS_IMETHOD SetSuggestedSize(nscoord aWidth, nscoord aHeight); + NS_IMETHOD GetName(nsString* aName); + NS_IMETHOD GetType(PRInt32* aType) const; NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); void SetFocus(PRBool aOn, PRBool aRepaint); - virtual void PostCreateWidget(nsIPresContext* aPresContext, nscoord& aWidth, nscoord& aHeight); - - - //nsTextControlFrame* GetTextFrame() { return mTextFrame; } - - //void SetTextFrame(nsTextControlFrame* aFrame) { mTextFrame = aFrame; } - - //nsButtonControlFrame* GetBrowseFrame() { return mBrowseFrame; } - //void SetBrowseFrame(nsButtonControlFrame* aFrame) { mBrowseFrame = aFrame; } virtual PRBool IsSuccessful(nsIFormControlFrame* aSubmitter); virtual void SetFormFrame(nsFormFrame* aFormFrame) { mFormFrame = aFormFrame; } virtual void Reset(); - NS_IMETHOD GetName(nsString* aName); - NS_IMETHOD GetType(PRInt32* aType) const; - + virtual PRInt32 GetMaxNumValues(); + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); NS_IMETHOD GetFont(nsIPresContext* aPresContext, nsFont& aFont); NS_IMETHOD GetFormContent(nsIContent*& aContent) const; @@ -107,69 +112,73 @@ public: float aPixToTwip, nscoord aInnerWidth, nscoord aCharWidth) const; - - virtual nsresult RequiresWidget(PRBool &aRequiresWidget); - - - NS_IMETHOD GetFrameForPoint(const nsPoint& aPoint, nsIFrame** aFrame); - - // A Static Helper Functions - - // This refreshes a particular pseudo style content when a "ReResolveStyleContent" happens - static void RefreshStyleContext(nsIPresContext* aPresContext, - nsIAtom * aNewContentPseudo, - nsIStyleContext*& aCurrentStyle, - nsIContent * aContent, - nsIStyleContext* aParentStyle); - // nsIFormMouseListener virtual void MouseClicked(nsIPresContext* aPresContext); //nsIComboboxControlFrame - NS_IMETHOD SetDropDown(nsIFrame* aPlaceHolderFrame, nsIFrame* aDropDownFrame); - NS_IMETHOD SetDropDownStyleContexts(nsIStyleContext * aVisible, nsIStyleContext * aHidden); - NS_IMETHOD SetButtonStyleContexts(nsIStyleContext * aOut, nsIStyleContext * aPressed); + NS_IMETHOD SetDropDown(nsIFrame* aDropDownFrame); NS_IMETHOD ListWasSelected(nsIPresContext* aPresContext); + //nsIDOMEventListener + virtual nsresult MouseDown(nsIDOMEvent* aMouseEvent); + virtual nsresult MouseUp(nsIDOMEvent* aMouseEvent) { return NS_OK; } + virtual nsresult MouseClick(nsIDOMEvent* aMouseEvent) { printf("mouse clock\n"); return NS_OK; }; + virtual nsresult MouseDblClick(nsIDOMEvent* aMouseEvent) { return NS_OK; } + virtual nsresult MouseOver(nsIDOMEvent* aMouseEvent) { return NS_OK; } + virtual nsresult MouseOut(nsIDOMEvent* aMouseEvent) { return NS_OK; } + virtual nsresult HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; } -protected: - virtual void PaintComboboxControl(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); +protected: + + // nsHTMLContainerFrame virtual PRIntn GetSkipSides() const; - void InitTextStr(); + + // Utilities + nsresult ReflowComboChildFrame(nsIFrame* aFrame, + nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus, + nscoord aAvailableWidth, + nscoord aAvailableHeight); + + nsresult GetScreenHeight(nsIPresContext& aPresContext, nscoord& aHeight); + nsresult PositionDropdown(nsIPresContext& aPresContext, + nscoord aHeight, + nsRect aAbsoluteTwipsRect, + nsRect aAbsolutePixelRect); + nsresult GetAbsoluteFramePosition(nsIPresContext& aPresContext, + nsIFrame *aFrame, + nsRect& aAbsoluteTwipsRect, + nsRect& aAbsolutePixelRect); + void ToggleList(nsIPresContext* aPresContext); + void ShowPopup(PRBool aShowPopup); + void ShowList(nsIPresContext* aPresContext, PRBool aShowList); + void SetChildFrameSize(nsIFrame* aFrame, nscoord aWidth, nscoord aHeight); + void InitTextStr(PRBool aUpdate); + nsresult GetPrimaryComboFrame(nsIPresContext& aPresContext, nsIContent* aContent, nsIFrame** aFrame); + nsIFrame* GetButtonFrame(nsIPresContext& aPresContext); + nsIFrame* GetDisplayFrame(nsIPresContext& aPresContext); + nsIFrame* GetDropdownFrame(); + + // Called when the selection has changed. If the the same item in the list is selected + // it is NOT called. void SelectionChanged(); + nsFrameList mPopupFrames; // additional named child list + nsIPresContext* mPresContext; // XXX: Remove the need to cache the pres context. nsFormFrame* mFormFrame; // Parent Form Frame - nsIFrame * mPlaceHolderFrame; - nsIFrame * mListFrame; // Generic nsIFrame - nsIListControlFrame * mListControlFrame; // Specific ListControl Interface - nsRect mButtonRect; // The Arrow Button's Rect cached for Painting - - // DropDown List Visibility Styles - nsIStyleContext * mVisibleStyleContext; // Style for the DropDown List to make it visible - nsIStyleContext * mHiddenStyleContext; // Style for the DropDown List to make it hidden - nsIStyleContext * mCurrentStyleContext; // The current Style state of the DropDown List - - // Arrow Button Styles - nsIStyleContext * mBtnOutStyleContext; // Style when not pressed - nsIStyleContext * mBtnPressedStyleContext; // Style When Pressed - nsIStyleContext * mArrowStyle; // Arrows currrent style (for painting) - - // Combobox Text Styles - nsIStyleContext * mBlockTextStyle; // Style when there is no selection and it doesn't have focus - nsIStyleContext * mBlockTextSelectedStyle; // Style when selected and it doesn't have focus - nsIStyleContext * mBlockTextSelectedFocusStyle; // Style when selected and it has focus - - PRBool mFirstTime; - - // State data members - nsString mTextStr; - PRBool mGotFocus; + nsString mTextStr; // Current Combo box selection + nsIHTMLContent* mDisplayContent; // Anonymous content used to display the current selection + nsIHTMLContent* mButtonContent; // Anonymous content used to popup the dropdown list + PRBool mDroppedDown; // Current state of the dropdown list, PR_TRUE is dropped down + nsIFrame* mDisplayFrame; // frame to display selection + nsIFrame* mButtonFrame; // button frame + nsIFrame* mDropdownFrame; // dropdown list frame + nsIListControlFrame * mListControlFrame; // ListControl Interface for the dropdown frame private: NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } diff --git a/mozilla/layout/html/forms/src/nsFileControlFrame.cpp b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp index b851e9005de..d21f30f0642 100644 --- a/mozilla/layout/html/forms/src/nsFileControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp @@ -70,6 +70,8 @@ NS_NewFileControlFrame(nsIFrame** aNewFrame) nsFileControlFrame::nsFileControlFrame():mTextFrame(nsnull), mFormFrame(nsnull) { + //Shrink the area around it's contents + SetFlags(NS_BLOCK_SHRINK_WRAP); } NS_IMETHODIMP diff --git a/mozilla/layout/html/forms/src/nsFileControlFrame.h b/mozilla/layout/html/forms/src/nsFileControlFrame.h index ad04d5611a8..eef454d3327 100644 --- a/mozilla/layout/html/forms/src/nsFileControlFrame.h +++ b/mozilla/layout/html/forms/src/nsFileControlFrame.h @@ -50,7 +50,6 @@ public: // nsIFormControlFrame NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); - NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); NS_IMETHOD Reflow(nsIPresContext& aCX, @@ -59,6 +58,7 @@ public: nsReflowStatus& aStatus); NS_IMETHOD GetFrameName(nsString& aResult) const; + NS_IMETHOD SetSuggestedSize(nscoord aWidth, nscoord aHeight) { return NS_OK; }; virtual PRInt32 GetMaxNumValues(); diff --git a/mozilla/layout/html/forms/src/nsFormControlFrame.cpp b/mozilla/layout/html/forms/src/nsFormControlFrame.cpp index 4e66e5f974a..7c6b6ac783b 100644 --- a/mozilla/layout/html/forms/src/nsFormControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFormControlFrame.cpp @@ -67,6 +67,8 @@ nsFormControlFrame::nsFormControlFrame() mDidInit = PR_FALSE; mWidget = nsnull; mFormFrame = nsnull; + mSuggestedWidth = NS_FORMSIZE_NOTSET; + mSuggestedHeight = NS_FORMSIZE_NOTSET; } nsFormControlFrame::~nsFormControlFrame() @@ -735,3 +737,10 @@ nsresult nsFormControlFrame::RequiresWidget(PRBool & aRequiresWidget) } +NS_IMETHODIMP nsFormControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight) +{ + mSuggestedWidth = aWidth; + mSuggestedHeight = aHeight; + return NS_OK; +} + diff --git a/mozilla/layout/html/forms/src/nsFormControlFrame.h b/mozilla/layout/html/forms/src/nsFormControlFrame.h index dd21114c59e..b68bc0979b5 100644 --- a/mozilla/layout/html/forms/src/nsFormControlFrame.h +++ b/mozilla/layout/html/forms/src/nsFormControlFrame.h @@ -36,6 +36,8 @@ class nsFormFrame; #define CSS_NOTSET -1 #define ATTR_NOTSET -1 +#define NS_FORMSIZE_NOTSET -1 + /** * nsFormControlFrame is the base class for frames of form controls. It * provides a uniform way of creating widgets, resizing, and painting. @@ -227,6 +229,8 @@ protected: nsHTMLReflowMetrics& aDesiredLayoutSize, nsSize& aDesiredWidgetSize); + NS_IMETHOD nsFormControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight); + // //------------------------------------------------------------------------------------- // Utility methods for managing checkboxes and radiobuttons @@ -274,6 +278,8 @@ protected: PRBool mDidInit; nsPoint mLastClickPoint; nsFormFrame* mFormFrame; + nscoord mSuggestedWidth; + nscoord mSuggestedHeight; private: NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } diff --git a/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.cpp b/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.cpp index 4af6f406631..ba199cbceb2 100644 --- a/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.cpp @@ -592,6 +592,13 @@ nsHTMLButtonControlFrame::ReResolveStyleContext ( nsIPresContext* aPresContext, } // ReResolveStyleContext +NS_IMETHODIMP nsHTMLButtonControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight) +{ +// mSuggestedWidth = aWidth; +// mSuggestedHeight = aHeight; + return NS_OK; +} + diff --git a/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.h b/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.h index a51107f7f8c..e8c5a3c3884 100644 --- a/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.h +++ b/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.h @@ -131,6 +131,7 @@ public: // nsIFormControlFrame NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); + NS_IMETHOD SetSuggestedSize(nscoord aWidth, nscoord aHeight); protected: NS_IMETHOD_(nsrefcnt) AddRef(void); diff --git a/mozilla/layout/html/forms/src/nsImageControlFrame.cpp b/mozilla/layout/html/forms/src/nsImageControlFrame.cpp index b659bf1837c..5847fee0c5c 100644 --- a/mozilla/layout/html/forms/src/nsImageControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsImageControlFrame.cpp @@ -117,6 +117,7 @@ public: // nsIFormControlFrame NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); + NS_IMETHOD SetSuggestedSize(nscoord aWidth, nscoord aHeight); protected: void GetTranslatedRect(nsRect& aRect); // XXX this implementation is a copy of nsHTMLButtonControlFrame @@ -452,3 +453,10 @@ NS_IMETHODIMP nsImageControlFrame::GetProperty(nsIAtom* aName, nsString& aValue) { return NS_OK; } + +NS_IMETHODIMP nsImageControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight) +{ +// mSuggestedWidth = aWidth; +// mSuggestedHeight = aHeight; + return NS_OK; +} \ No newline at end of file diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.cpp b/mozilla/layout/html/forms/src/nsListControlFrame.cpp index 8f121a517df..8fc1c86149e 100644 --- a/mozilla/layout/html/forms/src/nsListControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsListControlFrame.cpp @@ -37,7 +37,7 @@ #include "nsIReflowCommand.h" // Constants -const nscoord kMaxDropDownRows = 20; // This matches the setting for 4.x browsers +const nscoord kMaxDropDownRows = 20; // This matches the setting for 4.x browsers const PRInt32 kNothingSelected = -1; const PRInt32 kMaxZ= 0x7fffffff; //XXX: Shouldn't there be a define somewhere for MaxInt for PRInt32 @@ -54,7 +54,6 @@ static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID); static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); -//---------------------------------------------------------------------- nsresult NS_NewListControlFrame(nsIFrame** aNewFrame) @@ -71,7 +70,7 @@ NS_NewListControlFrame(nsIFrame** aNewFrame) return NS_OK; } -//---------------------------------------------------------------------- + nsListControlFrame::nsListControlFrame() { mHitFrame = nsnull; @@ -83,20 +82,20 @@ nsListControlFrame::nsListControlFrame() mDisplayed = PR_FALSE; mButtonDown = PR_FALSE; mLastFrame = nsnull; + mMaxWidth = 0; + mMaxHeight = 0; + mIsCapturingMouseEvents = PR_FALSE; } -//---------------------------------------------------------------------- nsListControlFrame::~nsListControlFrame() { mComboboxFrame = nsnull; mFormFrame = nsnull; } -//---------------------------------------------------------------------- NS_IMPL_ADDREF(nsListControlFrame) NS_IMPL_RELEASE(nsListControlFrame) -//---------------------------------------------------------------------- NS_IMETHODIMP nsListControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) { @@ -108,7 +107,6 @@ nsListControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) return NS_OK; } if (aIID.Equals(kIListControlFrameIID)) { - NS_ADDREF_THIS(); // Increase reference count for caller *aInstancePtr = (void *)((nsIListControlFrame*)this); return NS_OK; } @@ -116,7 +114,7 @@ nsListControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) return nsScrollFrame::QueryInterface(aIID, aInstancePtr); } -//---------------------------------------------------------------------- + NS_IMETHODIMP nsListControlFrame::GetFrameForPoint(const nsPoint& aPoint, nsIFrame** aFrame) { @@ -147,7 +145,7 @@ nsListControlFrame::GetFrameForPoint(const nsPoint& aPoint, nsIFrame** aFrame) } -//---------------------------------------------------------------------- + nsresult nsListControlFrame::GetFrameForPointUsing(const nsPoint& aPoint, nsIAtom* aList, @@ -194,7 +192,7 @@ nsListControlFrame::GetFrameForPointUsing(const nsPoint& aPoint, scrollableView->GetScrollPosition(offsetx, offsety); tmp.x += offsetx; tmp.y += offsety; - // Note: scrollableView is not ref counted so it's interface is not NS_RELEASE'd + // Note: scrollableView is not ref counted } } @@ -238,14 +236,13 @@ nsListControlFrame::GetFrameForPointUsing(const nsPoint& aPoint, } *aFrame = this; return NS_ERROR_FAILURE; - + } -//---------------------------------------------------------------------- // Reflow is overriden to constrain the listbox height to the number of rows and columns // specified. -// + NS_IMETHODIMP nsListControlFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -284,10 +281,9 @@ nsListControlFrame::Reflow(nsIPresContext& aPresContext, nsSize scrolledAreaSize(0,0); nsHTMLReflowMetrics scrolledAreaDesiredSize(&scrolledAreaSize); + if (eReflowReason_Incremental == firstPassState.reason) { - //XXX: Why do we have to change the reflow type in this - //case? If we don't an assert in the nsScrollFrame::Reflow prevents - //execution from continuing. Is the assertion in nsScrollFrame bogus? + // When incremental, Reflow everything nsIFrame* targetFrame; firstPassState.reflowCommand->GetTarget(targetFrame); if (this == targetFrame) { @@ -308,6 +304,8 @@ nsListControlFrame::Reflow(nsIPresContext& aPresContext, nscoord scrolledAreaWidth = scrolledAreaDesiredSize.maxElementSize->width; nscoord scrolledAreaHeight = scrolledAreaDesiredSize.height; + mMaxWidth = scrolledAreaWidth; + mMaxHeight = scrolledAreaDesiredSize.maxElementSize->height; // The first reflow produces a box with the scrollbar width and borders // added in so we need to subtract them out. @@ -342,20 +340,12 @@ nsListControlFrame::Reflow(nsIPresContext& aPresContext, nscoord visibleWidth = 0; if (IsInDropDownMode() == PR_TRUE) { - // Always set the width to be - // XXX: TODO The width of the list should be passed in so it can - // be set to the same as the text box + dropdown arrow. - visibleWidth = scrolledAreaWidth; - if (nsnull != mComboboxFrame) { - nsRect comboRect; - nsIFrame *comboFrame = nsnull; - if (NS_SUCCEEDED(mComboboxFrame->QueryInterface(kIFrameIID, (void **)&comboFrame))) { - comboFrame->GetRect(comboRect); - visibleWidth = comboRect.width; - visibleWidth -= (border.left + border.right); - } - } - + // Calculate visible width for dropdown + if (NS_UNCONSTRAINEDSIZE == aReflowState.computedWidth) { + visibleWidth = scrolledAreaWidth; + } else { + visibleWidth = aReflowState.computedWidth - (border.left + border.right); + } } else { if (NS_UNCONSTRAINEDSIZE == aReflowState.computedWidth) { visibleWidth = scrolledAreaWidth; @@ -364,11 +354,11 @@ nsListControlFrame::Reflow(nsIPresContext& aPresContext, } } - // Determine if a scrollbar will be needed, If so we need to add - // enough the width to allow for the scrollbar. - // The scrollbar will be needed under two conditions: - // (size * heightOfaRow) < scrolledAreaHeight or - // the height set through Style < scrolledAreaHeight. + // Determine if a scrollbar will be needed, If so we need to add + // enough the width to allow for the scrollbar. + // The scrollbar will be needed under two conditions: + // (size * heightOfaRow) < scrolledAreaHeight or + // the height set through Style < scrolledAreaHeight. // Calculate the height of a single row in the listbox or dropdown list // Note: It is calculated based on what layout returns for the maxElement @@ -428,7 +418,6 @@ nsListControlFrame::Reflow(nsIPresContext& aPresContext, return NS_OK; } -//-------------------------------------------------------------- NS_IMETHODIMP nsListControlFrame::GetFormContent(nsIContent*& aContent) const { @@ -440,7 +429,7 @@ nsListControlFrame::GetFormContent(nsIContent*& aContent) const return rv; } -//-------------------------------------------------------------- + NS_IMETHODIMP nsListControlFrame::GetFont(nsIPresContext* aPresContext, nsFont& aFont) @@ -450,7 +439,8 @@ nsListControlFrame::GetFont(nsIPresContext* aPresContext, } -PRBool nsListControlFrame::IsOptionElement(nsIContent* aContent) +PRBool +nsListControlFrame::IsOptionElement(nsIContent* aContent) { PRBool result = PR_FALSE; @@ -466,7 +456,8 @@ PRBool nsListControlFrame::IsOptionElement(nsIContent* aContent) } -PRBool nsListControlFrame::IsOptionElementFrame(nsIFrame *aFrame) +PRBool +nsListControlFrame::IsOptionElementFrame(nsIFrame *aFrame) { nsIContent *content = nsnull; aFrame->GetContent(&content); @@ -482,7 +473,8 @@ PRBool nsListControlFrame::IsOptionElementFrame(nsIFrame *aFrame) // Go up the frame tree looking for the first ancestor that has content // which is selectable -nsIFrame *nsListControlFrame::GetSelectableFrame(nsIFrame *aFrame) +nsIFrame * +nsListControlFrame::GetSelectableFrame(nsIFrame *aFrame) { nsIFrame* selectedFrame = aFrame; @@ -494,7 +486,8 @@ nsIFrame *nsListControlFrame::GetSelectableFrame(nsIFrame *aFrame) return(selectedFrame); } -void nsListControlFrame::ForceRedraw() +void +nsListControlFrame::ForceRedraw() { //XXX: Hack. This should not be needed. The problem is DisplaySelected //and DisplayDeselected set and unset an attribute on generic HTML content @@ -508,11 +501,12 @@ void nsListControlFrame::ForceRedraw() // XXX: Here we introduce a new -moz-option-selected attribute so a attribute // selecitor n the ua.css can change the style when the option is selected. -void nsListControlFrame::DisplaySelected(nsIContent* aContent) +void +nsListControlFrame::DisplaySelected(nsIContent* aContent) { //XXX: This is temporary. It simulates psuedo states by using a attribute selector on // -moz-option-selected in the ua.css style sheet. This will not be needed when - // The event state manager is functional. KMM + // The event state manager supports selected states. KMM nsCOMPtr selectedAtom ( dont_QueryInterface(NS_NewAtom(kMozSelected))); if (PR_TRUE == mDisplayed) { @@ -523,7 +517,8 @@ void nsListControlFrame::DisplaySelected(nsIContent* aContent) } } -void nsListControlFrame::DisplayDeselected(nsIContent* aContent) +void +nsListControlFrame::DisplayDeselected(nsIContent* aContent) { //XXX: This is temporary. It simulates psuedo states by using a attribute selector on // -moz-option-selected in the ua.css style sheet. This will not be needed when @@ -540,8 +535,9 @@ void nsListControlFrame::DisplayDeselected(nsIContent* aContent) } -//---------------------------------------------------------------------- -PRInt32 nsListControlFrame::GetSelectedIndex(nsIFrame *aHitFrame) + +PRInt32 +nsListControlFrame::GetSelectedIndex(nsIFrame *aHitFrame) { PRInt32 index = kNothingSelected; // Get the content of the frame that was selected @@ -575,19 +571,20 @@ PRInt32 nsListControlFrame::GetSelectedIndex(nsIFrame *aHitFrame) return index; } -//---------------------------------------------------------------------- -void nsListControlFrame::ClearSelection() + +void +nsListControlFrame::ClearSelection() { PRUint32 length = GetNumberOfOptions(); - for (PRInt32 i = 0; i < (PRInt32)length; i++) { - if (i != mSelectedIndex) { - SetFrameSelected(i, PR_FALSE); - } - } + for (PRInt32 i = 0; i < (PRInt32)length; i++) { + if (i != mSelectedIndex) { + SetFrameSelected(i, PR_FALSE); + } + } } -//---------------------------------------------------------------------- -void nsListControlFrame::ExtendedSelection(PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aDoInvert, PRBool aSetValue) +void +nsListControlFrame::ExtendedSelection(PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aDoInvert, PRBool aSetValue) { PRInt32 startInx; PRInt32 endInx; @@ -621,7 +618,8 @@ void nsListControlFrame::ExtendedSelection(PRInt32 aStartIndex, PRInt32 aEndInde } } -void nsListControlFrame::SingleSelection() +void +nsListControlFrame::SingleSelection() { if (nsnull != mHitFrame) { // Store previous selection @@ -644,7 +642,8 @@ void nsListControlFrame::SingleSelection() } } -void nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) +void +nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) { if (nsnull != mHitFrame) { mSelectedIndex = (PRInt32)GetSelectedIndex(mHitFrame); @@ -696,15 +695,13 @@ void nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) ClearSelection(); } } - - //XXX Fix this mHitContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, (selected?kSelectedFocus:kNormal), PR_TRUE); } - } -void nsListControlFrame::HandleListSelection(nsIPresContext& aPresContext, - nsGUIEvent* aEvent, - nsEventStatus& aEventStatus) +void +nsListControlFrame::HandleListSelection(nsIPresContext& aPresContext, + nsGUIEvent* aEvent, + nsEventStatus& aEventStatus) { if (mMultipleSelections) { MultipleSelection(((nsMouseEvent *)aEvent)->isShift, ((nsMouseEvent *)aEvent)->isControl); @@ -713,7 +710,8 @@ void nsListControlFrame::HandleListSelection(nsIPresContext& aPresContext, } } -PRBool nsListControlFrame::HasSameContent(nsIFrame* aFrame1, nsIFrame* aFrame2) +PRBool +nsListControlFrame::HasSameContent(nsIFrame* aFrame1, nsIFrame* aFrame2) { // Quick check, if the frames are equal they must have // the same content @@ -735,8 +733,8 @@ PRBool nsListControlFrame::HasSameContent(nsIFrame* aFrame1, nsIFrame* aFrame2) } -//---------------------------------------------------------------------- -NS_IMETHODIMP nsListControlFrame::HandleLikeListEvent(nsIPresContext& aPresContext, +nsresult +nsListControlFrame::HandleLikeListEvent(nsIPresContext& aPresContext, nsGUIEvent* aEvent, nsEventStatus& aEventStatus) { @@ -762,6 +760,7 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeListEvent(nsIPresContext& aPresConte NS_IMETHODIMP nsListControlFrame :: CaptureMouseEvents(PRBool aGrabMouseEvents) { + // get its view nsIView* view = nsnull; GetView(&view); @@ -773,8 +772,10 @@ nsListControlFrame :: CaptureMouseEvents(PRBool aGrabMouseEvents) if (viewMan) { if (aGrabMouseEvents) { viewMan->GrabMouseEvents(view,result); + mIsCapturingMouseEvents = PR_TRUE; } else { viewMan->GrabMouseEvents(nsnull,result); + mIsCapturingMouseEvents = PR_FALSE; } } } @@ -782,7 +783,8 @@ nsListControlFrame :: CaptureMouseEvents(PRBool aGrabMouseEvents) return NS_OK; } -nsIView* nsListControlFrame::GetViewFor(nsIWidget* aWidget) +nsIView* +nsListControlFrame::GetViewFor(nsIWidget* aWidget) { nsIView* view = nsnull; void* clientData; @@ -799,7 +801,8 @@ nsIView* nsListControlFrame::GetViewFor(nsIWidget* aWidget) // Determine if a view is an ancestor of another view. -PRBool nsListControlFrame::IsAncestor(nsIView* aAncestor, nsIView* aChild) +PRBool +nsListControlFrame::IsAncestor(nsIView* aAncestor, nsIView* aChild) { nsIView* view = aChild; while (nsnull != view) { @@ -814,10 +817,11 @@ PRBool nsListControlFrame::IsAncestor(nsIView* aAncestor, nsIView* aChild) return(PR_FALSE); } -//---------------------------------------------------------------------- -NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aPresContext, - nsGUIEvent* aEvent, - nsEventStatus& aEventStatus) + +nsresult +nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aPresContext, + nsGUIEvent* aEvent, + nsEventStatus& aEventStatus) { if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) { if (nsnull == mHitFrame) { @@ -883,12 +887,14 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aP return NS_OK; } -//---------------------------------------------------------------------- -NS_IMETHODIMP nsListControlFrame::HandleEvent(nsIPresContext& aPresContext, + +NS_IMETHODIMP +nsListControlFrame::HandleEvent(nsIPresContext& aPresContext, nsGUIEvent* aEvent, nsEventStatus& aEventStatus) { -/* const char * desc[] = {"NS_MOUSE_MOVE", +/* + const char * desc[] = {"NS_MOUSE_MOVE", "NS_MOUSE_LEFT_BUTTON_UP", "NS_MOUSE_LEFT_BUTTON_DOWN", "","","","","","","", @@ -910,8 +916,8 @@ NS_IMETHODIMP nsListControlFrame::HandleEvent(nsIPresContext& aPresContext, printf("Mouse in ListFrame %s [%d]\n", desc[inx], aEvent->message); } else { printf("Mouse in ListFrame [%d]\n", aEvent->message); - }*/ - + } +*/ if (nsEventStatus_eConsumeNoDefault == aEventStatus) { return NS_OK; } @@ -930,7 +936,7 @@ NS_IMETHODIMP nsListControlFrame::HandleEvent(nsIPresContext& aPresContext, return NS_OK; } -//---------------------------------------------------------------------- + NS_IMETHODIMP nsListControlFrame::SetInitialChildList(nsIPresContext& aPresContext, nsIAtom* aListName, @@ -945,7 +951,7 @@ nsListControlFrame::SetInitialChildList(nsIPresContext& aPresContext, return nsScrollFrame::SetInitialChildList(aPresContext, aListName, aChildList); } -//---------------------------------------------------------------------- + NS_IMETHODIMP nsListControlFrame::Init(nsIPresContext& aPresContext, nsIContent* aContent, @@ -977,7 +983,7 @@ nsListControlFrame::Init(nsIPresContext& aPresContext, return result; } -//---------------------------------------------------------------------- + nscoord nsListControlFrame::GetVerticalInsidePadding(float aPixToTwip, nscoord aInnerHeight) const @@ -985,7 +991,7 @@ nsListControlFrame::GetVerticalInsidePadding(float aPixToTwip, return NSIntPixelsToTwips(0, aPixToTwip); } -//---------------------------------------------------------------------- + nscoord nsListControlFrame::GetHorizontalInsidePadding(nsIPresContext& aPresContext, float aPixToTwip, @@ -996,7 +1002,6 @@ nsListControlFrame::GetHorizontalInsidePadding(nsIPresContext& aPresContext, } -//---------------------------------------------------------------------- NS_IMETHODIMP nsListControlFrame::GetMultiple(PRBool* aMultiple, nsIDOMHTMLSelectElement* aSelect) { @@ -1013,7 +1018,7 @@ nsListControlFrame::GetMultiple(PRBool* aMultiple, nsIDOMHTMLSelectElement* aSel } } -//---------------------------------------------------------------------- + nsIDOMHTMLSelectElement* nsListControlFrame::GetSelect(nsIContent * aContent) { @@ -1026,7 +1031,7 @@ nsListControlFrame::GetSelect(nsIContent * aContent) } } -//---------------------------------------------------------------------- + NS_IMETHODIMP nsListControlFrame::AboutToDropDown() { @@ -1034,7 +1039,6 @@ nsListControlFrame::AboutToDropDown() return(SyncViewWithFrame()); } - nsIContent* nsListControlFrame::GetOptionAsContent(nsIDOMHTMLCollection* aCollection,PRUint32 aIndex) { @@ -1101,7 +1105,6 @@ nsListControlFrame::SetFrameSelected(PRUint32 aIndex, PRBool aSelected) NS_IF_RELEASE(content); } -//---------------------------------------------------------------------- void nsListControlFrame::InitializeFromContent() { @@ -1127,7 +1130,7 @@ nsListControlFrame::InitializeFromContent() } -//---------------------------------------------------------------------- + nsIDOMHTMLCollection* nsListControlFrame::GetOptions(nsIContent * aContent, nsIDOMHTMLSelectElement* aSelect) { @@ -1147,7 +1150,6 @@ nsListControlFrame::GetOptions(nsIContent * aContent, nsIDOMHTMLSelectElement* a } } -//---------------------------------------------------------------------- nsIDOMHTMLOptionElement* nsListControlFrame::GetOption(nsIDOMHTMLCollection& aCollection, PRUint32 aIndex) { @@ -1163,7 +1165,7 @@ nsListControlFrame::GetOption(nsIDOMHTMLCollection& aCollection, PRUint32 aIndex return nsnull; } -//---------------------------------------------------------------------- + PRBool nsListControlFrame::GetOptionValue(nsIDOMHTMLCollection& aCollection, PRUint32 aIndex, nsString& aValue) { @@ -1184,36 +1186,27 @@ nsListControlFrame::GetOptionValue(nsIDOMHTMLCollection& aCollection, PRUint32 a return status; } -//---------------------------------------------------------------------- -NS_IMETHODIMP +nsresult nsListControlFrame::Deselect() { PRInt32 i; PRInt32 max = GetNumberOfOptions(); for (i=0;iQueryInterface(kIDOMHTMLSelectElementIID, (void**)&dselect); - if (NS_OK == result) { - result = dselect->GetSize(&size); + nsresult result = aContent->QueryInterface(kIDOMHTMLSelectElementIID, (void**)&select); + if (NS_SUCCEEDED(result)) { + result = select->GetSize(&size); if ((1 == size) || (kNoSizeSpecified == size)) { - // Construct a frame-based combo box - nsIFrame * comboboxFrame; - rv = NS_NewComboboxControlFrame(&comboboxFrame); + // Construct a frame-based combo box. + // The frame-based combo box is built out of tree parts. A display area, a button and + // a dropdown list. The display area and button are created through anonymous content. + // The drop-down list's frame is created explicitly. The combobox frame shares it's content + // with the drop-down list. + nsIFrame * comboboxFrame; + rv = NS_NewComboboxControlFrame(&comboboxFrame); - nsIFrame* geometricParent = aParentFrame; - if (aIsAbsolutelyPositioned) { - geometricParent = aState.mAbsoluteItems.containingBlock; - } else if (aIsFixedPositioned) { - geometricParent = aState.mFixedItems.containingBlock; + // Determine geometric parent for the combobox frame + nsIFrame* geometricParent = aParentFrame; + if (aIsAbsolutelyPositioned) { + geometricParent = aState.mAbsoluteItems.containingBlock; + } else if (aIsFixedPositioned) { + geometricParent = aState.mFixedItems.containingBlock; + } + // Initialize the combobox frame + comboboxFrame->Init(*aPresContext, aContent, geometricParent, aStyleContext, nsnull); + nsIComboboxControlFrame* comboBox = nsnull; + if (NS_SUCCEEDED(comboboxFrame->QueryInterface(kIComboboxControlFrameIID, (void**)&comboBox))) { + // Create a listbox + nsIFrame * listFrame; + rv = NS_NewListControlFrame(&listFrame); + + // Notify the listbox that it is being used as a dropdown list. + nsIListControlFrame * listControlFrame; + if (NS_SUCCEEDED(listFrame->QueryInterface(kIListControlFrameIID, (void**)&listControlFrame))) { + listControlFrame->SetComboboxFrame(comboboxFrame); } - - comboboxFrame->Init(*aPresContext, aContent, geometricParent, aStyleContext, nsnull); - nsIComboboxControlFrame* comboBox = nsnull; - if (NS_OK == comboboxFrame->QueryInterface(kIComboboxControlFrameIID, (void**)&comboBox)) { - nsIFrame * listFrame; - rv = NS_NewListControlFrame(&listFrame); - - // Get the style context that has been set for the combo box so it can be passed used - // to create the style context's for the drop down list. - nsIStyleContext* comboStyleContext; - comboboxFrame->GetStyleContext(&comboStyleContext); - - // This is important to do before it is initialized - // it tells it that it is in "DropDown Mode" - nsIListControlFrame * listControlFrame; - if (NS_OK == listFrame->QueryInterface(kIListControlFrameIID, (void**)&listControlFrame)) { - listControlFrame->SetComboboxFrame(comboboxFrame); - } - - //XXX: TODO: Make sure that a failure to resolve the following - //pseudo style will still work. - - // Set up the Pseudo Style contents - - // Dropdown list style - nsCOMPtr listStyle; - aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::dropDownList, comboStyleContext, PR_FALSE, - getter_AddRefs(listStyle)); + // Notify combobox that it should use the listbox as it's popup + comboBox->SetDropDown(listFrame); - // Dropdown list visible style - nsCOMPtr visiblePseudoStyle; - aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::dropDownVisible, comboStyleContext, PR_FALSE, - getter_AddRefs(visiblePseudoStyle)); - - // Dropdown list hidden style - nsCOMPtr hiddenPseudoStyle; - aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::dropDownHidden, comboStyleContext, PR_FALSE, - getter_AddRefs(hiddenPseudoStyle)); + // Resolve psuedo element style for the dropdown list + nsCOMPtr listStyle; + rv = aPresContext->ResolvePseudoStyleContextFor(aContent, + nsHTMLAtoms::dropDownListPseudo, + aStyleContext, + PR_FALSE, + getter_AddRefs(listStyle)); - // Done creating drop-down list style contexts - NS_RELEASE(comboStyleContext); + // Initialize the scroll frame positioned. Note that it is NOT initialized as + // absolutely positioned. + nsIFrame* newFrame = nsnull; + InitializeScrollFrame(aPresContext, aState, listFrame, aContent, comboboxFrame, + listStyle, newFrame, PR_FALSE, PR_FALSE, PR_TRUE); - // Initialize the scroll frame as absolutely positioned. - InitializeScrollFrame(aPresContext, aState, listFrame, aContent, comboboxFrame, - listStyle, aNewFrame, PR_TRUE, PR_FALSE, PR_TRUE); + // Set flag so the events go to the listFrame not child frames. + // XXX: We should replace this with a real widget manager similar + // to how the nsFormControlFrame works. Re-directing events is a temporary Kludge. + nsIView *listView; + listFrame->GetView(&listView); + NS_ASSERTION(nsnull != listView,"ListFrame's view is nsnull"); + listView->SetViewFlags(NS_VIEW_PUBLIC_FLAG_DONT_CHECK_CHILDREN); - - // Set flag so the events go to the listFrame not child frames. - // XXX: We should replace this with a real widget manager similar - // to how the nsFormControlFrame works. - // Re-directing events is a temporary Kludge. - nsIView *listView; - listFrame->GetView(&listView); - NS_ASSERTION(nsnull != listView,"ListFrame's view is nsnull"); - listView->SetViewFlags(NS_VIEW_PUBLIC_FLAG_DONT_CHECK_CHILDREN); - - // Set initial visibility to hidden for the drop-down list - // XXX: This should not be necessary. Need to restructure the combo box as follows: - // Derive nsComboboxFrame from nsAreaFrame. Attach the placeholder frame, a label frame and - // a button frame. Override reresolve style context and reresolve the style on the ListBox. - // The event state manager should then be asked to set active and non-active based on - // The mouse click this would get rid of all of the ugly code here. The setting of the active - // Should cause re-resolution of the AreaFrame which will re-sync it. KMM. - listFrame->ReResolveStyleContext(aPresContext, hiddenPseudoStyle, NS_STYLE_HINT_NONE, nsnull, nsnull); - listView->SetVisibility(nsViewVisibility_kHide); - - - // Create a place holder frame for the dropdown list - nsIFrame* placeholderFrame = nsnull; - CreatePlaceholderFrameFor(aPresContext, aContent, aNewFrame, aStyleContext, - aParentFrame, &placeholderFrame); - aFrameItems.AddChild(placeholderFrame); - - // Add the absolutely positioned frame to its containing block's list - // of child frames - aState.mAbsoluteItems.AddChild(listFrame); - - listFrame = aNewFrame; - - // This needs to be done "after" the ListFrame has it's ChildList set - // because the SetInitChildList intializes the ListBox selection state - // and this method initializes the ComboBox's selection state - comboBox->SetDropDown(placeholderFrame, listFrame); - - - // Set up the Pseudo Style contents for combo box button pressed and - // out. - //XXX: TODO: Make this work even if resolving the pseudo style fails. - - nsCOMPtr outPseudoStyle; - aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::dropDownBtnOut, aStyleContext, PR_FALSE, - getter_AddRefs(outPseudoStyle)); - - nsCOMPtr pressPseudoStyle; - aPresContext->ResolvePseudoStyleContextFor(aContent, nsHTMLAtoms::dropDownBtnPressed, - aStyleContext, PR_FALSE, getter_AddRefs(pressPseudoStyle)); - - comboBox->SetDropDownStyleContexts(visiblePseudoStyle, hiddenPseudoStyle); - comboBox->SetButtonStyleContexts(outPseudoStyle, pressPseudoStyle); + nsIFrame* frame = nsnull; + if (NS_SUCCEEDED(comboboxFrame->QueryInterface(kIFrameIID, (void**)&frame))) { + nsFrameItems childItems; - nsIFrame* frame = nsnull; - if (NS_OK == comboboxFrame->QueryInterface(kIFrameIID, (void**)&frame)) { - nsFrameItems childItems; - frame->SetInitialChildList(*aPresContext, nsnull, - childItems.childList); - } - aProcessChildren = PR_FALSE; - //XXX: TODO: Need to set an option on the view that was created for the dropdown list - //to be a borderless top-level window. - - aNewFrame = comboboxFrame; - aFrameHasBeenInitialized = PR_TRUE; - } + // Create display and button frames from the combobox'es anonymous content + CreateAnonymousFrames(aPresContext, nsHTMLAtoms::combobox, aState, aContent, frame, + childItems); + + frame->SetInitialChildList(*aPresContext, nsnull, + childItems.childList); + // Initialize the additional popup child list which contains the dropdown list frame. + nsFrameItems popupItems; + popupItems.AddChild(listFrame); + frame->SetInitialChildList(*aPresContext, nsLayoutAtoms::popupList, + popupItems.childList); + } + // Don't process, the children, They are already processed by the InitializeScrollFrame + // call above. + aProcessChildren = PR_FALSE; + aNewFrame = comboboxFrame; + aFrameHasBeenInitialized = PR_TRUE; + } } else { // Construct a frame-based list box nsIFrame * listFrame; @@ -2550,7 +2498,7 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresContext* aPresContex listView->SetViewFlags(NS_VIEW_PUBLIC_FLAG_DONT_CHECK_CHILDREN); aFrameHasBeenInitialized = PR_TRUE; } - NS_RELEASE(dselect); + NS_RELEASE(select); } else { rv = NS_NewSelectControlFrame(&aNewFrame); } @@ -2739,6 +2687,7 @@ nsCSSFrameConstructor::ConstructFrameByTag(nsIPresContext* aPresContext PR_TRUE, childItems); } + // if there are any anonymous children create frames for them CreateAnonymousFrames(aPresContext, aTag, aState, aContent, newFrame, childItems); @@ -2818,14 +2767,21 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresContext* aPresConte // only these tags types can have anonymous content. We do this check for performance // reasons. If we did a query interface on every tag it would be very inefficient. if (aTag != nsHTMLAtoms::input && + aTag != nsHTMLAtoms::combobox && aTag != nsXULAtoms::slider && aTag != nsXULAtoms::splitter && - aTag != nsXULAtoms::scrollbar) { + aTag != nsXULAtoms::scrollbar + ) { return NS_OK; } - + // get the document + nsIDocument* doc = nsnull; + nsresult rv = aContent->GetDocument(doc); + if (NS_FAILED(rv) || !doc) + return rv; + nsCOMPtr creator(do_QueryInterface(aNewFrame)); if (!creator) @@ -2849,6 +2805,8 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresContext* aPresConte nsCOMPtr content(do_QueryInterface(node)); content->SetParent(aContent); + content->SetDocument(doc, PR_TRUE); + // create the frame and attach it to our frame ConstructFrame(aPresContext, aState, content, aNewFrame, PR_FALSE, aChildItems); } diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.h b/mozilla/layout/html/style/src/nsCSSFrameConstructor.h index 29b85b2444b..93584718afc 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.h +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.h @@ -407,6 +407,7 @@ protected: nsresult ConstructTextControlFrame(nsIPresContext* aPresContext, nsIFrame*& aNewFrame); + nsresult ConstructSelectFrame(nsIPresContext* aPresContext, nsFrameConstructorState& aState, nsIContent* aContent, diff --git a/mozilla/layout/style/ua.css b/mozilla/layout/style/ua.css index 83377947f49..bee93ddf577 100644 --- a/mozilla/layout/style/ua.css +++ b/mozilla/layout/style/ua.css @@ -429,6 +429,18 @@ input[type=hidden] { border: none; visibility: hidden; } + + +input[type=file] { + white-space: nowrap; + border:none; +} + +/* browse button for file selector */ +input[type=file] input[type=button] { + height:inherit; +} + input[type=radio] { /* these margins are for NavQuirks, we need a Standard ua.css */ margin-left: 3px; @@ -738,8 +750,8 @@ label { /* Combo box style */ select, select[size="1"] { vertical-align: bottom; - border: 1px inset #c0c0c0; - background-color:rgb(204, 204, 204); + border: none; + background-color:rgb(204, 204, 204); color:black; white-space:nowrap; text-align: left; @@ -751,10 +763,53 @@ select[size] { border: 1px inset rgb(153, 153, 153); } -select:active { - border : 1px solid black; +select[size="1"] { + vertical-align: bottom; + border: none; + background-color:rgb(204, 204, 204); + color:black; + white-space:nowrap; + text-align: left; } + +/* combobox button */ +select input[type=button] { + border: outset 1px rgb(204, 204, 204); + background-image:url("arrow.gif"); + background-repeat:no-repeat; + background-position:center; + width:12px; + height:12px; + -moz-border-radius:0px; +} + +/* combobox display area */ +select input#-moz-display { + border: inset 1px rgb(204, 204, 204); + background-color: white; + background-image: none; + -moz-border-radius:0px; + padding-left: 0px; + padding-right: 0px; + padding-top: 0px; + padding-bottom: 0px; +} + +/* combbox display area - active */ +select input#-moz-display:active { + border: inset 1px rgb(204, 204, 204); + background-color:white; + background-image: none; + -moz-border-radius:0px; + padding-left: 0px; + padding-right: 0px; + padding-top: 0px; + padding-bottom: 0px; + background-color:white; +} + + option { display:block; padding-left:3px; @@ -985,47 +1040,20 @@ sourcetext { /* XXX should not be in HTML namespace */ display: none; } -:-moz-dropdown-visible { - visibility: visible; -} - -:-moz-dropdown-hidden { - visibility: hidden; -} - -:-moz-dropdown-btn-out { - border: 2px outset #c0c0c0; - background-color: rgb(206, 207, 206); -} - -:-moz-dropdown-btn-pressed { -/* border: 2px inset #c0c0c0; */ - background-color: rgb(204, 204, 204); - border: none; -} - +/* combobox dropdown list */ :-moz-dropdown-list { - position:absolute; - background-color:rgb(204, 204, 204); - border: 1px inset rgb(153, 153, 153); + background-color:inherit; + border: 1px inset rgb(153, 153, 153); } - -:-moz-combobox-text { - color: black; - padding-left: 2px; +/* combobox dropdown list hidden */ +select:-moz-dropdown-list { + visibility:hidden; } -:-moz-combobox-textselected { - background-color: rgb(0,0,128); - color: white; - border: 1px solid rgb(0,0,128); -} - -:-moz-combobox-textselectedfocus { - background-color: rgb(0,0,128); - color: white; - border: 1px dotted white; +/* combobox dropdown list visible */ +select[-moz-dropdown-active]:-moz-dropdown-list { + visibility: visible; } :-moz-anonymous-block { diff --git a/mozilla/webshell/tests/viewer/samples/mozform.css b/mozilla/webshell/tests/viewer/samples/mozform.css index 79dd0e7b6cd..f1b1b01f3da 100644 --- a/mozilla/webshell/tests/viewer/samples/mozform.css +++ b/mozilla/webshell/tests/viewer/samples/mozform.css @@ -161,25 +161,51 @@ button:focus:-moz-focus-inner { background-color:rgb(200, 200, 200); } - /* Combo box style */ select, select[size="1"] { vertical-align: bottom; - border: 1px inset #c0c0c0; - background-color:rgb(204, 204, 204); + border: none; + background-color:rgb(204, 204, 204); color:black; white-space:nowrap; text-align: left; } -/* Listbox style */ -select[size] { - background-color: white; - border: 1px inset rgb(153, 153, 153); + +/* combobox button */ +select input[type=button] { + border: outset 1px rgb(204, 204, 204); + background-image:url("arrow.gif"); + background-repeat:no-repeat; + background-position:center; + width:12px; + height:12px; + -moz-border-radius:0px; } -select:active { - border : 1px solid black; +/* combobox display area */ +select input#-moz-display { + border: inset 1px rgb(204, 204, 204); + background-color: white; + background-image: none; + -moz-border-radius:0px; + padding-left: 0px; + padding-right: 0px; + padding-top: 0px; + padding-bottom: 0px; +} + +/* combbox display area - active */ +select input#-moz-display:active { + border: inset 1px rgb(204, 204, 204); + background-color:white; + background-image: none; + -moz-border-radius:0px; + padding-left: 0px; + padding-right: 0px; + padding-top: 0px; + padding-bottom: 0px; + background-color:white; } option { diff --git a/mozilla/webshell/tests/viewer/samples/test16.html b/mozilla/webshell/tests/viewer/samples/test16.html index 2eb05453566..2d893acf4c6 100644 --- a/mozilla/webshell/tests/viewer/samples/test16.html +++ b/mozilla/webshell/tests/viewer/samples/test16.html @@ -114,10 +114,10 @@ function usestyle(styletype) group 2 -