diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 9b72d21e001c..3065a3b545f2 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -1721,82 +1721,86 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresContext* aPresContext, PRBool aIsFixedPositioned, nsAbsoluteItems& aFixedItems) { +#define NS_FRAME_BASED_COMBO_WORKS 0 nsresult rv = NS_OK; nsWidgetRendering mode; aPresContext->GetWidgetRenderingMode(&mode); -//XXX: When frame-based rendering works uncomment this and remove the line below -// if (eWidgetRendering_Gfx == mode) { - if (0) { + + if (eWidgetRendering_Gfx == mode) { nsIDOMHTMLSelectElement* select = nsnull; PRInt32 size = 1; nsresult result = aContent->QueryInterface(kIDOMHTMLSelectElementIID, (void**)&select); if (NS_OK == result) { result = select->GetSize(&size); if (1 == size) { - nsIFrame * comboboxFrame; - rv = NS_NewComboboxControlFrame(comboboxFrame); - nsIComboboxControlFrame* comboBox; - if (NS_OK == comboboxFrame->QueryInterface(kIComboboxControlFrameIID, (void**)&comboBox)) { + if (! NS_FRAME_BASED_COMBO_WORKS) { + rv = NS_NewSelectControlFrame(aNewFrame); + } else { + nsIFrame * comboboxFrame; + rv = NS_NewComboboxControlFrame(comboboxFrame); + nsIComboboxControlFrame* comboBox; + if (NS_OK == comboboxFrame->QueryInterface(kIComboboxControlFrameIID, (void**)&comboBox)) { - nsIFrame * listFrame; - rv = NS_NewListControlFrame(listFrame); + nsIFrame * listFrame; + rv = NS_NewListControlFrame(listFrame); - // 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); + // 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); + } + + InitializeScrollFrame(listFrame, aPresContext, aContent, comboboxFrame, aStyleContext, + aAbsoluteItems, aNewFrame, aFixedItems, aIsAbsolutelyPositioned, + aIsFixedPositioned, PR_TRUE); + + nsIFrame* placeholderFrame; + + CreatePlaceholderFrameFor(aPresContext, aContent, aNewFrame, aStyleContext, + aParentFrame, placeholderFrame); + + // Add the absolutely positioned frame to its containing block's list + // of child frames + if (aIsAbsolutelyPositioned) + aAbsoluteItems.AddChild(aNewFrame); + + 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 + //XXX: What should happend if resolving the pseudo style fails? + nsCOMPtr visiblePseudoStyle; + aPresContext->ResolvePseudoStyleContextFor + (aContent, nsHTMLAtoms::dropDownVisible, aStyleContext, PR_FALSE, + getter_AddRefs(visiblePseudoStyle)); + + nsCOMPtr hiddenPseudoStyle; + aPresContext->ResolvePseudoStyleContextFor + (aContent, nsHTMLAtoms::dropDownHidden, aStyleContext, PR_FALSE, + getter_AddRefs(hiddenPseudoStyle)); + + 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); + + aProcessChildren = PR_FALSE; + nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, listFrame, + aStyleContext, PR_TRUE); + aNewFrame = comboboxFrame; } - - InitializeScrollFrame(listFrame, aPresContext, aContent, comboboxFrame, aStyleContext, - aAbsoluteItems, aNewFrame, aFixedItems, aIsAbsolutelyPositioned, - aIsFixedPositioned, PR_TRUE); - - nsIFrame* placeholderFrame; - - CreatePlaceholderFrameFor(aPresContext, aContent, aNewFrame, aStyleContext, - aParentFrame, placeholderFrame); - - // Add the absolutely positioned frame to its containing block's list - // of child frames - if (aIsAbsolutelyPositioned) - aAbsoluteItems.AddChild(aNewFrame); - - 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 - //XXX: What should happend if resolving the pseudo style fails? - nsCOMPtr visiblePseudoStyle; - aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::dropDownVisible, aStyleContext, PR_FALSE, - getter_AddRefs(visiblePseudoStyle)); - - nsCOMPtr hiddenPseudoStyle; - aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::dropDownHidden, aStyleContext, PR_FALSE, - getter_AddRefs(hiddenPseudoStyle)); - - 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); - - aProcessChildren = PR_FALSE; - nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, listFrame, - aStyleContext, PR_TRUE); - aNewFrame = comboboxFrame; } } else { diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index 81d3b1aa740f..aaff733ef5b8 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -377,9 +377,11 @@ NS_IMETHODIMP nsComboboxControlFrame::Reflow(nsIPresContext& aPresConte aPresContext.GetScaledPixelsToTwips(&sp2t); nscoord onePixel = NSIntPixelsToTwips(1, sp2t); +#if 0 nscoord scrollbarWidth = 0; nscoord scrollbarHeight = 0; nsListControlFrame::GetScrollBarDimensions(aPresContext, scrollbarWidth, scrollbarHeight); +#endif nscoord extra = desiredSize.height - (rowHeight * numRows); diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index b93de4a8841e..195ee9aa23da 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/layout/forms/nsListControlFrame.cpp @@ -48,21 +48,21 @@ #include "nsIFormControl.h" #include "nsStyleUtil.h" #include "nsINameSpaceManager.h" -#include "nsIDeviceContext.h" //rods -#include "nsIHTMLContent.h" //rods -#include "nsIDOMHTMLCollection.h" //rods -#include "nsIDOMHTMLSelectElement.h" //rods -//#include "nsIDOMHTMLOListElement.h" //rods -#include "nsIDOMHTMLOptionElement.h" //rods -#include "nsIDOMNode.h" //rods -#include "nsHTMLAtoms.h" //rods -#include "nsIAtom.h" //rods +#include "nsIDeviceContext.h" +#include "nsIHTMLContent.h" +#include "nsIDOMHTMLCollection.h" +#include "nsIDOMHTMLSelectElement.h" +#include "nsIDOMHTMLOptionElement.h" +#include "nsIDOMNode.h" +#include "nsHTMLAtoms.h" +#include "nsIAtom.h" #include "nsIDOMEventReceiver.h" #include "nsIComboboxControlFrame.h" #include "nsComboboxControlFrame.h" // for the static helper function #include "nsIListControlFrame.h" #include "nsIViewManager.h" #include "nsFormFrame.h" +#include "nsIScrollableView.h" #define CSS_NOTSET -1 #define ATTR_NOTSET -1 @@ -71,22 +71,16 @@ const char * kNormal = ""; const char * kSelected = "SELECTED"; const char * kSelectedFocus = "SELECTEDFOCUS"; - const char * kMozSelected = "-moz-option-selected"; - -static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID); -static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); - -#ifdef PLUGGABLE_EVENTS -static NS_DEFINE_IID(kIPluggableEventListenerIID, NS_IPLUGGABLEEVENTLISTENER_IID); -#endif -static NS_DEFINE_IID(kIListControlFrameIID, NS_ILISTCONTROLFRAME_IID); - -static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID); -static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); -static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID); -static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID); +static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID); +static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); +static NS_DEFINE_IID(kIScrollableViewIID, NS_ISCROLLABLEVIEW_IID); +static NS_DEFINE_IID(kIListControlFrameIID, NS_ILISTCONTROLFRAME_IID); +static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); +static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID); +static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID); //---------------------------------------------------------------------- @@ -110,17 +104,10 @@ nsListControlFrame::nsListControlFrame() mSelectedContent = nsnull; mSelectedIndex = -1; mNumRows = 0; - mMaxNumSelections = 64; mIsInitializedFromContent = PR_FALSE; - - PRInt32 i; - for (i=0;iQueryInterface(kIScrollableViewIID, (void **)&scrollableView))) { + scrollableView->GetScrollPosition(offsetx, offsety); + absPoint.x += offsetx; + absPoint.y += offsety; + // Note: scrollableView is not ref counted so it's interface is not NS_RELEASE'd + } + } + mContentFrame->FirstChild(aList, &kid); while (nsnull != kid) { kid->GetRect(kidRect); - if (kidRect.Contains(aPoint)) { - tmp.MoveTo(aPoint.x - kidRect.x, aPoint.y - kidRect.y); + if (kidRect.Contains(absPoint)) { + tmp.MoveTo(absPoint.x - kidRect.x, absPoint.y - kidRect.y); nsIContent * content; kid->GetContent(&content); @@ -218,7 +239,7 @@ nsListControlFrame::GetFrameForPointUsing(const nsPoint& aPoint, kid->GetFrameState(&state); if (NS_FRAME_OUTSIDE_CHILDREN & state) { kid->GetRect(kidRect); - tmp.MoveTo(aPoint.x - kidRect.x, aPoint.y - kidRect.y); + tmp.MoveTo(absPoint.x - kidRect.x, absPoint.y - kidRect.y); if (NS_OK == kid->GetFrameForPoint(tmp, aFrame)) { return NS_OK; } @@ -229,120 +250,130 @@ nsListControlFrame::GetFrameForPointUsing(const nsPoint& aPoint, return NS_ERROR_FAILURE; } -//---------------------------------------------------------------------- -void -nsListControlFrame::PaintChildren(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) -{ - - nsScrollFrame::PaintChildren(aPresContext, - aRenderingContext, - aDirtyRect, aWhichLayer); -} //---------------------------------------------------------------------- -// XXX this needs to properly deal with max element size. percentage based unconstrained widths cannot -// be allowed to return large max element sizes or tables will get too large. +// Reflow is overriden to constrain the listbox height to the number of rows and columns +// specified. +// NS_IMETHODIMP -nsListControlFrame::Reflow(nsIPresContext& aPresContext, +nsListControlFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + // Strategy: Let the inherited reflow happen as though the width and height of the + // ScrollFrame are big enough to allow the listbox to + // shrink to fit the longest option element line in the list. + // The desired width and height returned by the inherited reflow is returned, + // unless one of the following has been specified. + // 1. A css width has been specified. + // 2. The size has been specified. + // 3. The css height has been specified, but the number of rows has not. + // The size attribute overrides the height setting but the height setting + // should be honored if there isn't a size specified. + + // Determine the desired width + height for the listbox + + aDesiredSize.width = 0; + aDesiredSize.height = 0; + + // Initialize the current selected and not selected state's for + // the listbox items from the content if (!mIsInitializedFromContent) { mIsInitializedFromContent = PR_TRUE; InitializeFromContent(PR_TRUE); } + + nsIFrame* childFrame = nsnull; + mContentFrame->FirstChild(nsnull, &childFrame); + PRInt32 numChildren = LengthOf(childFrame); + PRBool needsVerticalScrollbar = (numChildren > mNumRows); + + //--Calculate a width just big enough for the scrollframe to shrink around the + //longest element in the list + //XXX: This is usually dangerous to do this type of coercion. Should it set the + //State back to the original when done??? + nsHTMLReflowState& tempReflowState = (nsHTMLReflowState&)aReflowState; - nsIFrame* childFrame; - - nscoord scrollbarWidth = 0; - nscoord scrollbarHeight = 0; - GetScrollBarDimensions(aPresContext, scrollbarWidth, scrollbarHeight); - - nsFont font(aPresContext.GetDefaultFixedFontDeprecated()); - GetFont(&aPresContext, font); - - nsSize maxSize(aReflowState.availableWidth, aReflowState.availableHeight); - nsHTMLReflowMetrics desiredSize = aDesiredSize; - aDesiredSize.width = 0; - aDesiredSize.height = 0; - - // Calculate the amount of space needed for borders - const nsStyleSpacing* spacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); - nsMargin border; - if (!spacing->GetBorder(border)) { - border.SizeTo(0, 0, 0, 0); - } - + // Get the size of option elements inside the listbox nsSize desiredLineSize; - GetDesiredSize(&aPresContext, aReflowState, aDesiredSize, desiredLineSize); + nsHTMLReflowMetrics desiredSize = aDesiredSize; + // Save original values which will be modified for the reflow state. + // They are set back to their original values at the end of reflow. + nscoord saveComputedWidth = tempReflowState.computedWidth; + nscoord saveAvailableWidth = tempReflowState.availableWidth; - float p2t; - aPresContext.GetScaledPixelsToTwips(&p2t); - nscoord lineEndPadding = NSIntPixelsToTwips(10, p2t);//GetHorizontalInsidePadding(aPresContext, p2t, 0, 0); - aDesiredSize.width += lineEndPadding; + // Compute the width based on the longest line in the listbox. + // XXX: This should be changed to do the inherited reflow unconstrained for + // the width to get the real desired width. GetDesiredSize is limited to + // text strings. + + GetDesiredSize(&aPresContext, aReflowState, desiredSize, desiredLineSize); + // Only set to the desired width if it hasn't been explicitly defined through CSS. + // GetDesiredSize must still be done above to calculate the desired height. + if (NS_UNCONSTRAINEDSIZE == tempReflowState.computedWidth) { + tempReflowState.computedWidth = desiredLineSize.width; + } + + // Retrieve the scrollbar's width and height + float sbWidth = 0.0; + float sbHeight = 0.0;; + nsCOMPtr dc; + aPresContext.GetDeviceContext(getter_AddRefs(dc)); + dc->GetScrollBarDimensions(sbWidth, sbHeight); + // Convert to nscoord's by rounding + nscoord scrollbarWidth = NSToCoordRound(sbWidth); + nscoord scrollbarHeight = NSToCoordRound(sbHeight); - desiredSize = aDesiredSize; - nsIFrame * firstChild = mFrames.FirstChild(); + // Add vertical scrollbar, Always add it in, + // even though the vertical scrollbar is not needed all the time + // the inherited Reflow: allways leave space for the scrollbar by + // shrinking the scroll area by the scrollbar width - nsHTMLReflowState reflowState(aPresContext, aReflowState, firstChild, maxSize); - nsIHTMLReflow* htmlReflow; - if (NS_OK == firstChild->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) { - htmlReflow->WillReflow(aPresContext); - htmlReflow->Reflow(aPresContext, desiredSize, reflowState, aStatus); - NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); + tempReflowState.computedWidth += scrollbarWidth; + + // Now that we have calculated the width required to just shrink around the longest line. + // Go ahead and reflow + + // Do the inherited Reflow. This reflow uses the computed widths which + // are setup above. + + // Don't set the height. Let the height be unconstrained + + nsScrollFrame::Reflow(aPresContext, + aDesiredSize, + tempReflowState, + aStatus); + + // Now that we have reflowed, we may need to adjust the width and height returned + // for the listbox. + + // Set the desired height to the computed height above only if it has not + // been explicitly set by CSS. + if (NS_UNCONSTRAINEDSIZE == tempReflowState.computedHeight) { + aDesiredSize.height = desiredSize.height; } - mContentFrame->FirstChild(nsnull, &childFrame); - PRInt32 numChildren = LengthOf(childFrame); - - aDesiredSize.width += border.left+border.right; - aDesiredSize.height += border.top+border.bottom; - - nscoord insideWidth = aDesiredSize.width-border.left-border.right-1; - if (mInDropDownMode) { + //Need to addback the scrollbar because the inherited reflow + //subtracts the scrollbar width when computing the desired size. + //We don't subtract when there isn't a vertical scrollbar. This may + //seem odd, becuase above we always add in the scrollbar width before calling + //reflow. The reason is that inherited reflow always leaves blank space for + //the scrollbar, but we don't whant that behavior for the listbox'es scrollbars. + if (needsVerticalScrollbar) { aDesiredSize.width += scrollbarWidth; - insideWidth += scrollbarWidth; - } else { - if (mNumRows < numChildren) { - aDesiredSize.width += scrollbarWidth; - } - } - - nsRect rect(0,0, insideWidth, desiredLineSize.height*numChildren); - mContentFrame->SetRect(rect); - - - mContentFrame->FirstChild(nsnull, &childFrame); - nsPoint offset(0,0); - while (nsnull != childFrame) { // reflow, place, size the children - nsHTMLReflowState reflowState(aPresContext, aReflowState, childFrame, maxSize); - nsIHTMLReflow* htmlReflow; - - if (NS_OK == childFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) { - htmlReflow->WillReflow(aPresContext); - htmlReflow->Reflow(aPresContext, desiredSize, reflowState, aStatus); - NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); - //??nsRect rect(offset.x, offset.y, desiredLineSize.width+lineEndPadding, desiredLineSize.height); - nsRect rect(offset.x, offset.y, insideWidth, desiredLineSize.height); - childFrame->SetRect(rect); - childFrame->GetNextSibling(&childFrame); - offset.x = 0; - offset.y += desiredLineSize.height; - } - } - + } + // Set the max element size to be the same as the desired element size. if (nsnull != aDesiredSize.maxElementSize) { - //XXX aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding); aDesiredSize.maxElementSize->width = aDesiredSize.width; aDesiredSize.maxElementSize->height = aDesiredSize.height; } - aStatus = NS_FRAME_COMPLETE; + //XXX: Set the min element size here to the desired element size here?? + // Restore to original reflow state. + tempReflowState.computedWidth = saveComputedWidth; + tempReflowState.availableWidth = saveAvailableWidth; + aStatus = NS_FRAME_COMPLETE; return NS_OK; } @@ -406,21 +437,29 @@ nsListControlFrame::GetFont(nsIPresContext* aPresContext, return NS_OK; } -//---------------------------------------------------------------------- -NS_IMETHODIMP nsListControlFrame::PluggableEventHandler(nsIPresContext& aPresContext, - nsGUIEvent* aEvent, - nsEventStatus& aEventStatus) + +// 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) { - HandleEvent(aPresContext, aEvent, aEventStatus); - //aEventStatus = nsEventStatus_eConsumeNoDefault; - return NS_OK; + nsCOMPtr selectedAtom ( dont_QueryInterface(NS_NewAtom(kMozSelected))); + aContent->SetAttribute(kNameSpaceID_None, selectedAtom, "", PR_TRUE); } -//---------------------------------------------------------------------- -NS_IMETHODIMP nsListControlFrame::PluggableGetFrameForPoint(const nsPoint& aPoint, - nsIFrame** aFrame) +void nsListControlFrame::DisplayDeselected(nsIContent* aContent) { - return GetFrameForPoint(aPoint, aFrame); + nsCOMPtr selectedAtom ( dont_QueryInterface(NS_NewAtom(kMozSelected))); + aContent->UnsetAttribute(kNameSpaceID_None, selectedAtom, PR_TRUE); +} + +void nsListControlFrame::UpdateItem(nsIContent* aContent, PRBool aSelected) +{ + if (aSelected) { + DisplaySelected(aContent); + } else { + DisplayDeselected(aContent); + } } //---------------------------------------------------------------------- @@ -437,8 +476,7 @@ PRInt32 nsListControlFrame::SetContentSelected(nsIFrame * aHitFrame, nsIContent* content; kid->GetContent(&content); aHitContent = content; - nsCOMPtr selectedAtom ( dont_QueryInterface(NS_NewAtom(kMozSelected)) ); - aHitContent->SetAttribute(kNameSpaceID_None, selectedAtom, "", PR_TRUE); + //XXX: DisplaySelected(aHitContent); return index; } kid->GetNextSibling(&kid); @@ -456,10 +494,10 @@ void nsListControlFrame::ClearSelection() while (nsnull != kid) { nsIContent * content; kid->GetContent(&content); - if (mIsFrameSelected[i]) { + if (IsFrameSelected(i)) { if (i != mSelectedIndex) { - content->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kNormal, PR_TRUE); - mIsFrameSelected[i] = PR_FALSE; + DisplayDeselected(content); + SetFrameSelected(i, PR_FALSE); } } NS_RELEASE(content); @@ -494,12 +532,12 @@ void nsListControlFrame::ExtendedSelection(PRInt32 aStartIndex, PRInt32 aEndInde } if (startInverting && ((i != mStartExtendedIndex && aDoInvert) || !aDoInvert)) { if (aDoInvert) { - mIsFrameSelected[i] = !mIsFrameSelected[i]; + SetFrameSelected(i, !IsFrameSelected(i)); } else { - mIsFrameSelected[i] = aSetValue; + SetFrameSelected(i, aSetValue); } if (i != mSelectedIndex) { - content->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, (mIsFrameSelected[i]?kSelected:kNormal), PR_TRUE); + UpdateItem(content, IsFrameSelected(i)); } } if (i == endInx) { @@ -518,9 +556,12 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeListEvent(nsIPresContext& aPresConte { if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) { PRInt32 oldSelectedIndex = mSelectedIndex; + mSelectedIndex = (PRInt32)SetContentSelected(mHitFrame, mHitContent, PR_TRUE); if (-1 < mSelectedIndex) { - PRBool selected = mIsFrameSelected[mSelectedIndex]; + PRBool wasSelected = IsFrameSelected(mSelectedIndex); + SetFrameSelected(mSelectedIndex, PR_TRUE); + PRBool selected = wasSelected; if (mMultipleSelections) { if (((nsMouseEvent *)aEvent)->isShift) { @@ -556,10 +597,11 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeListEvent(nsIPresContext& aPresConte } else if (((nsMouseEvent *)aEvent)->isControl) { selected = !selected; if (nsnull != mSelectedContent) { - if (mHitContent != mSelectedContent) { - mSelectedContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, (mIsFrameSelected[oldSelectedIndex]?kSelected:kNormal), PR_TRUE); + if (mHitContent != mSelectedContent) { + // Toggle the selection + UpdateItem(mHitContent, !wasSelected); } else { - mSelectedContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, (selected?kSelectedFocus:kNormal), PR_TRUE); + //XXX: Fix this mSelectedContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, (selected?kSelectedFocus:kNormal), PR_TRUE); } } } else { @@ -570,13 +612,11 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeListEvent(nsIPresContext& aPresConte } } else { if (nsnull != mSelectedContent) { - nsCOMPtr selectedAtom ( dont_QueryInterface(NS_NewAtom(kMozSelected)) ); - mSelectedContent->UnsetAttribute(kNameSpaceID_None, selectedAtom, PR_TRUE); - //XXX: This needs to a set a psuedo attribute instead mSelectedContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kNormal, PR_TRUE); + DisplayDeselected(mSelectedContent); NS_RELEASE(mSelectedContent); } } - mIsFrameSelected[mSelectedIndex] = selected; + //XXX: Remove SetFrameSelected(mSelectedIndex, selected); //XXX mHitContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, (selected?kSelectedFocus:kNormal), PR_TRUE); mSelectedContent = mHitContent; mSelectedFrame = mHitFrame; @@ -603,7 +643,7 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aP // If the DropDown is currently has a selected item // then clear the selected item if (nsnull != mSelectedContent) { - mSelectedContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kNormal, PR_TRUE); + DisplayDeselected(mSelectedContent); NS_RELEASE(mSelectedContent); } @@ -613,7 +653,7 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aP // Since the new frame is different then clear the selection on the old frame (the current frame) if (nsnull != mCurrentHitContent) { - mCurrentHitContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kNormal, PR_TRUE); + DisplayDeselected(mCurrentHitContent); NS_RELEASE(mCurrentHitContent); } @@ -645,15 +685,15 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aP // Clean up frames before disappearing if (nsnull != mSelectedContent) { - mSelectedContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kNormal, PR_TRUE); + DisplayDeselected(mSelectedContent); NS_RELEASE(mSelectedContent); } if (nsnull != mHitContent) { - mHitContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kNormal, PR_TRUE); + DisplayDeselected(mHitContent); NS_RELEASE(mHitContent); } if (nsnull != mCurrentHitContent) { - mCurrentHitContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kNormal, PR_TRUE); + DisplayDeselected(mCurrentHitContent); NS_RELEASE(mCurrentHitContent); } NS_RELEASE(option); @@ -727,13 +767,10 @@ nsListControlFrame::SetInitialChildList(nsIPresContext& aPresContext, nsIFrame* aChildList) { mContentFrame = aChildList; -#ifdef PLUGGABLE_EVENTS - mContentFrame->SetPluggableEventListener(this); -#endif + if (!mInDropDownMode) { nsFormFrame::AddFormControlFrame(aPresContext, *this); } - //aChildList->FirstChild(nsnull, mContentFrame); if (!mIsInitializedFromContent) { InitializeFromContent(); @@ -742,33 +779,6 @@ nsListControlFrame::SetInitialChildList(nsIPresContext& aPresContext, return nsScrollFrame::SetInitialChildList(aPresContext, aListName, aChildList); } -//---------------------------------------------------------------------- -/*nsresult -nsListControlFrame::AppendNewFrames(nsIPresContext& aPresContext, - nsIFrame* aNewFrame) -{ - return nsScrollFrame::AppendNewFrames(aPresContext, aNewFrame); -} - -//---------------------------------------------------------------------- -nsresult -nsListControlFrame::InsertNewFrame(nsIPresContext& aPresContext, - nsBaseIBFrame* aParentFrame, - nsIFrame* aNewFrame, - nsIFrame* aPrevSibling) -{ - return nsScrollFrame::InsertNewFrame(aPresContext, aParentFrame, aNewFrame, aPrevSibling); -} - -//---------------------------------------------------------------------- -nsresult -nsListControlFrame::DoRemoveFrame(nsBlockReflowState& aState, - nsBaseIBFrame* aParentFrame, - nsIFrame* aDeletedFrame, - nsIFrame* aPrevSibling) -{ - return nsScrollFrame::DoRemoveFrame(aState, aParentFrame, aDeletedFrame, aPrevSibling); -}*/ //---------------------------------------------------------------------- NS_IMETHODIMP @@ -780,13 +790,6 @@ nsListControlFrame::Init(nsIPresContext& aPresContext, { nsresult result = nsScrollFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - /*if (NS_OK == result) { - nsIDOMNode* node; - if (mContent && (NS_OK == mContent->QueryInterface(kIDOMNodeIID, (void**) &node))) { - AddEventListener(node); - NS_RELEASE(node); - } - }*/ if (NS_OK == result) { nsIDOMHTMLSelectElement* select; if (mContent && (NS_OK == mContent->QueryInterface(kIDOMHTMLSelectElementIID, (void**) &select))) { @@ -798,7 +801,6 @@ nsListControlFrame::Init(nsIPresContext& aPresContext, } return result; - } //---------------------------------------------------------------------- @@ -838,31 +840,6 @@ nsListControlFrame::GetSizeFromContent(PRInt32* aSize) const } return result; } -//---------------------------------------------------------------------- -void -nsListControlFrame::GetScrollBarDimensions(nsIPresContext& aPresContext, - nscoord &aWidth, nscoord &aHeight) -{ - - aWidth = 0; - aHeight = 0; - float scale; - nsCOMPtr dx; - aPresContext.GetDeviceContext(getter_AddRefs(dx)); - if (dx) { - float sbWidth; - float sbHeight; - dx->GetCanonicalPixelScale(scale); - dx->GetScrollBarDimensions(sbWidth, sbHeight); - aWidth = PRInt32(sbWidth * scale); - aHeight = PRInt32(sbHeight * scale); - } //else { - //aWidth = 19 * sp2t; - //aHeight = scrollbarWidth; - //} - - -} //---------------------------------------------------------------------- nscoord @@ -883,7 +860,7 @@ nscoord nsListControlFrame::GetVerticalInsidePadding(float aPixToTwip, nscoord aInnerHeight) const { - return NSIntPixelsToTwips(0, aPixToTwip); // XXX this is really + return NSIntPixelsToTwips(0, aPixToTwip); } //---------------------------------------------------------------------- @@ -923,6 +900,8 @@ nsListControlFrame::GetDesiredSize(nsIPresContext* aPresContext, PRInt32 maxWidth = 1; PRUint32 numOptions; options->GetLength(&numOptions); + + for (PRUint32 i = 0; i < numOptions; i++) { nsIDOMHTMLOptionElement* option = GetOption(*options, i); if (option) { @@ -1059,7 +1038,7 @@ nsListControlFrame::AboutToDropDown() if (i == mSelectedIndex) { mSelectedContent = content; mSelectedFrame = kid; - mSelectedContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kSelected, PR_TRUE); + DisplaySelected(mSelectedContent); return NS_OK; } NS_RELEASE(content); @@ -1069,14 +1048,63 @@ nsListControlFrame::AboutToDropDown() return NS_OK; } + +nsIContent* +nsListControlFrame::GetOptionContent(PRUint32 aIndex) +{ + nsresult result = NS_OK; + nsIDOMHTMLCollection* options = GetOptions(mContent); + nsIDOMHTMLOptionElement* optionElement = GetOption(*options, aIndex); + + nsIContent *content = nsnull; + result = optionElement->QueryInterface(kIContentIID, (void**) &content); + + NS_RELEASE(optionElement); + NS_RELEASE(options); + + if (NS_SUCCEEDED(result)) { + return(content); + } else { + return(nsnull); + } +} + +PRBool +nsListControlFrame::IsFrameSelected(PRUint32 aIndex) +{ + nsIContent* content = GetOptionContent(aIndex); + NS_ASSERTION(nsnull != content, "Failed to retrieve option content"); + nsString value; + nsCOMPtr selectedAtom ( dont_QueryInterface(NS_NewAtom(kMozSelected))); + nsresult result = content->GetAttribute(kNameSpaceID_None, selectedAtom, value); + NS_IF_RELEASE(content); + + if (NS_CONTENT_ATTR_NOT_THERE == result) { + return(PR_FALSE); + } + else { + return(PR_TRUE); + } +} + +void +nsListControlFrame::SetFrameSelected(PRUint32 aIndex, PRBool aSelected) +{ + nsIContent* content = GetOptionContent(aIndex); + NS_ASSERTION(nsnull != content, "Failed to retrieve option content"); + if (aSelected) { + DisplaySelected(content); + } else { + DisplayDeselected(content); + } + NS_IF_RELEASE(content); +} + //---------------------------------------------------------------------- void nsListControlFrame::InitializeFromContent(PRBool aDoDisplay) { PRInt32 i; - for (i=0;iGetDefaultSelected(&selected); - //XXX: Remove, why is selected queried twice here? option->GetSelected(&selected); - mIsFrameSelected[i] = selected; + SetFrameSelected(i, selected); if (mInDropDownMode) { if (selected) { @@ -1106,11 +1133,10 @@ nsListControlFrame::InitializeFromContent(PRBool aDoDisplay) return; } } else { - if (selected && aDoDisplay) { - // 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. - nsCOMPtr selectedAtom ( dont_QueryInterface(NS_NewAtom(kMozSelected))); - content->SetAttribute(kNameSpaceID_None, selectedAtom, "", PR_TRUE); + if (selected && aDoDisplay) { + DisplaySelected(content); + mSelectedContent = content; + NS_ADDREF(content); } } NS_RELEASE(option); @@ -1186,203 +1212,14 @@ nsListControlFrame::Deselect() { PRInt32 i; for (i=0;iGetFont(&aPresContext, font); - nsIDeviceContext* deviceContext = aPresContext.GetDeviceContext(); - nsIFontMetrics* fontMet; - deviceContext->GetMetricsFor(font, fontMet); - aRendContext->SetFont(fontMet); - aRendContext->GetWidth(aString, aSize.width); - fontMet->GetHeight(aSize.height); - - char char1, char2; - nsCompatibility mode = nsFormControlHelper::GetRepChars(aPresContext, char1, char2); - nscoord char1Width, char2Width; - aRendContext->GetWidth(char1, char1Width); - aRendContext->GetWidth(char2, char2Width); - - NS_RELEASE(fontMet); - NS_RELEASE(deviceContext); - - if (eCompatibility_Standard == mode) { - return ((char1Width + char2Width) / 2) + 1; - } else { - return char1Width; - } -} - -//------------------------------------------------------------------ -nscoord -nsListControlFrame::GetTextSize(nsIPresContext& aPresContext, nsListControlFrame* aFrame, - PRInt32 aNumChars, nsSize& aSize, - nsIRenderingContext *aRendContext) -{ - nsAutoString val; - char char1, char2; - nsFormControlHelper::GetRepChars(aPresContext, char1, char2); - int i; - for (i = 0; i < aNumChars; i+=2) { - val += char1; - } - for (i = 1; i < aNumChars; i+=2) { - val += char2; - } - return GetTextSize(aPresContext, aFrame, val, aSize, aRendContext); -} - -//------------------------------------------------------------------ -PRInt32 -nsListControlFrame::CalculateSize (nsIPresContext* aPresContext, nsListControlFrame* aFrame, - const nsSize& aCSSSize, nsInputDimensionSpec& aSpec, - nsSize& aBounds, PRBool& aWidthExplicit, - PRBool& aHeightExplicit, nscoord& aRowHeight, - nsIRenderingContext *aRendContext) -{ - nscoord charWidth = 0; - PRInt32 numRows = ATTR_NOTSET; - aWidthExplicit = PR_FALSE; - aHeightExplicit = PR_FALSE; - - aBounds.width = CSS_NOTSET; - aBounds.height = CSS_NOTSET; - nsSize textSize(0,0); - - nsIContent* iContent = nsnull; - aFrame->GetContent((nsIContent*&) iContent); - if (!iContent) { - return 0; - } - nsIHTMLContent* hContent = nsnull; - nsresult result = iContent->QueryInterface(kIHTMLContentIID, (void**)&hContent); - if ((NS_OK != result) || !hContent) { - NS_RELEASE(iContent); - return 0; - } - nsAutoString valAttr; - nsresult valStatus = NS_CONTENT_ATTR_NOT_THERE; - if (nsnull != aSpec.mColValueAttr) { - valStatus = hContent->GetAttribute(kNameSpaceID_HTML, aSpec.mColValueAttr, valAttr); - } - nsHTMLValue colAttr; - nsresult colStatus = NS_CONTENT_ATTR_NOT_THERE; - if (nsnull != aSpec.mColSizeAttr) { - colStatus = hContent->GetHTMLAttribute(aSpec.mColSizeAttr, colAttr); - } - float p2t; - aPresContext->GetScaledPixelsToTwips(p2t); - - // determine the width - nscoord adjSize; - if (NS_CONTENT_ATTR_HAS_VALUE == colStatus) { // col attr will provide width - PRInt32 col = ((colAttr.GetUnit() == eHTMLUnit_Pixel) ? colAttr.GetPixelValue() : colAttr.GetIntValue()); - if (aSpec.mColSizeAttrInPixels) { - col = (col <= 0) ? 15 : col; - aBounds.width = NSIntPixelsToTwips(col, p2t); - } - else { - col = (col <= 0) ? 1 : col; - charWidth = GetTextSize(*aPresContext, aFrame, col, aBounds, aRendContext); - aRowHeight = aBounds.height; // XXX aBounds.height has CSS_NOTSET - } - if (aSpec.mColSizeAttrInPixels) { - aWidthExplicit = PR_TRUE; - } - } - else { - if (CSS_NOTSET != aCSSSize.width) { // css provides width - aBounds.width = (aCSSSize.width > 0) ? aCSSSize.width : 1; - aWidthExplicit = PR_TRUE; - } - else { - if (NS_CONTENT_ATTR_HAS_VALUE == valStatus) { // use width of initial value - charWidth = GetTextSize(*aPresContext, aFrame, valAttr, aBounds, aRendContext); - } - else if (aSpec.mColDefaultValue) { // use default value - charWidth = GetTextSize(*aPresContext, aFrame, *aSpec.mColDefaultValue, aBounds, aRendContext); - } - else if (aSpec.mColDefaultSizeInPixels) { // use default width in pixels - charWidth = GetTextSize(*aPresContext, aFrame, 1, aBounds, aRendContext); - aBounds.width = aSpec.mColDefaultSize; - } - else { // use default width in num characters - charWidth = GetTextSize(*aPresContext, aFrame, aSpec.mColDefaultSize, aBounds, aRendContext); - } - aRowHeight = aBounds.height; // XXX aBounds.height has CSS_NOTSET - } - } - - // determine the height - nsHTMLValue rowAttr; - nsresult rowStatus = NS_CONTENT_ATTR_NOT_THERE; - if (nsnull != aSpec.mRowSizeAttr) { - rowStatus = hContent->GetHTMLAttribute(aSpec.mRowSizeAttr, rowAttr); - } - if (NS_CONTENT_ATTR_HAS_VALUE == rowStatus) { // row attr will provide height - PRInt32 rowAttrInt = ((rowAttr.GetUnit() == eHTMLUnit_Pixel) ? rowAttr.GetPixelValue() : rowAttr.GetIntValue()); - adjSize = (rowAttrInt > 0) ? rowAttrInt : 1; - if (0 == charWidth) { - charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); - aBounds.height = textSize.height * adjSize; - aRowHeight = textSize.height; - numRows = adjSize; - } - else { - aBounds.height = aBounds.height * adjSize; - } - } - else if (CSS_NOTSET != aCSSSize.height) { // css provides height - aBounds.height = (aCSSSize.height > 0) ? aCSSSize.height : 1; - aHeightExplicit = PR_TRUE; - } - else { // use default height in num lines - if (0 == charWidth) { - charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); - aBounds.height = textSize.height * aSpec.mRowDefaultSize; - aRowHeight = textSize.height; - } - else { - aBounds.height = aBounds.height * aSpec.mRowDefaultSize; - } - } - - if ((0 == charWidth) || (0 == textSize.width)) { - charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); - aRowHeight = textSize.height; - } - - // add inside padding if necessary - if (!aWidthExplicit) { - aBounds.width += (2 * aFrame->GetHorizontalInsidePadding(*aPresContext, p2t, aBounds.width, charWidth)); - } - if (!aHeightExplicit) { - aBounds.height += (2 * aFrame->GetVerticalInsidePadding(p2t, textSize.height)); - } - - NS_RELEASE(hContent); - if (ATTR_NOTSET == numRows) { - numRows = aBounds.height / aRowHeight; - } - - NS_RELEASE(iContent); - return numRows; -} - -#endif //---------------------------------------------------------------------- //---------------------------------------------------------------------- @@ -1407,17 +1244,6 @@ nsListControlFrame::GetSkipSides() const NS_IMETHODIMP nsListControlFrame::GetType(PRInt32* aType) const { - /*nsresult result = NS_FORM_NOTOK; - if (mContent) { - nsIFormControl* formControl = nsnull; - result = mContent->QueryInterface(kIFormControlIID, (void**)&formControl); - if ((NS_OK == result) && formControl) { - result = formControl->GetType(aType); - NS_RELEASE(formControl); - } - } - return result; - */ *aType = NS_FORM_SELECT; return NS_OK; } @@ -1440,15 +1266,8 @@ nsListControlFrame::IsSuccessful(nsIFormControlFrame* aSubmitter) void nsListControlFrame::MouseClicked(nsIPresContext* aPresContext) { - /*nsIRadioButton* radioWidget; - if (mWidget && (NS_OK == mWidget->QueryInterface(kIRadioIID, (void**)&radioWidget))) { - radioWidget->SetState(PR_TRUE); - NS_RELEASE(radioWidget); - if (mFormFrame) { - mFormFrame->OnRadioChecked(*this); - } - }*/ } + //---------------------------------------------------------------------- PRInt32 nsListControlFrame::GetMaxNumValues() @@ -1488,7 +1307,7 @@ nsListControlFrame::Reset() PRBool selected = PR_FALSE; option->GetSelected(&selected); if (selected) { - mIsFrameSelected[i] = PR_TRUE; + SetFrameSelected(i, PR_TRUE); } NS_RELEASE(option); } @@ -1518,16 +1337,6 @@ nsListControlFrame::GetName(nsString* aResult) } return result; } - - -//---------------------------------------------------------------------- -/*PRBool -nsListControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames) -{ - aNumValues = 0; - return PR_FALSE; -}*/ //---------------------------------------------------------------------- PRBool @@ -1554,7 +1363,7 @@ nsListControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, PRInt32 i = 0; PRInt32 inx; for (inx=0;iQueryInterface(kIDOMNodeIID, (void**) &node))) { - RemoveEventListener(node); - NS_RELEASE(node); - } - return nsScrollFrame::DeleteFrame(aPresContext); - -} -//----------------------------------------------------------------- -nsresult nsListControlFrame::Focus(nsIDOMEvent* aEvent) -{ - return NS_OK; -} - -//----------------------------------------------------------------- -nsresult nsListControlFrame::Blur(nsIDOMEvent* aEvent) -{ - return NS_OK; -} - -//----------------------------------------------------------------- -nsresult nsListControlFrame::ProcessEvent(nsIDOMEvent* aEvent) -{ - return NS_OK; -} - -//----------------------------------------------------------------- -NS_IMETHODIMP nsListControlFrame::AddEventListener(nsIDOMNode * aNode) -{ - nsIDOMEventReceiver * receiver; - - if (NS_OK == aNode->QueryInterface(kIDOMEventReceiverIID, (void**) &receiver)) { - receiver->AddEventListener((nsIDOMFocusListener*)this, kIDOMFocusListenerIID); - NS_RELEASE(receiver); - return NS_OK; - } - return NS_ERROR_FAILURE; -} - -//----------------------------------------------------------------- -NS_IMETHODIMP nsListControlFrame::RemoveEventListener(nsIDOMNode * aNode) -{ - nsIDOMEventReceiver * receiver; - - if (NS_OK == aNode->QueryInterface(kIDOMEventReceiverIID, (void**) &receiver)) { - receiver->RemoveEventListener(this, kIDOMFocusListenerIID); - NS_RELEASE(receiver); - return NS_OK; - } - return NS_ERROR_FAILURE; -} -#endif diff --git a/layout/forms/nsListControlFrame.h b/layout/forms/nsListControlFrame.h index 738817b089cd..803fc8f3f543 100644 --- a/layout/forms/nsListControlFrame.h +++ b/layout/forms/nsListControlFrame.h @@ -23,11 +23,9 @@ #include "nsIDOMFocusListener.h" #include "nsIPresContext.h" #include "nsIFormControlFrame.h" -#ifdef PLUGGABLE_EVENTS -#include "nsIPluggableEventListener.h" -#endif #include "nsIListControlFrame.h" + class nsIDOMHTMLSelectElement; class nsIDOMHTMLCollection; class nsIDOMHTMLOptionElement; @@ -35,33 +33,7 @@ class nsFormFrame; class nsScrollFrame; class nsIComboboxControlFrame; -#if 0 -struct nsInputDimSpec -{ - nsIAtom* mColSizeAttr; // attribute used to determine width - PRBool mColSizeAttrInPixels; // is attribute value in pixels (otherwise num chars) - nsIAtom* mColValueAttr; // attribute used to get value to determine size - // if not determined above - nsString* mColDefaultValue; // default value if not determined above - nscoord mColDefaultSize; // default width if not determined above - PRBool mColDefaultSizeInPixels; // is default width in pixels (otherswise num chars) - nsIAtom* mRowSizeAttr; // attribute used to determine height - nscoord mRowDefaultSize; // default height if not determined above - nsInputDimSpec(nsIAtom* aColSizeAttr, PRBool aColSizeAttrInPixels, - nsIAtom* aColValueAttr, nsString* aColDefaultValue, - nscoord aColDefaultSize, PRBool aColDefaultSizeInPixels, - nsIAtom* aRowSizeAttr, nscoord aRowDefaultSize) - : mColSizeAttr(aColSizeAttr), mColSizeAttrInPixels(aColSizeAttrInPixels), - mColValueAttr(aColValueAttr), - mColDefaultValue(aColDefaultValue), mColDefaultSize(aColDefaultSize), - mColDefaultSizeInPixels(aColDefaultSizeInPixels), - mRowSizeAttr(aRowSizeAttr), mRowDefaultSize(aRowDefaultSize) - { - } - -}; -#endif /** * The block frame has two additional named child lists: * - "Floater-list" which contains the floated frames @@ -71,11 +43,8 @@ struct nsInputDimSpec * @see nsLayoutAtoms::floaterList */ class nsListControlFrame : public nsScrollFrame, - public nsIFormControlFrame, - public nsIListControlFrame -#ifdef PLUGGABLE_EVENTS - public nsIPluggableEventListener -#endif + public nsIFormControlFrame, + public nsIListControlFrame { public: friend nsresult NS_NewListControlFrame(nsIFrame*& aNewFrame); @@ -101,20 +70,6 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); - // -/* virtual nsresult AppendNewFrames(nsIPresContext& aPresContext, nsIFrame*); - - virtual nsresult InsertNewFrame(nsIPresContext& aPresContext, - nsBaseIBFrame* aParentFrame, - nsIFrame* aNewFrame, - nsIFrame* aPrevSibling); - - virtual nsresult DoRemoveFrame(nsBlockReflowState& aState, - nsBaseIBFrame* aParentFrame, - nsIFrame* aDeletedFrame, - nsIFrame* aPrevSibling); - */ - NS_IMETHOD Init(nsIPresContext& aPresContext, nsIContent* aContent, nsIFrame* aParent, @@ -127,24 +82,10 @@ public: NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); - -#if 0 - virtual void GetStyleSize(nsIPresContext& aContext, - const nsHTMLReflowState& aReflowState, - nsSize& aSize); -#endif - virtual void GetDesiredSize(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredLayoutSize, nsSize& aDesiredWidgetSize); -#if 0 - nscoord CalculateSize (nsIPresContext* aPresContext, nsListControlFrame* aFrame, - const nsSize& aCSSSize, nsInputDimSpec& aDimensionSpec, - nsSize& aBounds, PRBool& aWidthExplicit, - PRBool& aHeightExplicit, nscoord& aRowSize, - nsIRenderingContext *aRendContext); -#endif /*virtual nsresult Focus(nsIDOMEvent* aEvent); virtual nsresult Blur(nsIDOMEvent* aEvent); @@ -156,21 +97,9 @@ public: NS_METHOD GetMultiple(PRBool* aResult, nsIDOMHTMLSelectElement* aSelect = nsnull); - ///XXX: End o the temporary methods -#if 0 - nscoord GetTextSize(nsIPresContext& aContext, nsListControlFrame* aFrame, - const nsString& aString, nsSize& aSize, - nsIRenderingContext *aRendContext); - - nscoord GetTextSize(nsIPresContext& aContext, nsListControlFrame* aFrame, - PRInt32 aNumChars, nsSize& aSize, - nsIRenderingContext *aRendContext); -#endif virtual nsresult GetSizeFromContent(PRInt32* aSize) const; NS_IMETHOD GetMaxLength(PRInt32* aSize); - static void GetScrollBarDimensions(nsIPresContext& aPresContext, - nscoord &aWidth, nscoord &aHeight); virtual nscoord GetVerticalBorderWidth(float aPixToTwip) const; virtual nscoord GetHorizontalBorderWidth(float aPixToTwip) const; virtual nscoord GetVerticalInsidePadding(float aPixToTwip, @@ -205,7 +134,7 @@ public: NS_IMETHOD GetName(nsString* aName); virtual void SetFocus(PRBool aOn = PR_TRUE, PRBool aRepaint = PR_FALSE); - + virtual void MouseClicked(nsIPresContext* aPresContext); virtual void Reset(); @@ -219,26 +148,21 @@ public: virtual void SetFormFrame(nsFormFrame* aFrame); - // nsIPluggableEventListener - NS_IMETHOD PluggableEventHandler(nsIPresContext& aPresContext, - nsGUIEvent* aEvent, - nsEventStatus& aEventStatus); - - NS_IMETHOD PluggableGetFrameForPoint(const nsPoint& aPoint, - nsIFrame** aFrame); - // nsIListControlFrame NS_IMETHOD SetComboboxFrame(nsIFrame* aComboboxFrame); NS_IMETHOD GetSelectedItem(nsString & aStr); NS_IMETHOD AboutToDropDown(); - // Static Methods static nsIDOMHTMLSelectElement* GetSelect(nsIContent * aContent); static nsIDOMHTMLCollection* GetOptions(nsIContent * aContent, nsIDOMHTMLSelectElement* aSelect = nsnull); static nsIDOMHTMLOptionElement* GetOption(nsIDOMHTMLCollection& aOptions, PRUint32 aIndex); static PRBool GetOptionValue(nsIDOMHTMLCollection& aCollecton, PRUint32 aIndex, nsString& aValue); + nsIContent* GetOptionContent(PRUint32 aIndex); + PRBool IsFrameSelected(PRUint32 aIndex); + void SetFrameSelected(PRUint32 aIndex, PRBool aSelected); + protected: nsListControlFrame(); virtual ~nsListControlFrame(); @@ -249,12 +173,14 @@ protected: nsIAtom* aList, nsIFrame** aFrame); - // nsHTMLContainerFrame overrides - virtual void PaintChildren(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); + // Utility methods + void DisplaySelected(nsIContent* aContent); + void DisplayDeselected(nsIContent* aContent); + void UpdateItem(nsIContent* aContent, PRBool aSelected); + + // nsHTMLContainerFrame overrides + void ClearSelection(); void InitializeFromContent(PRBool aDoDisplay = PR_FALSE); @@ -272,35 +198,26 @@ protected: // Data Members nsFormFrame* mFormFrame; - PRInt32 mNumRows; - - PRBool mIsFrameSelected[64]; +//XXX: TODO: This should not be hardcoded to 64 +//ZZZ PRBool mIsFrameSelected[64]; PRInt32 mNumSelections; PRInt32 mMaxNumSelections; PRBool mMultipleSelections; - - - //nsIContent * mSelectedContent; PRInt32 mSelectedIndex; PRInt32 mStartExtendedIndex; PRInt32 mEndExtendedIndex; - - nsIFrame * mHitFrame; + nsIFrame * mHitFrame; nsIContent * mHitContent; - - nsIFrame * mCurrentHitFrame; + nsIFrame * mCurrentHitFrame; nsIContent * mCurrentHitContent; - - nsIFrame * mSelectedFrame; + nsIFrame * mSelectedFrame; nsIContent * mSelectedContent; - PRBool mIsInitializedFromContent; - - nsIFrame * mContentFrame; - PRBool mInDropDownMode; + nsIFrame * mContentFrame; + PRBool mInDropDownMode; nsIComboboxControlFrame * mComboboxFrame; - nsString mSelectionStr; + nsString mSelectionStr; }; diff --git a/layout/html/document/src/ua.css b/layout/html/document/src/ua.css index ed3c98541586..77eaebae3cc6 100644 --- a/layout/html/document/src/ua.css +++ b/layout/html/document/src/ua.css @@ -664,6 +664,7 @@ select { color:black; } option { + display:block; } option.selected { @@ -673,8 +674,8 @@ option.selected { } option[-moz-option-selected] { - color:blue; - background-color:green; + color:white; + background-color: rgb(0,0,128); } option.selectedfocus { diff --git a/layout/html/forms/src/nsComboboxControlFrame.cpp b/layout/html/forms/src/nsComboboxControlFrame.cpp index 81d3b1aa740f..aaff733ef5b8 100644 --- a/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/layout/html/forms/src/nsComboboxControlFrame.cpp @@ -377,9 +377,11 @@ NS_IMETHODIMP nsComboboxControlFrame::Reflow(nsIPresContext& aPresConte aPresContext.GetScaledPixelsToTwips(&sp2t); nscoord onePixel = NSIntPixelsToTwips(1, sp2t); +#if 0 nscoord scrollbarWidth = 0; nscoord scrollbarHeight = 0; nsListControlFrame::GetScrollBarDimensions(aPresContext, scrollbarWidth, scrollbarHeight); +#endif nscoord extra = desiredSize.height - (rowHeight * numRows); diff --git a/layout/html/forms/src/nsListControlFrame.cpp b/layout/html/forms/src/nsListControlFrame.cpp index b93de4a8841e..195ee9aa23da 100644 --- a/layout/html/forms/src/nsListControlFrame.cpp +++ b/layout/html/forms/src/nsListControlFrame.cpp @@ -48,21 +48,21 @@ #include "nsIFormControl.h" #include "nsStyleUtil.h" #include "nsINameSpaceManager.h" -#include "nsIDeviceContext.h" //rods -#include "nsIHTMLContent.h" //rods -#include "nsIDOMHTMLCollection.h" //rods -#include "nsIDOMHTMLSelectElement.h" //rods -//#include "nsIDOMHTMLOListElement.h" //rods -#include "nsIDOMHTMLOptionElement.h" //rods -#include "nsIDOMNode.h" //rods -#include "nsHTMLAtoms.h" //rods -#include "nsIAtom.h" //rods +#include "nsIDeviceContext.h" +#include "nsIHTMLContent.h" +#include "nsIDOMHTMLCollection.h" +#include "nsIDOMHTMLSelectElement.h" +#include "nsIDOMHTMLOptionElement.h" +#include "nsIDOMNode.h" +#include "nsHTMLAtoms.h" +#include "nsIAtom.h" #include "nsIDOMEventReceiver.h" #include "nsIComboboxControlFrame.h" #include "nsComboboxControlFrame.h" // for the static helper function #include "nsIListControlFrame.h" #include "nsIViewManager.h" #include "nsFormFrame.h" +#include "nsIScrollableView.h" #define CSS_NOTSET -1 #define ATTR_NOTSET -1 @@ -71,22 +71,16 @@ const char * kNormal = ""; const char * kSelected = "SELECTED"; const char * kSelectedFocus = "SELECTEDFOCUS"; - const char * kMozSelected = "-moz-option-selected"; - -static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID); -static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); - -#ifdef PLUGGABLE_EVENTS -static NS_DEFINE_IID(kIPluggableEventListenerIID, NS_IPLUGGABLEEVENTLISTENER_IID); -#endif -static NS_DEFINE_IID(kIListControlFrameIID, NS_ILISTCONTROLFRAME_IID); - -static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID); -static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); -static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID); -static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID); +static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID); +static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); +static NS_DEFINE_IID(kIScrollableViewIID, NS_ISCROLLABLEVIEW_IID); +static NS_DEFINE_IID(kIListControlFrameIID, NS_ILISTCONTROLFRAME_IID); +static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); +static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID); +static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID); //---------------------------------------------------------------------- @@ -110,17 +104,10 @@ nsListControlFrame::nsListControlFrame() mSelectedContent = nsnull; mSelectedIndex = -1; mNumRows = 0; - mMaxNumSelections = 64; mIsInitializedFromContent = PR_FALSE; - - PRInt32 i; - for (i=0;iQueryInterface(kIScrollableViewIID, (void **)&scrollableView))) { + scrollableView->GetScrollPosition(offsetx, offsety); + absPoint.x += offsetx; + absPoint.y += offsety; + // Note: scrollableView is not ref counted so it's interface is not NS_RELEASE'd + } + } + mContentFrame->FirstChild(aList, &kid); while (nsnull != kid) { kid->GetRect(kidRect); - if (kidRect.Contains(aPoint)) { - tmp.MoveTo(aPoint.x - kidRect.x, aPoint.y - kidRect.y); + if (kidRect.Contains(absPoint)) { + tmp.MoveTo(absPoint.x - kidRect.x, absPoint.y - kidRect.y); nsIContent * content; kid->GetContent(&content); @@ -218,7 +239,7 @@ nsListControlFrame::GetFrameForPointUsing(const nsPoint& aPoint, kid->GetFrameState(&state); if (NS_FRAME_OUTSIDE_CHILDREN & state) { kid->GetRect(kidRect); - tmp.MoveTo(aPoint.x - kidRect.x, aPoint.y - kidRect.y); + tmp.MoveTo(absPoint.x - kidRect.x, absPoint.y - kidRect.y); if (NS_OK == kid->GetFrameForPoint(tmp, aFrame)) { return NS_OK; } @@ -229,120 +250,130 @@ nsListControlFrame::GetFrameForPointUsing(const nsPoint& aPoint, return NS_ERROR_FAILURE; } -//---------------------------------------------------------------------- -void -nsListControlFrame::PaintChildren(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) -{ - - nsScrollFrame::PaintChildren(aPresContext, - aRenderingContext, - aDirtyRect, aWhichLayer); -} //---------------------------------------------------------------------- -// XXX this needs to properly deal with max element size. percentage based unconstrained widths cannot -// be allowed to return large max element sizes or tables will get too large. +// Reflow is overriden to constrain the listbox height to the number of rows and columns +// specified. +// NS_IMETHODIMP -nsListControlFrame::Reflow(nsIPresContext& aPresContext, +nsListControlFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + // Strategy: Let the inherited reflow happen as though the width and height of the + // ScrollFrame are big enough to allow the listbox to + // shrink to fit the longest option element line in the list. + // The desired width and height returned by the inherited reflow is returned, + // unless one of the following has been specified. + // 1. A css width has been specified. + // 2. The size has been specified. + // 3. The css height has been specified, but the number of rows has not. + // The size attribute overrides the height setting but the height setting + // should be honored if there isn't a size specified. + + // Determine the desired width + height for the listbox + + aDesiredSize.width = 0; + aDesiredSize.height = 0; + + // Initialize the current selected and not selected state's for + // the listbox items from the content if (!mIsInitializedFromContent) { mIsInitializedFromContent = PR_TRUE; InitializeFromContent(PR_TRUE); } + + nsIFrame* childFrame = nsnull; + mContentFrame->FirstChild(nsnull, &childFrame); + PRInt32 numChildren = LengthOf(childFrame); + PRBool needsVerticalScrollbar = (numChildren > mNumRows); + + //--Calculate a width just big enough for the scrollframe to shrink around the + //longest element in the list + //XXX: This is usually dangerous to do this type of coercion. Should it set the + //State back to the original when done??? + nsHTMLReflowState& tempReflowState = (nsHTMLReflowState&)aReflowState; - nsIFrame* childFrame; - - nscoord scrollbarWidth = 0; - nscoord scrollbarHeight = 0; - GetScrollBarDimensions(aPresContext, scrollbarWidth, scrollbarHeight); - - nsFont font(aPresContext.GetDefaultFixedFontDeprecated()); - GetFont(&aPresContext, font); - - nsSize maxSize(aReflowState.availableWidth, aReflowState.availableHeight); - nsHTMLReflowMetrics desiredSize = aDesiredSize; - aDesiredSize.width = 0; - aDesiredSize.height = 0; - - // Calculate the amount of space needed for borders - const nsStyleSpacing* spacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); - nsMargin border; - if (!spacing->GetBorder(border)) { - border.SizeTo(0, 0, 0, 0); - } - + // Get the size of option elements inside the listbox nsSize desiredLineSize; - GetDesiredSize(&aPresContext, aReflowState, aDesiredSize, desiredLineSize); + nsHTMLReflowMetrics desiredSize = aDesiredSize; + // Save original values which will be modified for the reflow state. + // They are set back to their original values at the end of reflow. + nscoord saveComputedWidth = tempReflowState.computedWidth; + nscoord saveAvailableWidth = tempReflowState.availableWidth; - float p2t; - aPresContext.GetScaledPixelsToTwips(&p2t); - nscoord lineEndPadding = NSIntPixelsToTwips(10, p2t);//GetHorizontalInsidePadding(aPresContext, p2t, 0, 0); - aDesiredSize.width += lineEndPadding; + // Compute the width based on the longest line in the listbox. + // XXX: This should be changed to do the inherited reflow unconstrained for + // the width to get the real desired width. GetDesiredSize is limited to + // text strings. + + GetDesiredSize(&aPresContext, aReflowState, desiredSize, desiredLineSize); + // Only set to the desired width if it hasn't been explicitly defined through CSS. + // GetDesiredSize must still be done above to calculate the desired height. + if (NS_UNCONSTRAINEDSIZE == tempReflowState.computedWidth) { + tempReflowState.computedWidth = desiredLineSize.width; + } + + // Retrieve the scrollbar's width and height + float sbWidth = 0.0; + float sbHeight = 0.0;; + nsCOMPtr dc; + aPresContext.GetDeviceContext(getter_AddRefs(dc)); + dc->GetScrollBarDimensions(sbWidth, sbHeight); + // Convert to nscoord's by rounding + nscoord scrollbarWidth = NSToCoordRound(sbWidth); + nscoord scrollbarHeight = NSToCoordRound(sbHeight); - desiredSize = aDesiredSize; - nsIFrame * firstChild = mFrames.FirstChild(); + // Add vertical scrollbar, Always add it in, + // even though the vertical scrollbar is not needed all the time + // the inherited Reflow: allways leave space for the scrollbar by + // shrinking the scroll area by the scrollbar width - nsHTMLReflowState reflowState(aPresContext, aReflowState, firstChild, maxSize); - nsIHTMLReflow* htmlReflow; - if (NS_OK == firstChild->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) { - htmlReflow->WillReflow(aPresContext); - htmlReflow->Reflow(aPresContext, desiredSize, reflowState, aStatus); - NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); + tempReflowState.computedWidth += scrollbarWidth; + + // Now that we have calculated the width required to just shrink around the longest line. + // Go ahead and reflow + + // Do the inherited Reflow. This reflow uses the computed widths which + // are setup above. + + // Don't set the height. Let the height be unconstrained + + nsScrollFrame::Reflow(aPresContext, + aDesiredSize, + tempReflowState, + aStatus); + + // Now that we have reflowed, we may need to adjust the width and height returned + // for the listbox. + + // Set the desired height to the computed height above only if it has not + // been explicitly set by CSS. + if (NS_UNCONSTRAINEDSIZE == tempReflowState.computedHeight) { + aDesiredSize.height = desiredSize.height; } - mContentFrame->FirstChild(nsnull, &childFrame); - PRInt32 numChildren = LengthOf(childFrame); - - aDesiredSize.width += border.left+border.right; - aDesiredSize.height += border.top+border.bottom; - - nscoord insideWidth = aDesiredSize.width-border.left-border.right-1; - if (mInDropDownMode) { + //Need to addback the scrollbar because the inherited reflow + //subtracts the scrollbar width when computing the desired size. + //We don't subtract when there isn't a vertical scrollbar. This may + //seem odd, becuase above we always add in the scrollbar width before calling + //reflow. The reason is that inherited reflow always leaves blank space for + //the scrollbar, but we don't whant that behavior for the listbox'es scrollbars. + if (needsVerticalScrollbar) { aDesiredSize.width += scrollbarWidth; - insideWidth += scrollbarWidth; - } else { - if (mNumRows < numChildren) { - aDesiredSize.width += scrollbarWidth; - } - } - - nsRect rect(0,0, insideWidth, desiredLineSize.height*numChildren); - mContentFrame->SetRect(rect); - - - mContentFrame->FirstChild(nsnull, &childFrame); - nsPoint offset(0,0); - while (nsnull != childFrame) { // reflow, place, size the children - nsHTMLReflowState reflowState(aPresContext, aReflowState, childFrame, maxSize); - nsIHTMLReflow* htmlReflow; - - if (NS_OK == childFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) { - htmlReflow->WillReflow(aPresContext); - htmlReflow->Reflow(aPresContext, desiredSize, reflowState, aStatus); - NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); - //??nsRect rect(offset.x, offset.y, desiredLineSize.width+lineEndPadding, desiredLineSize.height); - nsRect rect(offset.x, offset.y, insideWidth, desiredLineSize.height); - childFrame->SetRect(rect); - childFrame->GetNextSibling(&childFrame); - offset.x = 0; - offset.y += desiredLineSize.height; - } - } - + } + // Set the max element size to be the same as the desired element size. if (nsnull != aDesiredSize.maxElementSize) { - //XXX aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding); aDesiredSize.maxElementSize->width = aDesiredSize.width; aDesiredSize.maxElementSize->height = aDesiredSize.height; } - aStatus = NS_FRAME_COMPLETE; + //XXX: Set the min element size here to the desired element size here?? + // Restore to original reflow state. + tempReflowState.computedWidth = saveComputedWidth; + tempReflowState.availableWidth = saveAvailableWidth; + aStatus = NS_FRAME_COMPLETE; return NS_OK; } @@ -406,21 +437,29 @@ nsListControlFrame::GetFont(nsIPresContext* aPresContext, return NS_OK; } -//---------------------------------------------------------------------- -NS_IMETHODIMP nsListControlFrame::PluggableEventHandler(nsIPresContext& aPresContext, - nsGUIEvent* aEvent, - nsEventStatus& aEventStatus) + +// 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) { - HandleEvent(aPresContext, aEvent, aEventStatus); - //aEventStatus = nsEventStatus_eConsumeNoDefault; - return NS_OK; + nsCOMPtr selectedAtom ( dont_QueryInterface(NS_NewAtom(kMozSelected))); + aContent->SetAttribute(kNameSpaceID_None, selectedAtom, "", PR_TRUE); } -//---------------------------------------------------------------------- -NS_IMETHODIMP nsListControlFrame::PluggableGetFrameForPoint(const nsPoint& aPoint, - nsIFrame** aFrame) +void nsListControlFrame::DisplayDeselected(nsIContent* aContent) { - return GetFrameForPoint(aPoint, aFrame); + nsCOMPtr selectedAtom ( dont_QueryInterface(NS_NewAtom(kMozSelected))); + aContent->UnsetAttribute(kNameSpaceID_None, selectedAtom, PR_TRUE); +} + +void nsListControlFrame::UpdateItem(nsIContent* aContent, PRBool aSelected) +{ + if (aSelected) { + DisplaySelected(aContent); + } else { + DisplayDeselected(aContent); + } } //---------------------------------------------------------------------- @@ -437,8 +476,7 @@ PRInt32 nsListControlFrame::SetContentSelected(nsIFrame * aHitFrame, nsIContent* content; kid->GetContent(&content); aHitContent = content; - nsCOMPtr selectedAtom ( dont_QueryInterface(NS_NewAtom(kMozSelected)) ); - aHitContent->SetAttribute(kNameSpaceID_None, selectedAtom, "", PR_TRUE); + //XXX: DisplaySelected(aHitContent); return index; } kid->GetNextSibling(&kid); @@ -456,10 +494,10 @@ void nsListControlFrame::ClearSelection() while (nsnull != kid) { nsIContent * content; kid->GetContent(&content); - if (mIsFrameSelected[i]) { + if (IsFrameSelected(i)) { if (i != mSelectedIndex) { - content->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kNormal, PR_TRUE); - mIsFrameSelected[i] = PR_FALSE; + DisplayDeselected(content); + SetFrameSelected(i, PR_FALSE); } } NS_RELEASE(content); @@ -494,12 +532,12 @@ void nsListControlFrame::ExtendedSelection(PRInt32 aStartIndex, PRInt32 aEndInde } if (startInverting && ((i != mStartExtendedIndex && aDoInvert) || !aDoInvert)) { if (aDoInvert) { - mIsFrameSelected[i] = !mIsFrameSelected[i]; + SetFrameSelected(i, !IsFrameSelected(i)); } else { - mIsFrameSelected[i] = aSetValue; + SetFrameSelected(i, aSetValue); } if (i != mSelectedIndex) { - content->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, (mIsFrameSelected[i]?kSelected:kNormal), PR_TRUE); + UpdateItem(content, IsFrameSelected(i)); } } if (i == endInx) { @@ -518,9 +556,12 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeListEvent(nsIPresContext& aPresConte { if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) { PRInt32 oldSelectedIndex = mSelectedIndex; + mSelectedIndex = (PRInt32)SetContentSelected(mHitFrame, mHitContent, PR_TRUE); if (-1 < mSelectedIndex) { - PRBool selected = mIsFrameSelected[mSelectedIndex]; + PRBool wasSelected = IsFrameSelected(mSelectedIndex); + SetFrameSelected(mSelectedIndex, PR_TRUE); + PRBool selected = wasSelected; if (mMultipleSelections) { if (((nsMouseEvent *)aEvent)->isShift) { @@ -556,10 +597,11 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeListEvent(nsIPresContext& aPresConte } else if (((nsMouseEvent *)aEvent)->isControl) { selected = !selected; if (nsnull != mSelectedContent) { - if (mHitContent != mSelectedContent) { - mSelectedContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, (mIsFrameSelected[oldSelectedIndex]?kSelected:kNormal), PR_TRUE); + if (mHitContent != mSelectedContent) { + // Toggle the selection + UpdateItem(mHitContent, !wasSelected); } else { - mSelectedContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, (selected?kSelectedFocus:kNormal), PR_TRUE); + //XXX: Fix this mSelectedContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, (selected?kSelectedFocus:kNormal), PR_TRUE); } } } else { @@ -570,13 +612,11 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeListEvent(nsIPresContext& aPresConte } } else { if (nsnull != mSelectedContent) { - nsCOMPtr selectedAtom ( dont_QueryInterface(NS_NewAtom(kMozSelected)) ); - mSelectedContent->UnsetAttribute(kNameSpaceID_None, selectedAtom, PR_TRUE); - //XXX: This needs to a set a psuedo attribute instead mSelectedContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kNormal, PR_TRUE); + DisplayDeselected(mSelectedContent); NS_RELEASE(mSelectedContent); } } - mIsFrameSelected[mSelectedIndex] = selected; + //XXX: Remove SetFrameSelected(mSelectedIndex, selected); //XXX mHitContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, (selected?kSelectedFocus:kNormal), PR_TRUE); mSelectedContent = mHitContent; mSelectedFrame = mHitFrame; @@ -603,7 +643,7 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aP // If the DropDown is currently has a selected item // then clear the selected item if (nsnull != mSelectedContent) { - mSelectedContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kNormal, PR_TRUE); + DisplayDeselected(mSelectedContent); NS_RELEASE(mSelectedContent); } @@ -613,7 +653,7 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aP // Since the new frame is different then clear the selection on the old frame (the current frame) if (nsnull != mCurrentHitContent) { - mCurrentHitContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kNormal, PR_TRUE); + DisplayDeselected(mCurrentHitContent); NS_RELEASE(mCurrentHitContent); } @@ -645,15 +685,15 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aP // Clean up frames before disappearing if (nsnull != mSelectedContent) { - mSelectedContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kNormal, PR_TRUE); + DisplayDeselected(mSelectedContent); NS_RELEASE(mSelectedContent); } if (nsnull != mHitContent) { - mHitContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kNormal, PR_TRUE); + DisplayDeselected(mHitContent); NS_RELEASE(mHitContent); } if (nsnull != mCurrentHitContent) { - mCurrentHitContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kNormal, PR_TRUE); + DisplayDeselected(mCurrentHitContent); NS_RELEASE(mCurrentHitContent); } NS_RELEASE(option); @@ -727,13 +767,10 @@ nsListControlFrame::SetInitialChildList(nsIPresContext& aPresContext, nsIFrame* aChildList) { mContentFrame = aChildList; -#ifdef PLUGGABLE_EVENTS - mContentFrame->SetPluggableEventListener(this); -#endif + if (!mInDropDownMode) { nsFormFrame::AddFormControlFrame(aPresContext, *this); } - //aChildList->FirstChild(nsnull, mContentFrame); if (!mIsInitializedFromContent) { InitializeFromContent(); @@ -742,33 +779,6 @@ nsListControlFrame::SetInitialChildList(nsIPresContext& aPresContext, return nsScrollFrame::SetInitialChildList(aPresContext, aListName, aChildList); } -//---------------------------------------------------------------------- -/*nsresult -nsListControlFrame::AppendNewFrames(nsIPresContext& aPresContext, - nsIFrame* aNewFrame) -{ - return nsScrollFrame::AppendNewFrames(aPresContext, aNewFrame); -} - -//---------------------------------------------------------------------- -nsresult -nsListControlFrame::InsertNewFrame(nsIPresContext& aPresContext, - nsBaseIBFrame* aParentFrame, - nsIFrame* aNewFrame, - nsIFrame* aPrevSibling) -{ - return nsScrollFrame::InsertNewFrame(aPresContext, aParentFrame, aNewFrame, aPrevSibling); -} - -//---------------------------------------------------------------------- -nsresult -nsListControlFrame::DoRemoveFrame(nsBlockReflowState& aState, - nsBaseIBFrame* aParentFrame, - nsIFrame* aDeletedFrame, - nsIFrame* aPrevSibling) -{ - return nsScrollFrame::DoRemoveFrame(aState, aParentFrame, aDeletedFrame, aPrevSibling); -}*/ //---------------------------------------------------------------------- NS_IMETHODIMP @@ -780,13 +790,6 @@ nsListControlFrame::Init(nsIPresContext& aPresContext, { nsresult result = nsScrollFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - /*if (NS_OK == result) { - nsIDOMNode* node; - if (mContent && (NS_OK == mContent->QueryInterface(kIDOMNodeIID, (void**) &node))) { - AddEventListener(node); - NS_RELEASE(node); - } - }*/ if (NS_OK == result) { nsIDOMHTMLSelectElement* select; if (mContent && (NS_OK == mContent->QueryInterface(kIDOMHTMLSelectElementIID, (void**) &select))) { @@ -798,7 +801,6 @@ nsListControlFrame::Init(nsIPresContext& aPresContext, } return result; - } //---------------------------------------------------------------------- @@ -838,31 +840,6 @@ nsListControlFrame::GetSizeFromContent(PRInt32* aSize) const } return result; } -//---------------------------------------------------------------------- -void -nsListControlFrame::GetScrollBarDimensions(nsIPresContext& aPresContext, - nscoord &aWidth, nscoord &aHeight) -{ - - aWidth = 0; - aHeight = 0; - float scale; - nsCOMPtr dx; - aPresContext.GetDeviceContext(getter_AddRefs(dx)); - if (dx) { - float sbWidth; - float sbHeight; - dx->GetCanonicalPixelScale(scale); - dx->GetScrollBarDimensions(sbWidth, sbHeight); - aWidth = PRInt32(sbWidth * scale); - aHeight = PRInt32(sbHeight * scale); - } //else { - //aWidth = 19 * sp2t; - //aHeight = scrollbarWidth; - //} - - -} //---------------------------------------------------------------------- nscoord @@ -883,7 +860,7 @@ nscoord nsListControlFrame::GetVerticalInsidePadding(float aPixToTwip, nscoord aInnerHeight) const { - return NSIntPixelsToTwips(0, aPixToTwip); // XXX this is really + return NSIntPixelsToTwips(0, aPixToTwip); } //---------------------------------------------------------------------- @@ -923,6 +900,8 @@ nsListControlFrame::GetDesiredSize(nsIPresContext* aPresContext, PRInt32 maxWidth = 1; PRUint32 numOptions; options->GetLength(&numOptions); + + for (PRUint32 i = 0; i < numOptions; i++) { nsIDOMHTMLOptionElement* option = GetOption(*options, i); if (option) { @@ -1059,7 +1038,7 @@ nsListControlFrame::AboutToDropDown() if (i == mSelectedIndex) { mSelectedContent = content; mSelectedFrame = kid; - mSelectedContent->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::kClass, kSelected, PR_TRUE); + DisplaySelected(mSelectedContent); return NS_OK; } NS_RELEASE(content); @@ -1069,14 +1048,63 @@ nsListControlFrame::AboutToDropDown() return NS_OK; } + +nsIContent* +nsListControlFrame::GetOptionContent(PRUint32 aIndex) +{ + nsresult result = NS_OK; + nsIDOMHTMLCollection* options = GetOptions(mContent); + nsIDOMHTMLOptionElement* optionElement = GetOption(*options, aIndex); + + nsIContent *content = nsnull; + result = optionElement->QueryInterface(kIContentIID, (void**) &content); + + NS_RELEASE(optionElement); + NS_RELEASE(options); + + if (NS_SUCCEEDED(result)) { + return(content); + } else { + return(nsnull); + } +} + +PRBool +nsListControlFrame::IsFrameSelected(PRUint32 aIndex) +{ + nsIContent* content = GetOptionContent(aIndex); + NS_ASSERTION(nsnull != content, "Failed to retrieve option content"); + nsString value; + nsCOMPtr selectedAtom ( dont_QueryInterface(NS_NewAtom(kMozSelected))); + nsresult result = content->GetAttribute(kNameSpaceID_None, selectedAtom, value); + NS_IF_RELEASE(content); + + if (NS_CONTENT_ATTR_NOT_THERE == result) { + return(PR_FALSE); + } + else { + return(PR_TRUE); + } +} + +void +nsListControlFrame::SetFrameSelected(PRUint32 aIndex, PRBool aSelected) +{ + nsIContent* content = GetOptionContent(aIndex); + NS_ASSERTION(nsnull != content, "Failed to retrieve option content"); + if (aSelected) { + DisplaySelected(content); + } else { + DisplayDeselected(content); + } + NS_IF_RELEASE(content); +} + //---------------------------------------------------------------------- void nsListControlFrame::InitializeFromContent(PRBool aDoDisplay) { PRInt32 i; - for (i=0;iGetDefaultSelected(&selected); - //XXX: Remove, why is selected queried twice here? option->GetSelected(&selected); - mIsFrameSelected[i] = selected; + SetFrameSelected(i, selected); if (mInDropDownMode) { if (selected) { @@ -1106,11 +1133,10 @@ nsListControlFrame::InitializeFromContent(PRBool aDoDisplay) return; } } else { - if (selected && aDoDisplay) { - // 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. - nsCOMPtr selectedAtom ( dont_QueryInterface(NS_NewAtom(kMozSelected))); - content->SetAttribute(kNameSpaceID_None, selectedAtom, "", PR_TRUE); + if (selected && aDoDisplay) { + DisplaySelected(content); + mSelectedContent = content; + NS_ADDREF(content); } } NS_RELEASE(option); @@ -1186,203 +1212,14 @@ nsListControlFrame::Deselect() { PRInt32 i; for (i=0;iGetFont(&aPresContext, font); - nsIDeviceContext* deviceContext = aPresContext.GetDeviceContext(); - nsIFontMetrics* fontMet; - deviceContext->GetMetricsFor(font, fontMet); - aRendContext->SetFont(fontMet); - aRendContext->GetWidth(aString, aSize.width); - fontMet->GetHeight(aSize.height); - - char char1, char2; - nsCompatibility mode = nsFormControlHelper::GetRepChars(aPresContext, char1, char2); - nscoord char1Width, char2Width; - aRendContext->GetWidth(char1, char1Width); - aRendContext->GetWidth(char2, char2Width); - - NS_RELEASE(fontMet); - NS_RELEASE(deviceContext); - - if (eCompatibility_Standard == mode) { - return ((char1Width + char2Width) / 2) + 1; - } else { - return char1Width; - } -} - -//------------------------------------------------------------------ -nscoord -nsListControlFrame::GetTextSize(nsIPresContext& aPresContext, nsListControlFrame* aFrame, - PRInt32 aNumChars, nsSize& aSize, - nsIRenderingContext *aRendContext) -{ - nsAutoString val; - char char1, char2; - nsFormControlHelper::GetRepChars(aPresContext, char1, char2); - int i; - for (i = 0; i < aNumChars; i+=2) { - val += char1; - } - for (i = 1; i < aNumChars; i+=2) { - val += char2; - } - return GetTextSize(aPresContext, aFrame, val, aSize, aRendContext); -} - -//------------------------------------------------------------------ -PRInt32 -nsListControlFrame::CalculateSize (nsIPresContext* aPresContext, nsListControlFrame* aFrame, - const nsSize& aCSSSize, nsInputDimensionSpec& aSpec, - nsSize& aBounds, PRBool& aWidthExplicit, - PRBool& aHeightExplicit, nscoord& aRowHeight, - nsIRenderingContext *aRendContext) -{ - nscoord charWidth = 0; - PRInt32 numRows = ATTR_NOTSET; - aWidthExplicit = PR_FALSE; - aHeightExplicit = PR_FALSE; - - aBounds.width = CSS_NOTSET; - aBounds.height = CSS_NOTSET; - nsSize textSize(0,0); - - nsIContent* iContent = nsnull; - aFrame->GetContent((nsIContent*&) iContent); - if (!iContent) { - return 0; - } - nsIHTMLContent* hContent = nsnull; - nsresult result = iContent->QueryInterface(kIHTMLContentIID, (void**)&hContent); - if ((NS_OK != result) || !hContent) { - NS_RELEASE(iContent); - return 0; - } - nsAutoString valAttr; - nsresult valStatus = NS_CONTENT_ATTR_NOT_THERE; - if (nsnull != aSpec.mColValueAttr) { - valStatus = hContent->GetAttribute(kNameSpaceID_HTML, aSpec.mColValueAttr, valAttr); - } - nsHTMLValue colAttr; - nsresult colStatus = NS_CONTENT_ATTR_NOT_THERE; - if (nsnull != aSpec.mColSizeAttr) { - colStatus = hContent->GetHTMLAttribute(aSpec.mColSizeAttr, colAttr); - } - float p2t; - aPresContext->GetScaledPixelsToTwips(p2t); - - // determine the width - nscoord adjSize; - if (NS_CONTENT_ATTR_HAS_VALUE == colStatus) { // col attr will provide width - PRInt32 col = ((colAttr.GetUnit() == eHTMLUnit_Pixel) ? colAttr.GetPixelValue() : colAttr.GetIntValue()); - if (aSpec.mColSizeAttrInPixels) { - col = (col <= 0) ? 15 : col; - aBounds.width = NSIntPixelsToTwips(col, p2t); - } - else { - col = (col <= 0) ? 1 : col; - charWidth = GetTextSize(*aPresContext, aFrame, col, aBounds, aRendContext); - aRowHeight = aBounds.height; // XXX aBounds.height has CSS_NOTSET - } - if (aSpec.mColSizeAttrInPixels) { - aWidthExplicit = PR_TRUE; - } - } - else { - if (CSS_NOTSET != aCSSSize.width) { // css provides width - aBounds.width = (aCSSSize.width > 0) ? aCSSSize.width : 1; - aWidthExplicit = PR_TRUE; - } - else { - if (NS_CONTENT_ATTR_HAS_VALUE == valStatus) { // use width of initial value - charWidth = GetTextSize(*aPresContext, aFrame, valAttr, aBounds, aRendContext); - } - else if (aSpec.mColDefaultValue) { // use default value - charWidth = GetTextSize(*aPresContext, aFrame, *aSpec.mColDefaultValue, aBounds, aRendContext); - } - else if (aSpec.mColDefaultSizeInPixels) { // use default width in pixels - charWidth = GetTextSize(*aPresContext, aFrame, 1, aBounds, aRendContext); - aBounds.width = aSpec.mColDefaultSize; - } - else { // use default width in num characters - charWidth = GetTextSize(*aPresContext, aFrame, aSpec.mColDefaultSize, aBounds, aRendContext); - } - aRowHeight = aBounds.height; // XXX aBounds.height has CSS_NOTSET - } - } - - // determine the height - nsHTMLValue rowAttr; - nsresult rowStatus = NS_CONTENT_ATTR_NOT_THERE; - if (nsnull != aSpec.mRowSizeAttr) { - rowStatus = hContent->GetHTMLAttribute(aSpec.mRowSizeAttr, rowAttr); - } - if (NS_CONTENT_ATTR_HAS_VALUE == rowStatus) { // row attr will provide height - PRInt32 rowAttrInt = ((rowAttr.GetUnit() == eHTMLUnit_Pixel) ? rowAttr.GetPixelValue() : rowAttr.GetIntValue()); - adjSize = (rowAttrInt > 0) ? rowAttrInt : 1; - if (0 == charWidth) { - charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); - aBounds.height = textSize.height * adjSize; - aRowHeight = textSize.height; - numRows = adjSize; - } - else { - aBounds.height = aBounds.height * adjSize; - } - } - else if (CSS_NOTSET != aCSSSize.height) { // css provides height - aBounds.height = (aCSSSize.height > 0) ? aCSSSize.height : 1; - aHeightExplicit = PR_TRUE; - } - else { // use default height in num lines - if (0 == charWidth) { - charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); - aBounds.height = textSize.height * aSpec.mRowDefaultSize; - aRowHeight = textSize.height; - } - else { - aBounds.height = aBounds.height * aSpec.mRowDefaultSize; - } - } - - if ((0 == charWidth) || (0 == textSize.width)) { - charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); - aRowHeight = textSize.height; - } - - // add inside padding if necessary - if (!aWidthExplicit) { - aBounds.width += (2 * aFrame->GetHorizontalInsidePadding(*aPresContext, p2t, aBounds.width, charWidth)); - } - if (!aHeightExplicit) { - aBounds.height += (2 * aFrame->GetVerticalInsidePadding(p2t, textSize.height)); - } - - NS_RELEASE(hContent); - if (ATTR_NOTSET == numRows) { - numRows = aBounds.height / aRowHeight; - } - - NS_RELEASE(iContent); - return numRows; -} - -#endif //---------------------------------------------------------------------- //---------------------------------------------------------------------- @@ -1407,17 +1244,6 @@ nsListControlFrame::GetSkipSides() const NS_IMETHODIMP nsListControlFrame::GetType(PRInt32* aType) const { - /*nsresult result = NS_FORM_NOTOK; - if (mContent) { - nsIFormControl* formControl = nsnull; - result = mContent->QueryInterface(kIFormControlIID, (void**)&formControl); - if ((NS_OK == result) && formControl) { - result = formControl->GetType(aType); - NS_RELEASE(formControl); - } - } - return result; - */ *aType = NS_FORM_SELECT; return NS_OK; } @@ -1440,15 +1266,8 @@ nsListControlFrame::IsSuccessful(nsIFormControlFrame* aSubmitter) void nsListControlFrame::MouseClicked(nsIPresContext* aPresContext) { - /*nsIRadioButton* radioWidget; - if (mWidget && (NS_OK == mWidget->QueryInterface(kIRadioIID, (void**)&radioWidget))) { - radioWidget->SetState(PR_TRUE); - NS_RELEASE(radioWidget); - if (mFormFrame) { - mFormFrame->OnRadioChecked(*this); - } - }*/ } + //---------------------------------------------------------------------- PRInt32 nsListControlFrame::GetMaxNumValues() @@ -1488,7 +1307,7 @@ nsListControlFrame::Reset() PRBool selected = PR_FALSE; option->GetSelected(&selected); if (selected) { - mIsFrameSelected[i] = PR_TRUE; + SetFrameSelected(i, PR_TRUE); } NS_RELEASE(option); } @@ -1518,16 +1337,6 @@ nsListControlFrame::GetName(nsString* aResult) } return result; } - - -//---------------------------------------------------------------------- -/*PRBool -nsListControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames) -{ - aNumValues = 0; - return PR_FALSE; -}*/ //---------------------------------------------------------------------- PRBool @@ -1554,7 +1363,7 @@ nsListControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, PRInt32 i = 0; PRInt32 inx; for (inx=0;iQueryInterface(kIDOMNodeIID, (void**) &node))) { - RemoveEventListener(node); - NS_RELEASE(node); - } - return nsScrollFrame::DeleteFrame(aPresContext); - -} -//----------------------------------------------------------------- -nsresult nsListControlFrame::Focus(nsIDOMEvent* aEvent) -{ - return NS_OK; -} - -//----------------------------------------------------------------- -nsresult nsListControlFrame::Blur(nsIDOMEvent* aEvent) -{ - return NS_OK; -} - -//----------------------------------------------------------------- -nsresult nsListControlFrame::ProcessEvent(nsIDOMEvent* aEvent) -{ - return NS_OK; -} - -//----------------------------------------------------------------- -NS_IMETHODIMP nsListControlFrame::AddEventListener(nsIDOMNode * aNode) -{ - nsIDOMEventReceiver * receiver; - - if (NS_OK == aNode->QueryInterface(kIDOMEventReceiverIID, (void**) &receiver)) { - receiver->AddEventListener((nsIDOMFocusListener*)this, kIDOMFocusListenerIID); - NS_RELEASE(receiver); - return NS_OK; - } - return NS_ERROR_FAILURE; -} - -//----------------------------------------------------------------- -NS_IMETHODIMP nsListControlFrame::RemoveEventListener(nsIDOMNode * aNode) -{ - nsIDOMEventReceiver * receiver; - - if (NS_OK == aNode->QueryInterface(kIDOMEventReceiverIID, (void**) &receiver)) { - receiver->RemoveEventListener(this, kIDOMFocusListenerIID); - NS_RELEASE(receiver); - return NS_OK; - } - return NS_ERROR_FAILURE; -} -#endif diff --git a/layout/html/forms/src/nsListControlFrame.h b/layout/html/forms/src/nsListControlFrame.h index 738817b089cd..803fc8f3f543 100644 --- a/layout/html/forms/src/nsListControlFrame.h +++ b/layout/html/forms/src/nsListControlFrame.h @@ -23,11 +23,9 @@ #include "nsIDOMFocusListener.h" #include "nsIPresContext.h" #include "nsIFormControlFrame.h" -#ifdef PLUGGABLE_EVENTS -#include "nsIPluggableEventListener.h" -#endif #include "nsIListControlFrame.h" + class nsIDOMHTMLSelectElement; class nsIDOMHTMLCollection; class nsIDOMHTMLOptionElement; @@ -35,33 +33,7 @@ class nsFormFrame; class nsScrollFrame; class nsIComboboxControlFrame; -#if 0 -struct nsInputDimSpec -{ - nsIAtom* mColSizeAttr; // attribute used to determine width - PRBool mColSizeAttrInPixels; // is attribute value in pixels (otherwise num chars) - nsIAtom* mColValueAttr; // attribute used to get value to determine size - // if not determined above - nsString* mColDefaultValue; // default value if not determined above - nscoord mColDefaultSize; // default width if not determined above - PRBool mColDefaultSizeInPixels; // is default width in pixels (otherswise num chars) - nsIAtom* mRowSizeAttr; // attribute used to determine height - nscoord mRowDefaultSize; // default height if not determined above - nsInputDimSpec(nsIAtom* aColSizeAttr, PRBool aColSizeAttrInPixels, - nsIAtom* aColValueAttr, nsString* aColDefaultValue, - nscoord aColDefaultSize, PRBool aColDefaultSizeInPixels, - nsIAtom* aRowSizeAttr, nscoord aRowDefaultSize) - : mColSizeAttr(aColSizeAttr), mColSizeAttrInPixels(aColSizeAttrInPixels), - mColValueAttr(aColValueAttr), - mColDefaultValue(aColDefaultValue), mColDefaultSize(aColDefaultSize), - mColDefaultSizeInPixels(aColDefaultSizeInPixels), - mRowSizeAttr(aRowSizeAttr), mRowDefaultSize(aRowDefaultSize) - { - } - -}; -#endif /** * The block frame has two additional named child lists: * - "Floater-list" which contains the floated frames @@ -71,11 +43,8 @@ struct nsInputDimSpec * @see nsLayoutAtoms::floaterList */ class nsListControlFrame : public nsScrollFrame, - public nsIFormControlFrame, - public nsIListControlFrame -#ifdef PLUGGABLE_EVENTS - public nsIPluggableEventListener -#endif + public nsIFormControlFrame, + public nsIListControlFrame { public: friend nsresult NS_NewListControlFrame(nsIFrame*& aNewFrame); @@ -101,20 +70,6 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); - // -/* virtual nsresult AppendNewFrames(nsIPresContext& aPresContext, nsIFrame*); - - virtual nsresult InsertNewFrame(nsIPresContext& aPresContext, - nsBaseIBFrame* aParentFrame, - nsIFrame* aNewFrame, - nsIFrame* aPrevSibling); - - virtual nsresult DoRemoveFrame(nsBlockReflowState& aState, - nsBaseIBFrame* aParentFrame, - nsIFrame* aDeletedFrame, - nsIFrame* aPrevSibling); - */ - NS_IMETHOD Init(nsIPresContext& aPresContext, nsIContent* aContent, nsIFrame* aParent, @@ -127,24 +82,10 @@ public: NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); - -#if 0 - virtual void GetStyleSize(nsIPresContext& aContext, - const nsHTMLReflowState& aReflowState, - nsSize& aSize); -#endif - virtual void GetDesiredSize(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredLayoutSize, nsSize& aDesiredWidgetSize); -#if 0 - nscoord CalculateSize (nsIPresContext* aPresContext, nsListControlFrame* aFrame, - const nsSize& aCSSSize, nsInputDimSpec& aDimensionSpec, - nsSize& aBounds, PRBool& aWidthExplicit, - PRBool& aHeightExplicit, nscoord& aRowSize, - nsIRenderingContext *aRendContext); -#endif /*virtual nsresult Focus(nsIDOMEvent* aEvent); virtual nsresult Blur(nsIDOMEvent* aEvent); @@ -156,21 +97,9 @@ public: NS_METHOD GetMultiple(PRBool* aResult, nsIDOMHTMLSelectElement* aSelect = nsnull); - ///XXX: End o the temporary methods -#if 0 - nscoord GetTextSize(nsIPresContext& aContext, nsListControlFrame* aFrame, - const nsString& aString, nsSize& aSize, - nsIRenderingContext *aRendContext); - - nscoord GetTextSize(nsIPresContext& aContext, nsListControlFrame* aFrame, - PRInt32 aNumChars, nsSize& aSize, - nsIRenderingContext *aRendContext); -#endif virtual nsresult GetSizeFromContent(PRInt32* aSize) const; NS_IMETHOD GetMaxLength(PRInt32* aSize); - static void GetScrollBarDimensions(nsIPresContext& aPresContext, - nscoord &aWidth, nscoord &aHeight); virtual nscoord GetVerticalBorderWidth(float aPixToTwip) const; virtual nscoord GetHorizontalBorderWidth(float aPixToTwip) const; virtual nscoord GetVerticalInsidePadding(float aPixToTwip, @@ -205,7 +134,7 @@ public: NS_IMETHOD GetName(nsString* aName); virtual void SetFocus(PRBool aOn = PR_TRUE, PRBool aRepaint = PR_FALSE); - + virtual void MouseClicked(nsIPresContext* aPresContext); virtual void Reset(); @@ -219,26 +148,21 @@ public: virtual void SetFormFrame(nsFormFrame* aFrame); - // nsIPluggableEventListener - NS_IMETHOD PluggableEventHandler(nsIPresContext& aPresContext, - nsGUIEvent* aEvent, - nsEventStatus& aEventStatus); - - NS_IMETHOD PluggableGetFrameForPoint(const nsPoint& aPoint, - nsIFrame** aFrame); - // nsIListControlFrame NS_IMETHOD SetComboboxFrame(nsIFrame* aComboboxFrame); NS_IMETHOD GetSelectedItem(nsString & aStr); NS_IMETHOD AboutToDropDown(); - // Static Methods static nsIDOMHTMLSelectElement* GetSelect(nsIContent * aContent); static nsIDOMHTMLCollection* GetOptions(nsIContent * aContent, nsIDOMHTMLSelectElement* aSelect = nsnull); static nsIDOMHTMLOptionElement* GetOption(nsIDOMHTMLCollection& aOptions, PRUint32 aIndex); static PRBool GetOptionValue(nsIDOMHTMLCollection& aCollecton, PRUint32 aIndex, nsString& aValue); + nsIContent* GetOptionContent(PRUint32 aIndex); + PRBool IsFrameSelected(PRUint32 aIndex); + void SetFrameSelected(PRUint32 aIndex, PRBool aSelected); + protected: nsListControlFrame(); virtual ~nsListControlFrame(); @@ -249,12 +173,14 @@ protected: nsIAtom* aList, nsIFrame** aFrame); - // nsHTMLContainerFrame overrides - virtual void PaintChildren(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); + // Utility methods + void DisplaySelected(nsIContent* aContent); + void DisplayDeselected(nsIContent* aContent); + void UpdateItem(nsIContent* aContent, PRBool aSelected); + + // nsHTMLContainerFrame overrides + void ClearSelection(); void InitializeFromContent(PRBool aDoDisplay = PR_FALSE); @@ -272,35 +198,26 @@ protected: // Data Members nsFormFrame* mFormFrame; - PRInt32 mNumRows; - - PRBool mIsFrameSelected[64]; +//XXX: TODO: This should not be hardcoded to 64 +//ZZZ PRBool mIsFrameSelected[64]; PRInt32 mNumSelections; PRInt32 mMaxNumSelections; PRBool mMultipleSelections; - - - //nsIContent * mSelectedContent; PRInt32 mSelectedIndex; PRInt32 mStartExtendedIndex; PRInt32 mEndExtendedIndex; - - nsIFrame * mHitFrame; + nsIFrame * mHitFrame; nsIContent * mHitContent; - - nsIFrame * mCurrentHitFrame; + nsIFrame * mCurrentHitFrame; nsIContent * mCurrentHitContent; - - nsIFrame * mSelectedFrame; + nsIFrame * mSelectedFrame; nsIContent * mSelectedContent; - PRBool mIsInitializedFromContent; - - nsIFrame * mContentFrame; - PRBool mInDropDownMode; + nsIFrame * mContentFrame; + PRBool mInDropDownMode; nsIComboboxControlFrame * mComboboxFrame; - nsString mSelectionStr; + nsString mSelectionStr; }; diff --git a/layout/html/style/src/nsCSSFrameConstructor.cpp b/layout/html/style/src/nsCSSFrameConstructor.cpp index 9b72d21e001c..3065a3b545f2 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -1721,82 +1721,86 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresContext* aPresContext, PRBool aIsFixedPositioned, nsAbsoluteItems& aFixedItems) { +#define NS_FRAME_BASED_COMBO_WORKS 0 nsresult rv = NS_OK; nsWidgetRendering mode; aPresContext->GetWidgetRenderingMode(&mode); -//XXX: When frame-based rendering works uncomment this and remove the line below -// if (eWidgetRendering_Gfx == mode) { - if (0) { + + if (eWidgetRendering_Gfx == mode) { nsIDOMHTMLSelectElement* select = nsnull; PRInt32 size = 1; nsresult result = aContent->QueryInterface(kIDOMHTMLSelectElementIID, (void**)&select); if (NS_OK == result) { result = select->GetSize(&size); if (1 == size) { - nsIFrame * comboboxFrame; - rv = NS_NewComboboxControlFrame(comboboxFrame); - nsIComboboxControlFrame* comboBox; - if (NS_OK == comboboxFrame->QueryInterface(kIComboboxControlFrameIID, (void**)&comboBox)) { + if (! NS_FRAME_BASED_COMBO_WORKS) { + rv = NS_NewSelectControlFrame(aNewFrame); + } else { + nsIFrame * comboboxFrame; + rv = NS_NewComboboxControlFrame(comboboxFrame); + nsIComboboxControlFrame* comboBox; + if (NS_OK == comboboxFrame->QueryInterface(kIComboboxControlFrameIID, (void**)&comboBox)) { - nsIFrame * listFrame; - rv = NS_NewListControlFrame(listFrame); + nsIFrame * listFrame; + rv = NS_NewListControlFrame(listFrame); - // 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); + // 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); + } + + InitializeScrollFrame(listFrame, aPresContext, aContent, comboboxFrame, aStyleContext, + aAbsoluteItems, aNewFrame, aFixedItems, aIsAbsolutelyPositioned, + aIsFixedPositioned, PR_TRUE); + + nsIFrame* placeholderFrame; + + CreatePlaceholderFrameFor(aPresContext, aContent, aNewFrame, aStyleContext, + aParentFrame, placeholderFrame); + + // Add the absolutely positioned frame to its containing block's list + // of child frames + if (aIsAbsolutelyPositioned) + aAbsoluteItems.AddChild(aNewFrame); + + 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 + //XXX: What should happend if resolving the pseudo style fails? + nsCOMPtr visiblePseudoStyle; + aPresContext->ResolvePseudoStyleContextFor + (aContent, nsHTMLAtoms::dropDownVisible, aStyleContext, PR_FALSE, + getter_AddRefs(visiblePseudoStyle)); + + nsCOMPtr hiddenPseudoStyle; + aPresContext->ResolvePseudoStyleContextFor + (aContent, nsHTMLAtoms::dropDownHidden, aStyleContext, PR_FALSE, + getter_AddRefs(hiddenPseudoStyle)); + + 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); + + aProcessChildren = PR_FALSE; + nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, listFrame, + aStyleContext, PR_TRUE); + aNewFrame = comboboxFrame; } - - InitializeScrollFrame(listFrame, aPresContext, aContent, comboboxFrame, aStyleContext, - aAbsoluteItems, aNewFrame, aFixedItems, aIsAbsolutelyPositioned, - aIsFixedPositioned, PR_TRUE); - - nsIFrame* placeholderFrame; - - CreatePlaceholderFrameFor(aPresContext, aContent, aNewFrame, aStyleContext, - aParentFrame, placeholderFrame); - - // Add the absolutely positioned frame to its containing block's list - // of child frames - if (aIsAbsolutelyPositioned) - aAbsoluteItems.AddChild(aNewFrame); - - 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 - //XXX: What should happend if resolving the pseudo style fails? - nsCOMPtr visiblePseudoStyle; - aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::dropDownVisible, aStyleContext, PR_FALSE, - getter_AddRefs(visiblePseudoStyle)); - - nsCOMPtr hiddenPseudoStyle; - aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::dropDownHidden, aStyleContext, PR_FALSE, - getter_AddRefs(hiddenPseudoStyle)); - - 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); - - aProcessChildren = PR_FALSE; - nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, listFrame, - aStyleContext, PR_TRUE); - aNewFrame = comboboxFrame; } } else { diff --git a/layout/style/ua.css b/layout/style/ua.css index ed3c98541586..77eaebae3cc6 100644 --- a/layout/style/ua.css +++ b/layout/style/ua.css @@ -664,6 +664,7 @@ select { color:black; } option { + display:block; } option.selected { @@ -673,8 +674,8 @@ option.selected { } option[-moz-option-selected] { - color:blue; - background-color:green; + color:white; + background-color: rgb(0,0,128); } option.selectedfocus { diff --git a/webshell/tests/viewer/makefile.win b/webshell/tests/viewer/makefile.win index 196ffd563225..a2c163a3cc31 100644 --- a/webshell/tests/viewer/makefile.win +++ b/webshell/tests/viewer/makefile.win @@ -151,6 +151,7 @@ install:: $(PROGRAM) $(MAKE_INSTALL) samples\test13.html $(DIST)\bin\res\samples $(MAKE_INSTALL) samples\test_pr.html $(DIST)\bin\res\samples $(MAKE_INSTALL) samples\test_gfx.html $(DIST)\bin\res\samples + $(MAKE_INSTALL) samples\test_lbox.html $(DIST)\bin\res\samples $(MAKE_INSTALL) samples\toolbarTest1.xul $(DIST)\bin\res\samples $(MAKE_INSTALL) samples\treeTest1.xul $(DIST)\bin\res\samples $(MAKE_INSTALL) samples\xulTest.css $(DIST)\bin\res\samples @@ -202,6 +203,7 @@ clobber:: rm -f $(DIST)\bin\res\samples\test12.html rm -f $(DIST)\bin\res\samples\test_pr.html rm -f $(DIST)\bin\res\samples\test_gfx.html + rm -f $(DIST)\bin\res\samples\test_lbox.html rm -f $(DIST)\bin\res\throbber\anim.gif rm -f $(DIST)\bin\res\throbber\anims00.gif rm -f $(DIST)\bin\res\throbber\anims01.gif diff --git a/webshell/tests/viewer/samples/test_lbox.html b/webshell/tests/viewer/samples/test_lbox.html new file mode 100644 index 000000000000..dc69c5aeb7e6 --- /dev/null +++ b/webshell/tests/viewer/samples/test_lbox.html @@ -0,0 +1,63 @@ + + +
+

Side by Side listboxes

(left - single select, right - multiselect) +
+ + +
+

This listbox should be on a new line with now scrollbars +
+ +
+

This listbox has a specified width of 500px +
+ +
+ +

This listbox has a specified height of 100px +
+ +
+ +

This listbox should have 5pixel red inset borders +

the first option has orange text. +

the second option has yellow text. +
+ +
+ + + +