diff --git a/content/html/content/src/nsHTMLAtoms.cpp b/content/html/content/src/nsHTMLAtoms.cpp index 026b7f7351dc..a49ce9e24611 100644 --- a/content/html/content/src/nsHTMLAtoms.cpp +++ b/content/html/content/src/nsHTMLAtoms.cpp @@ -211,6 +211,7 @@ nsIAtom* nsHTMLAtoms::pre; nsIAtom* nsHTMLAtoms::processingInstructionPseudo; nsIAtom* nsHTMLAtoms::profile; nsIAtom* nsHTMLAtoms::prompt; +nsIAtom* nsHTMLAtoms::radioPseudo; nsIAtom* nsHTMLAtoms::readonly; nsIAtom* nsHTMLAtoms::rel; nsIAtom* nsHTMLAtoms::repeat; @@ -481,6 +482,7 @@ void nsHTMLAtoms::AddrefAtoms() processingInstructionPseudo = NS_NewAtom(":-moz-pi"); profile = NS_NewAtom("profile"); prompt = NS_NewAtom("prompt"); + radioPseudo = NS_NewAtom(":-moz-radio"); readonly = NS_NewAtom("readonly"); rel = NS_NewAtom("rel"); repeat = NS_NewAtom("repeat"); @@ -740,6 +742,7 @@ void nsHTMLAtoms::ReleaseAtoms() NS_RELEASE(processingInstructionPseudo); NS_RELEASE(profile); NS_RELEASE(prompt); + NS_RELEASE(radioPseudo); NS_RELEASE(readonly); NS_RELEASE(rel); NS_RELEASE(repeat); diff --git a/content/html/content/src/nsHTMLAtoms.h b/content/html/content/src/nsHTMLAtoms.h index eb556d3dbd18..9dff9cbb1e61 100644 --- a/content/html/content/src/nsHTMLAtoms.h +++ b/content/html/content/src/nsHTMLAtoms.h @@ -243,7 +243,8 @@ public: static nsIAtom* processingInstructionPseudo; static nsIAtom* profile; static nsIAtom* prompt; - + + static nsIAtom* radioPseudo; static nsIAtom* readonly; static nsIAtom* rel; static nsIAtom* repeat; diff --git a/content/shared/public/nsHTMLAtoms.h b/content/shared/public/nsHTMLAtoms.h index eb556d3dbd18..9dff9cbb1e61 100644 --- a/content/shared/public/nsHTMLAtoms.h +++ b/content/shared/public/nsHTMLAtoms.h @@ -243,7 +243,8 @@ public: static nsIAtom* processingInstructionPseudo; static nsIAtom* profile; static nsIAtom* prompt; - + + static nsIAtom* radioPseudo; static nsIAtom* readonly; static nsIAtom* rel; static nsIAtom* repeat; diff --git a/content/shared/src/nsHTMLAtoms.cpp b/content/shared/src/nsHTMLAtoms.cpp index 026b7f7351dc..a49ce9e24611 100644 --- a/content/shared/src/nsHTMLAtoms.cpp +++ b/content/shared/src/nsHTMLAtoms.cpp @@ -211,6 +211,7 @@ nsIAtom* nsHTMLAtoms::pre; nsIAtom* nsHTMLAtoms::processingInstructionPseudo; nsIAtom* nsHTMLAtoms::profile; nsIAtom* nsHTMLAtoms::prompt; +nsIAtom* nsHTMLAtoms::radioPseudo; nsIAtom* nsHTMLAtoms::readonly; nsIAtom* nsHTMLAtoms::rel; nsIAtom* nsHTMLAtoms::repeat; @@ -481,6 +482,7 @@ void nsHTMLAtoms::AddrefAtoms() processingInstructionPseudo = NS_NewAtom(":-moz-pi"); profile = NS_NewAtom("profile"); prompt = NS_NewAtom("prompt"); + radioPseudo = NS_NewAtom(":-moz-radio"); readonly = NS_NewAtom("readonly"); rel = NS_NewAtom("rel"); repeat = NS_NewAtom("repeat"); @@ -740,6 +742,7 @@ void nsHTMLAtoms::ReleaseAtoms() NS_RELEASE(processingInstructionPseudo); NS_RELEASE(profile); NS_RELEASE(prompt); + NS_RELEASE(radioPseudo); NS_RELEASE(readonly); NS_RELEASE(rel); NS_RELEASE(repeat); diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index e78dc10f274b..89a4d5028a8a 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -49,6 +49,7 @@ #include "nsLayoutAtoms.h" #include "nsIDOMHTMLSelectElement.h" #include "nsIComboboxControlFrame.h" +#include "nsIRadioControlFrame.h" #include "nsIListControlFrame.h" #include "nsIDOMCharacterData.h" #include "nsIDOMHTMLImageElement.h" @@ -122,6 +123,7 @@ static NS_DEFINE_IID(kIWebShellIID, NS_IWEB_SHELL_IID); static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID); static NS_DEFINE_IID(kIComboboxControlFrameIID, NS_ICOMBOBOXCONTROLFRAME_IID); +static NS_DEFINE_IID(kIRadioControlFrameIID, NS_IRADIOCONTROLFRAME_IID); static NS_DEFINE_IID(kIListControlFrameIID, NS_ILISTCONTROLFRAME_IID); static NS_DEFINE_IID(kIDOMHTMLImageElementIID, NS_IDOMHTMLIMAGEELEMENT_IID); static NS_DEFINE_IID(kIDOMCharacterDataIID, NS_IDOMCHARACTERDATA_IID); @@ -765,7 +767,7 @@ nsCSSFrameConstructor::CreateInputFrame(nsIPresContext *aPresContext, rv = ConstructTextControlFrame(aPresContext, aFrame); } else if (val.EqualsIgnoreCase("radio")) { - rv = NS_NewRadioControlFrame(&aFrame); + rv = ConstructRadioControlFrame(aPresContext, aFrame, aContent); } else if (val.EqualsIgnoreCase("text")) { rv = ConstructTextControlFrame(aPresContext, aFrame); @@ -2233,6 +2235,23 @@ nsCSSFrameConstructor::CreatePlaceholderFrameFor(nsIPresContext* aPresContext, return rv; } +nsresult +nsCSSFrameConstructor::ConstructRadioControlFrame(nsIPresContext* aPresContext, + nsIFrame*& aNewFrame, + nsIContent* aContent) +{ + nsresult rv = NS_NewRadioControlFrame(&aNewFrame); + nsCOMPtr radioStyle; + aPresContext->ResolvePseudoStyleContextFor(aContent, nsHTMLAtoms::radioPseudo, + radioStyle, PR_FALSE, getter_AddRefs(radioStyle)); + nsIRadioControlFrame* radio = nsnull; + if (NS_SUCCEEDED(aNewFrame->QueryInterface(kIRadioControlFrameIID, (void**)&radio))) { + radio->SetRadioButtonFaceStyleContext(radioStyle); + NS_RELEASE(radio); + } + return rv; +} + nsresult nsCSSFrameConstructor::ConstructTextControlFrame(nsIPresContext* aPresContext, nsIFrame*& aNewFrame) @@ -2711,7 +2730,7 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresContext* aPresContext, else if (aTag == nsXULAtoms::fontpicker) rv = NS_NewFontPickerFrame(&newFrame); else if (aTag == nsXULAtoms::radio) - rv = NS_NewRadioControlFrame(&newFrame); + rv = ConstructRadioControlFrame(aPresContext, newFrame, aContent); else if (aTag == nsXULAtoms::text) rv = ConstructTextControlFrame(aPresContext, newFrame); else if (aTag == nsXULAtoms::widget) diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index 3a42487d4ea5..5518b71d2b13 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -380,6 +380,9 @@ protected: nsIFrame* aParentFrame, nsIFrame*& aFrame); + nsresult ConstructRadioControlFrame(nsIPresContext* aPresContext, + nsIFrame*& aNewFrame, + nsIContent* aContent); nsresult ConstructTextControlFrame(nsIPresContext* aPresContext, nsIFrame*& aNewFrame); diff --git a/layout/forms/nsIRadioControlFrame.h b/layout/forms/nsIRadioControlFrame.h new file mode 100644 index 000000000000..2e116cde5197 --- /dev/null +++ b/layout/forms/nsIRadioControlFrame.h @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#ifndef nsIRadioControlFrame_h___ +#define nsIRadioControlFrame_h___ + +#include "nsISupports.h" +class nsIStyleContext; + +// IID for the nsIRadioControlFrame class +// {06450E00-24D9-11d3-966B-00105A1B1B76} +#define NS_IRADIOCONTROLFRAME_IID \ +{ 0x6450e00, 0x24d9, 0x11d3, \ + { 0x96, 0x6b, 0x0, 0x10, 0x5a, 0x1b, 0x1b, 0x76 } } + + +/** + * nsIRadioControlFrame is the common interface radio buttons. + * @see nsFromControlFrame and its base classes for more info + */ +class nsIRadioControlFrame : public nsISupports { + +public: + + /** + * Sets the Pseudo Style Contexts for the Radio button + * + */ + NS_IMETHOD SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioButtonFaceStyleContext) = 0; +}; + +#endif + diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index 7ce48e1c7c1d..8fda0934ebca 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/layout/forms/nsListControlFrame.cpp @@ -126,7 +126,7 @@ nsListControlFrame::GetFrameForPoint(const nsPoint& aPoint, nsIFrame** aFrame) // on in the HandleEvent. The GetFrameForPointUsing is always called before the HandleEvent. // nsresult rv; - + mHitFrame = nsnull; nsIFrame *childFrame; FirstChild(nsnull, &childFrame); rv = GetFrameForPointUsing(aPoint, nsnull, aFrame); @@ -424,7 +424,7 @@ nsListControlFrame::Reflow(nsIPresContext& aPresContext, aStatus = NS_FRAME_COMPLETE; mDisplayed = PR_TRUE; - + return NS_OK; } @@ -766,12 +766,15 @@ nsListControlFrame :: CaptureMouseEvents(PRBool aGrabMouseEvents) if (view) { view->GetViewManager(*getter_AddRefs(viewMan)); - +// nsIWidget* widget = nsnull; +// view->GetWidget(widget); if (viewMan) { if (aGrabMouseEvents) { viewMan->GrabMouseEvents(view,result); +// widget->CaptureMouse(PR_TRUE); } else { viewMan->GrabMouseEvents(nsnull,result); +// widget->CaptureMouse(PR_FALSE); } } } @@ -779,6 +782,37 @@ nsListControlFrame :: CaptureMouseEvents(PRBool aGrabMouseEvents) return NS_OK; } +nsIView* nsListControlFrame::GetViewFor(nsIWidget* aWidget) +{ + nsIView* view = nsnull; + void* clientData; + + NS_PRECONDITION(nsnull != aWidget, "null widget ptr"); + + // The widget's client data points back to the owning view + if (aWidget && NS_SUCCEEDED(aWidget->GetClientData(clientData))) { + view = (nsIView*)clientData; + } + + return view; +} + +// Determine if a view is an ancestor of another view. + +PRBool nsListControlFrame::IsAncestor(nsIView* aAncestor, nsIView* aChild) +{ + nsIView* view = aChild; + while (nsnull != view) { + if (view == aAncestor) + // Is an ancestor + return(PR_TRUE); + else { + view->GetParent(view); + } + } + // Not an ancestor + return(PR_FALSE); +} //---------------------------------------------------------------------- NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aPresContext, @@ -786,15 +820,26 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aP nsEventStatus& aEventStatus) { if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) { - // Don't do anything unless a frame was target of the event. - if (nsnull == mHitFrame) { - if (IsInDropDownMode() == PR_TRUE) { - mComboboxFrame->ListWasSelected(&aPresContext); - } - return NS_OK; - } - } - + if (nsnull == mHitFrame) { + // Button down without hitting a frame in the drop down list. + + // May need to give the scrollbars a chance at the event. + // The drop down list's scrollbar view will be a descendant + // of the drop down list's view. So check to see if the view + // that associated with event's widget is a descendant. + // If so, then we do not pop the drop down list back up. + nsIView* eventView = GetViewFor(aEvent->widget); + nsIView* view=nsnull; + GetView(&view); + if (PR_TRUE == IsAncestor(view, eventView)) { + return NS_OK; + } + // Roll the drop-down list back up. + mComboboxFrame->ListWasSelected(&aPresContext); + return NS_OK; + } + } + // Mouse Move behavior is as follows: // When the DropDown occurs, if an item is selected it displayed as being selected. // It may or may not be currently visible, when the mouse is moved across any item @@ -817,29 +862,24 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aP mSelectedIndex = newSelectedIndex; } } - } - - + } } else if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) { + // Start by finding the newly "hit" content from the hit frame + if (nsnull != mHitFrame) { + PRInt32 index = GetSelectedIndex(mHitFrame); + if (kNothingSelected != index) { + SetFrameSelected(index, PR_TRUE); + mSelectedIndex = index; + } + if (mComboboxFrame) { mComboboxFrame->ListWasSelected(&aPresContext); } - - } else if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) { - // Start by finding the newly "hit" content from the hit frame - if (nsnull != mHitFrame) { - PRInt32 index = GetSelectedIndex(mHitFrame); - if (kNothingSelected != index) { - SetFrameSelected(index, PR_TRUE); - mSelectedIndex = index; - } - } - - if (mComboboxFrame) { - mComboboxFrame->ListWasSelected(&aPresContext); } } + + aEventStatus = nsEventStatus_eConsumeNoDefault; return NS_OK; } @@ -887,8 +927,6 @@ NS_IMETHODIMP nsListControlFrame::HandleEvent(nsIPresContext& aPresContext, HandleLikeListEvent(aPresContext, aEvent, aEventStatus); } - aEventStatus = nsEventStatus_eConsumeNoDefault; - return NS_OK; } @@ -993,10 +1031,7 @@ NS_IMETHODIMP nsListControlFrame::AboutToDropDown() { // Resync the view's position with the frame. - nsRect rect; - GetRect(rect); - MoveTo(rect.x, rect.y); - return NS_OK; + return(SyncViewWithFrame()); } @@ -1470,7 +1505,105 @@ nsresult nsListControlFrame::CreateScrollingViewWidget(nsIView* aView, const nsS return nsScrollFrame::CreateScrollingViewWidget(aView, aPosition); } } + +void +nsListControlFrame::GetViewOffset(nsIViewManager* aManager, nsIView* aView, + nsPoint& aPoint) +{ + aPoint.x = 0; + aPoint.y = 0; + + nsIView *parent; + nsRect bounds; + + parent = aView; + while (nsnull != parent) { + parent->GetBounds(bounds); + aPoint.x += bounds.x; + aPoint.y += bounds.y; + parent->GetParent(parent); + } +} +//---------------------------------------------------------------------- +nsresult +nsListControlFrame::SyncViewWithFrame() +{ + // Resync the view's position with the frame. + // The problem is the dropdown's view is attached directly under + // the root view. This means it's view needs to have it's coordinates calculated + // as if it were in it's normal position in the view hierarchy. + + nsPoint parentPos; + nsCOMPtr viewManager; + + //Get parent frame + nsIFrame* parent; + GetParentWithView(&parent); + NS_ASSERTION(parent, "GetParentWithView failed"); + + // Get parent view + nsIView* parentView = nsnull; + parent->GetView(&parentView); + + parentView->GetViewManager(*getter_AddRefs(viewManager)); + GetViewOffset(viewManager, parentView, parentPos); + nsIView* view = nsnull; + GetView(&view); + + nsIView* containingView = nsnull; + nsPoint offset; + GetOffsetFromView(offset, &containingView); + nsSize size; + GetSize(size); + + viewManager->ResizeView(view, mRect.width, mRect.height); + viewManager->MoveViewTo(view, parentPos.x + offset.x, parentPos.y + offset.y ); + + return NS_OK; +} + +nsresult +nsListControlFrame::GetScrollingParentView(nsIFrame* aParent, nsIView** aParentView) +{ + if (IsInDropDownMode() == PR_TRUE) { + // Use the parent frame to get the view manager + nsIView* parentView = nsnull; + nsresult rv = aParent->GetView(&parentView); + NS_ASSERTION(parentView, "GetView failed"); + nsCOMPtr viewManager; + parentView->GetViewManager(*getter_AddRefs(viewManager)); + NS_ASSERTION(viewManager, "GetViewManager failed"); + + // Ask the view manager for the root view and + // use it as the parent for popup scrolling lists. + // Using the normal view as the parent causes the + // drop-down list to be clipped to a parent view. + // Using the root view as the parent + // prevents this from happening. + viewManager->GetRootView(*aParentView); + NS_ASSERTION(aParentView, "GetRootView failed"); + return rv; + } else { + return nsScrollFrame::GetScrollingParentView(aParent, aParentView); + } +} + +NS_IMETHODIMP +nsListControlFrame::DidReflow(nsIPresContext& aPresContext, + nsDidReflowStatus aStatus) +{ + if (PR_TRUE == IsInDropDownMode()) + { + nsresult rv = nsScrollFrame::DidReflow(aPresContext, aStatus); + SyncViewWithFrame(); + return rv; + } else { + return nsScrollFrame::DidReflow(aPresContext, aStatus); + } +} + + diff --git a/layout/forms/nsListControlFrame.h b/layout/forms/nsListControlFrame.h index cd5a4f297d67..2dca5a9702e9 100644 --- a/layout/forms/nsListControlFrame.h +++ b/layout/forms/nsListControlFrame.h @@ -27,6 +27,7 @@ class nsIDOMHTMLSelectElement; class nsIDOMHTMLCollection; class nsIDOMHTMLOptionElement; class nsIComboboxControlFrame; +class nsIViewManager; /** * Frame-based listbox. @@ -65,6 +66,8 @@ public: nsIFrame* aPrevInFlow); NS_IMETHOD Deselect(); + + NS_IMETHOD DidReflow(nsIPresContext& aPresContext, nsDidReflowStatus aStatus); // nsIFormControlFrame NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); @@ -122,17 +125,19 @@ public: nsIContent* GetOptionContent(PRUint32 aIndex); PRBool IsContentSelected(nsIContent* aContent); PRBool IsFrameSelected(PRUint32 aIndex); - void SetFrameSelected(PRUint32 aIndex, PRBool aSelected); - -protected: - // nsScrollFrame overrides - // Override the widget created for the list box so a Borderless top level widget is created - // for drop-down lists. - virtual nsresult CreateScrollingViewWidget(nsIView* aView,const nsStylePosition* aPosition); + void SetFrameSelected(PRUint32 aIndex, PRBool aSelected); + void GetViewOffset(nsIViewManager* aManager, nsIView* aView, nsPoint& aPoint); +protected: + nsListControlFrame(); virtual ~nsListControlFrame(); + // nsScrollFrame overrides + // Override the widget created for the list box so a Borderless top level widget is created + // for drop-down lists. + virtual nsresult CreateScrollingViewWidget(nsIView* aView,const nsStylePosition* aPosition); + virtual nsresult GetScrollingParentView(nsIFrame* aParent, nsIView** aParentView); PRInt32 GetNumberOfOptions(); nsIFrame * GetOptionFromChild(nsIFrame* aParentFrame); @@ -142,6 +147,9 @@ protected: nsIFrame** aFrame); // Utility methods + PRBool IsAncestor(nsIView* aAncestor, nsIView* aChild); + nsIView* GetViewFor(nsIWidget* aWidget); + nsresult SyncViewWithFrame(); PRBool IsInDropDownMode(); PRBool IsOptionElement(nsIContent* aContent); PRBool IsOptionElementFrame(nsIFrame *aFrame); diff --git a/layout/html/base/src/nsHTMLAtoms.cpp b/layout/html/base/src/nsHTMLAtoms.cpp index 026b7f7351dc..a49ce9e24611 100644 --- a/layout/html/base/src/nsHTMLAtoms.cpp +++ b/layout/html/base/src/nsHTMLAtoms.cpp @@ -211,6 +211,7 @@ nsIAtom* nsHTMLAtoms::pre; nsIAtom* nsHTMLAtoms::processingInstructionPseudo; nsIAtom* nsHTMLAtoms::profile; nsIAtom* nsHTMLAtoms::prompt; +nsIAtom* nsHTMLAtoms::radioPseudo; nsIAtom* nsHTMLAtoms::readonly; nsIAtom* nsHTMLAtoms::rel; nsIAtom* nsHTMLAtoms::repeat; @@ -481,6 +482,7 @@ void nsHTMLAtoms::AddrefAtoms() processingInstructionPseudo = NS_NewAtom(":-moz-pi"); profile = NS_NewAtom("profile"); prompt = NS_NewAtom("prompt"); + radioPseudo = NS_NewAtom(":-moz-radio"); readonly = NS_NewAtom("readonly"); rel = NS_NewAtom("rel"); repeat = NS_NewAtom("repeat"); @@ -740,6 +742,7 @@ void nsHTMLAtoms::ReleaseAtoms() NS_RELEASE(processingInstructionPseudo); NS_RELEASE(profile); NS_RELEASE(prompt); + NS_RELEASE(radioPseudo); NS_RELEASE(readonly); NS_RELEASE(rel); NS_RELEASE(repeat); diff --git a/layout/html/base/src/nsHTMLAtoms.h b/layout/html/base/src/nsHTMLAtoms.h index eb556d3dbd18..9dff9cbb1e61 100644 --- a/layout/html/base/src/nsHTMLAtoms.h +++ b/layout/html/base/src/nsHTMLAtoms.h @@ -243,7 +243,8 @@ public: static nsIAtom* processingInstructionPseudo; static nsIAtom* profile; static nsIAtom* prompt; - + + static nsIAtom* radioPseudo; static nsIAtom* readonly; static nsIAtom* rel; static nsIAtom* repeat; diff --git a/layout/html/base/src/nsScrollFrame.cpp b/layout/html/base/src/nsScrollFrame.cpp index f6b313b06334..8a92604aaeba 100644 --- a/layout/html/base/src/nsScrollFrame.cpp +++ b/layout/html/base/src/nsScrollFrame.cpp @@ -162,19 +162,28 @@ nsScrollFrame::CreateScrollingViewWidget(nsIView* aView, const nsStylePosition* return(rv); } +nsresult +nsScrollFrame::GetScrollingParentView(nsIFrame* aParent, nsIView** aParentView) +{ + nsresult rv = aParent->GetView(aParentView); + NS_ASSERTION(aParentView, "GetParentWithView failed"); + return(rv); +} + nsresult nsScrollFrame::CreateScrollingView(nsIPresContext& aPresContext) { nsIView* view; - // Get parent view + //Get parent frame nsIFrame* parent; GetParentWithView(&parent); NS_ASSERTION(parent, "GetParentWithView failed"); - nsIView* parentView; - parent->GetView(&parentView); - NS_ASSERTION(parentView, "GetParentWithView failed"); + // Get parent view + nsIView* parentView = nsnull; + GetScrollingParentView(parent, &parentView); + // Get the view manager nsIViewManager* viewManager; parentView->GetViewManager(viewManager); diff --git a/layout/html/base/src/nsScrollFrame.h b/layout/html/base/src/nsScrollFrame.h index 078aaae0bc68..ea95784081ed 100644 --- a/layout/html/base/src/nsScrollFrame.h +++ b/layout/html/base/src/nsScrollFrame.h @@ -69,7 +69,8 @@ protected: // Creation of the widget for the scrolling view is factored into a virtual method so // that sub-classes may control widget creation. virtual nsresult CreateScrollingViewWidget(nsIView* aView,const nsStylePosition* aPosition); - + // Getting the view for scollframe may be overriden to provide a parent view for te scroll frame + virtual nsresult GetScrollingParentView(nsIFrame* aParent, nsIView** aParentView); private: nsresult CreateScrollingView(nsIPresContext& aPresContext); }; diff --git a/layout/html/document/src/ua.css b/layout/html/document/src/ua.css index 7389c9515e5b..4a35e8105c4d 100644 --- a/layout/html/document/src/ua.css +++ b/layout/html/document/src/ua.css @@ -430,24 +430,54 @@ input[type=radio] { margin-right: 5px; margin-top: 3px; margin-bottom: 3px; - border: 2px inset rgb(192, 192, 192); - background-color:white; + border: 2px outset rgb(192, 192, 192); + background-color:rgb(192, 192, 192); color:black; width:12px; height:12px; + -moz-border-radius:6px; } +input[type=radio]:active { + background-color:white; + border: 2px inset rgb(192, 192, 192); +} + +input[type=radio]:hover { + border : 2px solid black; +} + +:-moz-radio { + background-color:black; + width:6px; + height:6px; + left:6px; + top:6px; + -moz-border-radius:3px; +} + + input[type=checkbox] { /* these margins are for NavQuirks, we need a Standard ua.css */ margin-left: 3px; margin-right: 5px; margin-top: 3px; margin-bottom: 4px; - border: 2px inset rgb(192, 192, 192); + border: 2px outset rgb(192, 192, 192); width:11px; height:11px; - background-color:white; + background-color:rgb(192, 192, 192); color:black; + -moz-border-radius:1px; +} + +input[type=checkbox]:active { + background-color:gray; + border: 2px inset rgb(192, 192, 192); +} + +input[type=checkbox]:hover { + border : 1px solid black; } input[type="submit"] { @@ -706,9 +736,29 @@ select { background-color: white; color:black; white-space:nowrap; + text-align: left; } + +select:active { + border : 1px solid black; +} + option { display:block; + padding-left:3px; + padding-right:3px; +} + +/* Combobox item style */ +select option[-moz-option-selected], select[size="1"] option[-moz-option-selected] { + color:black; + background-color:white; +} + +/* List box item selected style */ +select[size] option[-moz-option-selected] { + color:white; + background-color:black; } option.selected { @@ -717,10 +767,6 @@ option.selected { color: rgb(255,255,255); } -option[-moz-option-selected] { - color:white; - background-color: rgb(0,0,128); -} option.selectedfocus { border: 1px dotted white; @@ -940,14 +986,15 @@ sourcetext { /* XXX should not be in HTML namespace */ } :-moz-dropdown-btn-pressed { - border: 2px inset #c0c0c0; - background-color: rgb(206, 207, 206); +/* border: 2px inset #c0c0c0; */ + background-color: rgb(192, 192, 192); + border: none; } :-moz-dropdown-list { position:absolute; - background-color:white; - border: 1px solid blue; + background-color:rgb(192, 192, 192); + border: 1px solid black; } diff --git a/layout/html/forms/public/MANIFEST b/layout/html/forms/public/MANIFEST index cbc538d84c4a..7e1cb1f05df5 100644 --- a/layout/html/forms/public/MANIFEST +++ b/layout/html/forms/public/MANIFEST @@ -5,3 +5,4 @@ nsIComboboxControlFrame.h nsIListControlFrame.h nsIFormControlFrame.h +nsIRadioControlFrame.h diff --git a/layout/html/forms/public/Makefile.in b/layout/html/forms/public/Makefile.in index dbc2453e73ea..a6d48b492392 100644 --- a/layout/html/forms/public/Makefile.in +++ b/layout/html/forms/public/Makefile.in @@ -27,6 +27,7 @@ EXPORTS = \ nsIListControlFrame.h \ nsIComboboxControlFrame.h \ nsIFormControlFrame.h \ + nsIRadioControlFrame.h \ $(NULL) EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS)) diff --git a/layout/html/forms/public/makefile.win b/layout/html/forms/public/makefile.win index 793c7f1d9282..d6406a9ca198 100644 --- a/layout/html/forms/public/makefile.win +++ b/layout/html/forms/public/makefile.win @@ -20,6 +20,7 @@ DEPTH=..\..\..\.. EXPORTS=nsIFormManager.h \ nsIListControlFrame.h \ nsIComboboxControlFrame.h \ + nsIRadioControlFrame.h \ nsIFormControlFrame.h MODULE=raptor diff --git a/layout/html/forms/public/nsIRadioControlFrame.h b/layout/html/forms/public/nsIRadioControlFrame.h new file mode 100644 index 000000000000..2e116cde5197 --- /dev/null +++ b/layout/html/forms/public/nsIRadioControlFrame.h @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#ifndef nsIRadioControlFrame_h___ +#define nsIRadioControlFrame_h___ + +#include "nsISupports.h" +class nsIStyleContext; + +// IID for the nsIRadioControlFrame class +// {06450E00-24D9-11d3-966B-00105A1B1B76} +#define NS_IRADIOCONTROLFRAME_IID \ +{ 0x6450e00, 0x24d9, 0x11d3, \ + { 0x96, 0x6b, 0x0, 0x10, 0x5a, 0x1b, 0x1b, 0x76 } } + + +/** + * nsIRadioControlFrame is the common interface radio buttons. + * @see nsFromControlFrame and its base classes for more info + */ +class nsIRadioControlFrame : public nsISupports { + +public: + + /** + * Sets the Pseudo Style Contexts for the Radio button + * + */ + NS_IMETHOD SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioButtonFaceStyleContext) = 0; +}; + +#endif + diff --git a/layout/html/forms/src/nsListControlFrame.cpp b/layout/html/forms/src/nsListControlFrame.cpp index 7ce48e1c7c1d..8fda0934ebca 100644 --- a/layout/html/forms/src/nsListControlFrame.cpp +++ b/layout/html/forms/src/nsListControlFrame.cpp @@ -126,7 +126,7 @@ nsListControlFrame::GetFrameForPoint(const nsPoint& aPoint, nsIFrame** aFrame) // on in the HandleEvent. The GetFrameForPointUsing is always called before the HandleEvent. // nsresult rv; - + mHitFrame = nsnull; nsIFrame *childFrame; FirstChild(nsnull, &childFrame); rv = GetFrameForPointUsing(aPoint, nsnull, aFrame); @@ -424,7 +424,7 @@ nsListControlFrame::Reflow(nsIPresContext& aPresContext, aStatus = NS_FRAME_COMPLETE; mDisplayed = PR_TRUE; - + return NS_OK; } @@ -766,12 +766,15 @@ nsListControlFrame :: CaptureMouseEvents(PRBool aGrabMouseEvents) if (view) { view->GetViewManager(*getter_AddRefs(viewMan)); - +// nsIWidget* widget = nsnull; +// view->GetWidget(widget); if (viewMan) { if (aGrabMouseEvents) { viewMan->GrabMouseEvents(view,result); +// widget->CaptureMouse(PR_TRUE); } else { viewMan->GrabMouseEvents(nsnull,result); +// widget->CaptureMouse(PR_FALSE); } } } @@ -779,6 +782,37 @@ nsListControlFrame :: CaptureMouseEvents(PRBool aGrabMouseEvents) return NS_OK; } +nsIView* nsListControlFrame::GetViewFor(nsIWidget* aWidget) +{ + nsIView* view = nsnull; + void* clientData; + + NS_PRECONDITION(nsnull != aWidget, "null widget ptr"); + + // The widget's client data points back to the owning view + if (aWidget && NS_SUCCEEDED(aWidget->GetClientData(clientData))) { + view = (nsIView*)clientData; + } + + return view; +} + +// Determine if a view is an ancestor of another view. + +PRBool nsListControlFrame::IsAncestor(nsIView* aAncestor, nsIView* aChild) +{ + nsIView* view = aChild; + while (nsnull != view) { + if (view == aAncestor) + // Is an ancestor + return(PR_TRUE); + else { + view->GetParent(view); + } + } + // Not an ancestor + return(PR_FALSE); +} //---------------------------------------------------------------------- NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aPresContext, @@ -786,15 +820,26 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aP nsEventStatus& aEventStatus) { if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) { - // Don't do anything unless a frame was target of the event. - if (nsnull == mHitFrame) { - if (IsInDropDownMode() == PR_TRUE) { - mComboboxFrame->ListWasSelected(&aPresContext); - } - return NS_OK; - } - } - + if (nsnull == mHitFrame) { + // Button down without hitting a frame in the drop down list. + + // May need to give the scrollbars a chance at the event. + // The drop down list's scrollbar view will be a descendant + // of the drop down list's view. So check to see if the view + // that associated with event's widget is a descendant. + // If so, then we do not pop the drop down list back up. + nsIView* eventView = GetViewFor(aEvent->widget); + nsIView* view=nsnull; + GetView(&view); + if (PR_TRUE == IsAncestor(view, eventView)) { + return NS_OK; + } + // Roll the drop-down list back up. + mComboboxFrame->ListWasSelected(&aPresContext); + return NS_OK; + } + } + // Mouse Move behavior is as follows: // When the DropDown occurs, if an item is selected it displayed as being selected. // It may or may not be currently visible, when the mouse is moved across any item @@ -817,29 +862,24 @@ NS_IMETHODIMP nsListControlFrame::HandleLikeDropDownListEvent(nsIPresContext& aP mSelectedIndex = newSelectedIndex; } } - } - - + } } else if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) { + // Start by finding the newly "hit" content from the hit frame + if (nsnull != mHitFrame) { + PRInt32 index = GetSelectedIndex(mHitFrame); + if (kNothingSelected != index) { + SetFrameSelected(index, PR_TRUE); + mSelectedIndex = index; + } + if (mComboboxFrame) { mComboboxFrame->ListWasSelected(&aPresContext); } - - } else if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) { - // Start by finding the newly "hit" content from the hit frame - if (nsnull != mHitFrame) { - PRInt32 index = GetSelectedIndex(mHitFrame); - if (kNothingSelected != index) { - SetFrameSelected(index, PR_TRUE); - mSelectedIndex = index; - } - } - - if (mComboboxFrame) { - mComboboxFrame->ListWasSelected(&aPresContext); } } + + aEventStatus = nsEventStatus_eConsumeNoDefault; return NS_OK; } @@ -887,8 +927,6 @@ NS_IMETHODIMP nsListControlFrame::HandleEvent(nsIPresContext& aPresContext, HandleLikeListEvent(aPresContext, aEvent, aEventStatus); } - aEventStatus = nsEventStatus_eConsumeNoDefault; - return NS_OK; } @@ -993,10 +1031,7 @@ NS_IMETHODIMP nsListControlFrame::AboutToDropDown() { // Resync the view's position with the frame. - nsRect rect; - GetRect(rect); - MoveTo(rect.x, rect.y); - return NS_OK; + return(SyncViewWithFrame()); } @@ -1470,7 +1505,105 @@ nsresult nsListControlFrame::CreateScrollingViewWidget(nsIView* aView, const nsS return nsScrollFrame::CreateScrollingViewWidget(aView, aPosition); } } + +void +nsListControlFrame::GetViewOffset(nsIViewManager* aManager, nsIView* aView, + nsPoint& aPoint) +{ + aPoint.x = 0; + aPoint.y = 0; + + nsIView *parent; + nsRect bounds; + + parent = aView; + while (nsnull != parent) { + parent->GetBounds(bounds); + aPoint.x += bounds.x; + aPoint.y += bounds.y; + parent->GetParent(parent); + } +} +//---------------------------------------------------------------------- +nsresult +nsListControlFrame::SyncViewWithFrame() +{ + // Resync the view's position with the frame. + // The problem is the dropdown's view is attached directly under + // the root view. This means it's view needs to have it's coordinates calculated + // as if it were in it's normal position in the view hierarchy. + + nsPoint parentPos; + nsCOMPtr viewManager; + + //Get parent frame + nsIFrame* parent; + GetParentWithView(&parent); + NS_ASSERTION(parent, "GetParentWithView failed"); + + // Get parent view + nsIView* parentView = nsnull; + parent->GetView(&parentView); + + parentView->GetViewManager(*getter_AddRefs(viewManager)); + GetViewOffset(viewManager, parentView, parentPos); + nsIView* view = nsnull; + GetView(&view); + + nsIView* containingView = nsnull; + nsPoint offset; + GetOffsetFromView(offset, &containingView); + nsSize size; + GetSize(size); + + viewManager->ResizeView(view, mRect.width, mRect.height); + viewManager->MoveViewTo(view, parentPos.x + offset.x, parentPos.y + offset.y ); + + return NS_OK; +} + +nsresult +nsListControlFrame::GetScrollingParentView(nsIFrame* aParent, nsIView** aParentView) +{ + if (IsInDropDownMode() == PR_TRUE) { + // Use the parent frame to get the view manager + nsIView* parentView = nsnull; + nsresult rv = aParent->GetView(&parentView); + NS_ASSERTION(parentView, "GetView failed"); + nsCOMPtr viewManager; + parentView->GetViewManager(*getter_AddRefs(viewManager)); + NS_ASSERTION(viewManager, "GetViewManager failed"); + + // Ask the view manager for the root view and + // use it as the parent for popup scrolling lists. + // Using the normal view as the parent causes the + // drop-down list to be clipped to a parent view. + // Using the root view as the parent + // prevents this from happening. + viewManager->GetRootView(*aParentView); + NS_ASSERTION(aParentView, "GetRootView failed"); + return rv; + } else { + return nsScrollFrame::GetScrollingParentView(aParent, aParentView); + } +} + +NS_IMETHODIMP +nsListControlFrame::DidReflow(nsIPresContext& aPresContext, + nsDidReflowStatus aStatus) +{ + if (PR_TRUE == IsInDropDownMode()) + { + nsresult rv = nsScrollFrame::DidReflow(aPresContext, aStatus); + SyncViewWithFrame(); + return rv; + } else { + return nsScrollFrame::DidReflow(aPresContext, aStatus); + } +} + + diff --git a/layout/html/forms/src/nsListControlFrame.h b/layout/html/forms/src/nsListControlFrame.h index cd5a4f297d67..2dca5a9702e9 100644 --- a/layout/html/forms/src/nsListControlFrame.h +++ b/layout/html/forms/src/nsListControlFrame.h @@ -27,6 +27,7 @@ class nsIDOMHTMLSelectElement; class nsIDOMHTMLCollection; class nsIDOMHTMLOptionElement; class nsIComboboxControlFrame; +class nsIViewManager; /** * Frame-based listbox. @@ -65,6 +66,8 @@ public: nsIFrame* aPrevInFlow); NS_IMETHOD Deselect(); + + NS_IMETHOD DidReflow(nsIPresContext& aPresContext, nsDidReflowStatus aStatus); // nsIFormControlFrame NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); @@ -122,17 +125,19 @@ public: nsIContent* GetOptionContent(PRUint32 aIndex); PRBool IsContentSelected(nsIContent* aContent); PRBool IsFrameSelected(PRUint32 aIndex); - void SetFrameSelected(PRUint32 aIndex, PRBool aSelected); - -protected: - // nsScrollFrame overrides - // Override the widget created for the list box so a Borderless top level widget is created - // for drop-down lists. - virtual nsresult CreateScrollingViewWidget(nsIView* aView,const nsStylePosition* aPosition); + void SetFrameSelected(PRUint32 aIndex, PRBool aSelected); + void GetViewOffset(nsIViewManager* aManager, nsIView* aView, nsPoint& aPoint); +protected: + nsListControlFrame(); virtual ~nsListControlFrame(); + // nsScrollFrame overrides + // Override the widget created for the list box so a Borderless top level widget is created + // for drop-down lists. + virtual nsresult CreateScrollingViewWidget(nsIView* aView,const nsStylePosition* aPosition); + virtual nsresult GetScrollingParentView(nsIFrame* aParent, nsIView** aParentView); PRInt32 GetNumberOfOptions(); nsIFrame * GetOptionFromChild(nsIFrame* aParentFrame); @@ -142,6 +147,9 @@ protected: nsIFrame** aFrame); // Utility methods + PRBool IsAncestor(nsIView* aAncestor, nsIView* aChild); + nsIView* GetViewFor(nsIWidget* aWidget); + nsresult SyncViewWithFrame(); PRBool IsInDropDownMode(); PRBool IsOptionElement(nsIContent* aContent); PRBool IsOptionElementFrame(nsIFrame *aFrame); diff --git a/layout/html/forms/src/nsRadioControlFrame.cpp b/layout/html/forms/src/nsRadioControlFrame.cpp index 0e4d65dc634e..b616f5740df2 100644 --- a/layout/html/forms/src/nsRadioControlFrame.cpp +++ b/layout/html/forms/src/nsRadioControlFrame.cpp @@ -40,6 +40,8 @@ #include "nsINameSpaceManager.h" #include "nsILookAndFeel.h" #include "nsIComponentManager.h" +#include "nsCOMPtr.h" +#include "nsCSSRendering.h" static NS_DEFINE_IID(kIRadioIID, NS_IRADIOBUTTON_IID); static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); @@ -49,6 +51,7 @@ static NS_DEFINE_IID(kILookAndFeelIID, NS_ILOOKANDFEEL_IID); #define NS_DEFAULT_RADIOBOX_SIZE 12 +static NS_DEFINE_IID(kIRadioControlFrameIID, NS_IRADIOCONTROLFRAME_IID); nsresult NS_NewRadioControlFrame(nsIFrame** aNewFrame) @@ -69,8 +72,29 @@ nsRadioControlFrame::nsRadioControlFrame() { // Initialize GFX-rendered state mChecked = PR_FALSE; + mRadioButtonFaceStyle = nsnull; } +nsRadioControlFrame::~nsRadioControlFrame() +{ + NS_IF_RELEASE(mRadioButtonFaceStyle); +} + +//-------------------------------------------------------------- +nsresult +nsRadioControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kIRadioControlFrameIID)) { + *aInstancePtr = (void*) ((nsIRadioControlFrame*) this); + return NS_OK; + } + + return nsFormControlFrame::QueryInterface(aIID, aInstancePtr); +} const nsIID& @@ -86,6 +110,42 @@ nsRadioControlFrame::GetCID() return kRadioCID; } + +NS_IMETHODIMP +nsRadioControlFrame::ReResolveStyleContext(nsIPresContext* aPresContext, + nsIStyleContext* aParentContext, + PRInt32 aParentChange, + nsStyleChangeList* aChangeList, + PRInt32* aLocalChange) +{ + // this re-resolves |mStyleContext|, so it may change + nsresult rv = nsFormControlFrame::ReResolveStyleContext(aPresContext, aParentContext, aParentChange, + aChangeList, aLocalChange); + if (NS_FAILED(rv)) { + return rv; + } + + if (NS_COMFALSE != rv) { // frame style changed + if (aLocalChange) { + aParentChange = *aLocalChange; // tell children about or change + } + } + + // see if the outline has changed. + nsCOMPtr oldRadioButtonFaceStyle = mRadioButtonFaceStyle; + aPresContext->ProbePseudoStyleContextFor(mContent, nsHTMLAtoms::radioPseudo, mStyleContext, + PR_FALSE, + &mRadioButtonFaceStyle); + + if ((mRadioButtonFaceStyle && oldRadioButtonFaceStyle) && (mRadioButtonFaceStyle != oldRadioButtonFaceStyle)) { + nsFormControlFrame::CaptureStyleChangeFor(this, oldRadioButtonFaceStyle, mRadioButtonFaceStyle, + aParentChange, aChangeList, aLocalChange); + } + + return rv; +} + + nscoord nsRadioControlFrame::GetRadioboxSize(float aPixToTwip) const { @@ -339,50 +399,45 @@ nsRadioControlFrame::GetFrameName(nsString& aResult) const } +NS_IMETHODIMP +nsRadioControlFrame::SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioButtonFaceStyleContext) +{ + mRadioButtonFaceStyle = aRadioButtonFaceStyleContext; + NS_ADDREF(mRadioButtonFaceStyle); + return NS_OK; +} + void nsRadioControlFrame::PaintRadioButton(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect) { - aRenderingContext.PushState(); - - const nsStyleColor* color = (const nsStyleColor*) - mStyleContext->GetStyleData(eStyleStruct_Color); - - //XXX: This is backwards for now. The PaintCircular border code actually draws pie slices. - - nsFormControlHelper::PaintCircularBorder(aPresContext,aRenderingContext, - aDirtyRect, mStyleContext, PR_FALSE, this, mRect.width, mRect.height); - nsFormControlHelper::PaintCircularBackground(aPresContext,aRenderingContext, - aDirtyRect, mStyleContext, PR_FALSE, this, mRect.width, mRect.height); - - + PRBool checked = PR_TRUE; GetCurrentCheckState(&checked); // Get check state from the content model if (PR_TRUE == checked) { - // Have to do 180 degress at a time because FillArc will not correctly - // go from 0-360 - float p2t; - aPresContext.GetScaledPixelsToTwips(&p2t); + // Paint the button for the radio button using CSS background rendering code + if (nsnull != mRadioButtonFaceStyle) { + const nsStyleColor* myColor = (const nsStyleColor*) + mRadioButtonFaceStyle->GetStyleData(eStyleStruct_Color); + const nsStyleSpacing* mySpacing = (const nsStyleSpacing*) + mRadioButtonFaceStyle->GetStyleData(eStyleStruct_Spacing); + const nsStylePosition* myPosition = (const nsStylePosition*) + mRadioButtonFaceStyle->GetStyleData(eStyleStruct_Position); - nscoord onePixel = NSIntPixelsToTwips(1, p2t); -//XXX nscoord twelvePixels = NSIntPixelsToTwips(12, p2t); + nscoord width = myPosition->mWidth.GetCoordValue(); + nscoord height = myPosition->mHeight.GetCoordValue(); + // Position the button centered within the radio control's rectangle. + nscoord x = (mRect.width - width) / 2; + nscoord y = (mRect.height - height) / 2; + nsRect rect(x, y, width, height); - nsRect outside; - nsFormControlHelper::GetCircularRect(mRect.width, mRect.height, outside); - - outside.Deflate(onePixel, onePixel); - outside.Deflate(onePixel, onePixel); - outside.Deflate(onePixel, onePixel); - outside.Deflate(onePixel, onePixel); - - aRenderingContext.SetColor(color->mColor); - aRenderingContext.FillArc(outside, 0, 180); - aRenderingContext.FillArc(outside, 180, 360); + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this, + aDirtyRect, rect, *myColor, *mySpacing, 0, 0); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, + aDirtyRect, rect, *mySpacing, mRadioButtonFaceStyle, 0); + } } - - PRBool clip; - aRenderingContext.PopState(clip); } NS_METHOD @@ -396,6 +451,9 @@ nsRadioControlFrame::Paint(nsIPresContext& aPresContext, if (!disp->mVisible) return NS_OK; + // Paint the background + nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { PaintRadioButton(aPresContext, aRenderingContext, aDirtyRect); } diff --git a/layout/html/forms/src/nsRadioControlFrame.h b/layout/html/forms/src/nsRadioControlFrame.h index 1ec93fc45b75..8f596536b6e5 100644 --- a/layout/html/forms/src/nsRadioControlFrame.h +++ b/layout/html/forms/src/nsRadioControlFrame.h @@ -19,6 +19,7 @@ #ifndef nsRadioControlFrame_h___ #define nsRadioControlFrame_h___ +#include "nsIRadioControlFrame.h" #include "nsFormControlFrame.h" #include "nsVoidArray.h" #include "nsString.h" @@ -26,10 +27,11 @@ class nsIAtom; // nsRadioControlFrame -class nsRadioControlFrame : public nsFormControlFrame +class nsRadioControlFrame : public nsFormControlFrame, public nsIRadioControlFrame { public: nsRadioControlFrame(); + ~nsRadioControlFrame(); // nsFormControlFrame overrides nsresult RequiresWidget(PRBool &aHasWidget); @@ -49,6 +51,10 @@ public: NS_IMETHOD GetFrameName(nsString& aResult) const; + //nsIRadioControlFrame methods + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + NS_IMETHOD SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioButtonFaceStyleContext); + virtual PRBool GetChecked(PRBool aGetInitialValue); virtual void SetChecked(PRBool aValue, PRBool aSetInitialValue); @@ -63,6 +69,12 @@ public: virtual const nsIID& GetIID(); + NS_IMETHOD ReResolveStyleContext(nsIPresContext* aPresContext, + nsIStyleContext* aParentContext, + PRInt32 aParentChange, + nsStyleChangeList* aChangeList, + PRInt32* aLocalChange); + // // XXX: The following paint methods are TEMPORARY. It is being used to get printing working // under windows. Later it may be used to GFX-render the controls to the display. @@ -97,6 +109,12 @@ protected: nsSize& aDesiredWidgetSize); //GFX-rendered state variables PRBool mChecked; + + nsIStyleContext* mRadioButtonFaceStyle; + +private: + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } + NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } }; // nsRadioControlGroup @@ -120,8 +138,10 @@ protected: nsString mName; nsVoidArray mRadios; nsRadioControlFrame* mCheckedRadio; + }; + #endif diff --git a/layout/html/style/src/nsCSSFrameConstructor.cpp b/layout/html/style/src/nsCSSFrameConstructor.cpp index e78dc10f274b..89a4d5028a8a 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -49,6 +49,7 @@ #include "nsLayoutAtoms.h" #include "nsIDOMHTMLSelectElement.h" #include "nsIComboboxControlFrame.h" +#include "nsIRadioControlFrame.h" #include "nsIListControlFrame.h" #include "nsIDOMCharacterData.h" #include "nsIDOMHTMLImageElement.h" @@ -122,6 +123,7 @@ static NS_DEFINE_IID(kIWebShellIID, NS_IWEB_SHELL_IID); static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID); static NS_DEFINE_IID(kIComboboxControlFrameIID, NS_ICOMBOBOXCONTROLFRAME_IID); +static NS_DEFINE_IID(kIRadioControlFrameIID, NS_IRADIOCONTROLFRAME_IID); static NS_DEFINE_IID(kIListControlFrameIID, NS_ILISTCONTROLFRAME_IID); static NS_DEFINE_IID(kIDOMHTMLImageElementIID, NS_IDOMHTMLIMAGEELEMENT_IID); static NS_DEFINE_IID(kIDOMCharacterDataIID, NS_IDOMCHARACTERDATA_IID); @@ -765,7 +767,7 @@ nsCSSFrameConstructor::CreateInputFrame(nsIPresContext *aPresContext, rv = ConstructTextControlFrame(aPresContext, aFrame); } else if (val.EqualsIgnoreCase("radio")) { - rv = NS_NewRadioControlFrame(&aFrame); + rv = ConstructRadioControlFrame(aPresContext, aFrame, aContent); } else if (val.EqualsIgnoreCase("text")) { rv = ConstructTextControlFrame(aPresContext, aFrame); @@ -2233,6 +2235,23 @@ nsCSSFrameConstructor::CreatePlaceholderFrameFor(nsIPresContext* aPresContext, return rv; } +nsresult +nsCSSFrameConstructor::ConstructRadioControlFrame(nsIPresContext* aPresContext, + nsIFrame*& aNewFrame, + nsIContent* aContent) +{ + nsresult rv = NS_NewRadioControlFrame(&aNewFrame); + nsCOMPtr radioStyle; + aPresContext->ResolvePseudoStyleContextFor(aContent, nsHTMLAtoms::radioPseudo, + radioStyle, PR_FALSE, getter_AddRefs(radioStyle)); + nsIRadioControlFrame* radio = nsnull; + if (NS_SUCCEEDED(aNewFrame->QueryInterface(kIRadioControlFrameIID, (void**)&radio))) { + radio->SetRadioButtonFaceStyleContext(radioStyle); + NS_RELEASE(radio); + } + return rv; +} + nsresult nsCSSFrameConstructor::ConstructTextControlFrame(nsIPresContext* aPresContext, nsIFrame*& aNewFrame) @@ -2711,7 +2730,7 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresContext* aPresContext, else if (aTag == nsXULAtoms::fontpicker) rv = NS_NewFontPickerFrame(&newFrame); else if (aTag == nsXULAtoms::radio) - rv = NS_NewRadioControlFrame(&newFrame); + rv = ConstructRadioControlFrame(aPresContext, newFrame, aContent); else if (aTag == nsXULAtoms::text) rv = ConstructTextControlFrame(aPresContext, newFrame); else if (aTag == nsXULAtoms::widget) diff --git a/layout/html/style/src/nsCSSFrameConstructor.h b/layout/html/style/src/nsCSSFrameConstructor.h index 3a42487d4ea5..5518b71d2b13 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.h +++ b/layout/html/style/src/nsCSSFrameConstructor.h @@ -380,6 +380,9 @@ protected: nsIFrame* aParentFrame, nsIFrame*& aFrame); + nsresult ConstructRadioControlFrame(nsIPresContext* aPresContext, + nsIFrame*& aNewFrame, + nsIContent* aContent); nsresult ConstructTextControlFrame(nsIPresContext* aPresContext, nsIFrame*& aNewFrame); diff --git a/layout/style/ua.css b/layout/style/ua.css index 7389c9515e5b..4a35e8105c4d 100644 --- a/layout/style/ua.css +++ b/layout/style/ua.css @@ -430,24 +430,54 @@ input[type=radio] { margin-right: 5px; margin-top: 3px; margin-bottom: 3px; - border: 2px inset rgb(192, 192, 192); - background-color:white; + border: 2px outset rgb(192, 192, 192); + background-color:rgb(192, 192, 192); color:black; width:12px; height:12px; + -moz-border-radius:6px; } +input[type=radio]:active { + background-color:white; + border: 2px inset rgb(192, 192, 192); +} + +input[type=radio]:hover { + border : 2px solid black; +} + +:-moz-radio { + background-color:black; + width:6px; + height:6px; + left:6px; + top:6px; + -moz-border-radius:3px; +} + + input[type=checkbox] { /* these margins are for NavQuirks, we need a Standard ua.css */ margin-left: 3px; margin-right: 5px; margin-top: 3px; margin-bottom: 4px; - border: 2px inset rgb(192, 192, 192); + border: 2px outset rgb(192, 192, 192); width:11px; height:11px; - background-color:white; + background-color:rgb(192, 192, 192); color:black; + -moz-border-radius:1px; +} + +input[type=checkbox]:active { + background-color:gray; + border: 2px inset rgb(192, 192, 192); +} + +input[type=checkbox]:hover { + border : 1px solid black; } input[type="submit"] { @@ -706,9 +736,29 @@ select { background-color: white; color:black; white-space:nowrap; + text-align: left; } + +select:active { + border : 1px solid black; +} + option { display:block; + padding-left:3px; + padding-right:3px; +} + +/* Combobox item style */ +select option[-moz-option-selected], select[size="1"] option[-moz-option-selected] { + color:black; + background-color:white; +} + +/* List box item selected style */ +select[size] option[-moz-option-selected] { + color:white; + background-color:black; } option.selected { @@ -717,10 +767,6 @@ option.selected { color: rgb(255,255,255); } -option[-moz-option-selected] { - color:white; - background-color: rgb(0,0,128); -} option.selectedfocus { border: 1px dotted white; @@ -940,14 +986,15 @@ sourcetext { /* XXX should not be in HTML namespace */ } :-moz-dropdown-btn-pressed { - border: 2px inset #c0c0c0; - background-color: rgb(206, 207, 206); +/* border: 2px inset #c0c0c0; */ + background-color: rgb(192, 192, 192); + border: none; } :-moz-dropdown-list { position:absolute; - background-color:white; - border: 1px solid blue; + background-color:rgb(192, 192, 192); + border: 1px solid black; }