Numerous changes to support gfx-rendered form elements.

git-svn-id: svn://10.0.0.236/trunk@36078 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
kmcclusk%netscape.com
1999-06-21 20:41:56 +00:00
parent 99d3512b02
commit 040ca9ca76
25 changed files with 771 additions and 152 deletions

View File

@@ -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<nsIViewManager> 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<nsIViewManager> 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);
}
}

View File

@@ -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);

View File

@@ -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<nsIStyleContext> 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);
}

View File

@@ -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