From 87a10a39d90f7dec8b5985446c86d6ef4224e7ba Mon Sep 17 00:00:00 2001 From: kipp Date: Thu, 7 May 1998 16:13:59 +0000 Subject: [PATCH] Support (mostly) border+padding around input form elements git-svn-id: svn://10.0.0.236/trunk@1231 18797224-902f-48f8-a5cc-f745e15eee43 --- .../layout/html/forms/src/nsFormElement.cpp | 154 --------------- .../layout/html/forms/src/nsInputButton.cpp | 6 +- .../layout/html/forms/src/nsInputFrame.cpp | 184 +++++++++++------- mozilla/layout/html/forms/src/nsInputFrame.h | 17 +- 4 files changed, 136 insertions(+), 225 deletions(-) delete mode 100644 mozilla/layout/html/forms/src/nsFormElement.cpp diff --git a/mozilla/layout/html/forms/src/nsFormElement.cpp b/mozilla/layout/html/forms/src/nsFormElement.cpp deleted file mode 100644 index 6db012b2532..00000000000 --- a/mozilla/layout/html/forms/src/nsFormElement.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* -*- 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. - */ -#include "nsHTMLParts.h" -#include "nsHTMLTagContent.h" -#include "nsIRenderingContext.h" -#include "nsIPresContext.h" -#include "nsIStyleContext.h" -#include "nsLeafFrame.h" -#include "nsCSSRendering.h" -#include "nsHTMLIIDs.h" - -// this file is obsolete and will be removed - -static NS_DEFINE_IID(kStyleBorderSID, NS_STYLEBORDER_SID); - -enum FormElementType { - eFormElementType_Submit, - eFormElementType_Reset, - eFormElementType_Text, - eFormElementType_Password, - eFormElementType_TextArea, -}; - -class FormElementFrame : public nsLeafFrame { -public: - FormElementFrame(nsIContent* aContent, - PRInt32 aIndexInParent, - nsIFrame* aParentFrame); - - virtual void Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect); - -protected: - virtual ~FormElementFrame(); - virtual void GetDesiredSize(nsIPresContext* aPresContext, - nsReflowMetrics& aDesiredSize, - const nsSize& aMaxSize); -}; - -class FormElementContent : public nsHTMLTagContent { -public: - FormElementContent(nsIAtom* aTag, FormElementType aType); - - virtual nsIFrame* CreateFrame(nsIPresContext* aPresContext, - PRInt32 aIndexInParent, - nsIFrame* aParentFrame); - -protected: - virtual ~FormElementContent(); - - FormElementType mType; -}; - -//---------------------------------------------------------------------- - -FormElementFrame::FormElementFrame(nsIContent* aContent, - PRInt32 aIndexInParent, - nsIFrame* aParentFrame) - : nsLeafFrame(aContent, aIndexInParent, aParentFrame) -{ -} - -FormElementFrame::~FormElementFrame() -{ -} - -// XXX it would be cool if form element used our rendering sw, then -// they could be blended, and bordered, and so on... -void FormElementFrame::Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect) -{ - nsStyleBorder* myBorder = - (nsStyleBorder*)mStyleContext->GetData(kStyleBorderSID); - nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, - aDirtyRect, mRect, *myBorder, 0); -} - -void FormElementFrame::GetDesiredSize(nsIPresContext* aPresContext, - nsReflowMetrics& aDesiredSize, - const nsSize& aMaxSize) -{ - float p2t = aPresContext->GetPixelsToTwips(); - aDesiredSize.width = nscoord(75 * p2t); - aDesiredSize.height = nscoord(37 * p2t); - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; -} - -//---------------------------------------------------------------------- - -FormElementContent::FormElementContent(nsIAtom* aTag, FormElementType aType) - : nsHTMLTagContent(aTag), - mType(aType) -{ -} - -FormElementContent::~FormElementContent() -{ -} - -nsIFrame* FormElementContent::CreateFrame(nsIPresContext* aPresContext, - PRInt32 aIndexInParent, - nsIFrame* aParentFrame) -{ - nsIFrame* rv = new FormElementFrame(this, aIndexInParent, aParentFrame); - return rv; -} - -NS_HTML nsresult -NS_NewHTMLSubmitButton(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag) -{ - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); - if (nsnull == aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } - nsIHTMLContent* it = new FormElementContent(aTag, eFormElementType_Submit); - if (nsnull == it) { - return NS_ERROR_OUT_OF_MEMORY; - } - return it->QueryInterface(kIHTMLContentIID, (void**) aInstancePtrResult); -} - -NS_HTML nsresult -NS_NewHTMLResetButton(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag) -{ - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); - if (nsnull == aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } - nsIHTMLContent* it = new FormElementContent(aTag, eFormElementType_Reset); - if (nsnull == it) { - return NS_ERROR_OUT_OF_MEMORY; - } - return it->QueryInterface(kIHTMLContentIID, (void**) aInstancePtrResult); -} diff --git a/mozilla/layout/html/forms/src/nsInputButton.cpp b/mozilla/layout/html/forms/src/nsInputButton.cpp index ed3657d420e..dffa7ea2dc3 100644 --- a/mozilla/layout/html/forms/src/nsInputButton.cpp +++ b/mozilla/layout/html/forms/src/nsInputButton.cpp @@ -386,8 +386,10 @@ nsInputButtonFrame::ResizeReflow(nsIPresContext* aPresContext, aMaxElementSize->width = aDesiredSize.width; aMaxElementSize->height = aDesiredSize.height; } - mCacheBounds.width = aDesiredSize.width; - mCacheBounds.height = aDesiredSize.height; + mViewBounds.x = 0; + mViewBounds.y = 0; + mViewBounds.width = aDesiredSize.width; + mViewBounds.height = aDesiredSize.height; aStatus = frComplete; return NS_OK; } diff --git a/mozilla/layout/html/forms/src/nsInputFrame.cpp b/mozilla/layout/html/forms/src/nsInputFrame.cpp index 823555c4803..f7af8584b7e 100644 --- a/mozilla/layout/html/forms/src/nsInputFrame.cpp +++ b/mozilla/layout/html/forms/src/nsInputFrame.cpp @@ -49,6 +49,7 @@ static NS_DEFINE_IID(kStyleFontSID, NS_STYLEFONT_SID); static NS_DEFINE_IID(kStylePositionSID, NS_STYLEPOSITION_SID); +static NS_DEFINE_IID(kStyleSpacingSID, NS_STYLESPACING_SID); struct nsInputCallbackData { @@ -63,8 +64,6 @@ struct nsInputCallbackData nsInputFrame::nsInputFrame(nsIContent* aContent, nsIFrame* aParentFrame) : nsLeafFrame(aContent, aParentFrame) { - mCacheBounds.width = 0; - mCacheBounds.height = 0; mLastMouseState = eMouseNone; } @@ -77,6 +76,48 @@ NS_METHOD nsInputFrame::SetRect(const nsRect& aRect) return nsInputFrameSuper::SetRect(aRect); } +NS_METHOD +nsInputFrame::MoveTo(nscoord aX, nscoord aY) +{ + if ((aX != mRect.x) || (aY != mRect.y)) { + mRect.x = aX; + mRect.y = aY; + + // Let the view know + nsIView* view = nsnull; + GetView(view); + if (nsnull != view) { + // Position view relative to it's parent, not relative to our + // parent frame (our parent frame may not have a view). Also, + // inset the view by the border+padding if present + nsIView* parentWithView; + nsPoint origin; + GetOffsetFromView(origin, parentWithView); + view->SetPosition(origin.x + mViewBounds.x, origin.y + mViewBounds.y); + NS_IF_RELEASE(parentWithView); + NS_RELEASE(view); + } + } + + return NS_OK; +} + +NS_METHOD +nsInputFrame::SizeTo(nscoord aWidth, nscoord aHeight) +{ + mRect.width = aWidth; + mRect.height = aHeight; + + // Let the view know the correct size + nsIView* view = nsnull; + GetView(view); + if (nsnull != view) { + view->SetDimensions(mViewBounds.width, mViewBounds.height); + NS_RELEASE(view); + } + return NS_OK; +} + // XXX it would be cool if form element used our rendering sw, then // they could be blended, and bordered, and so on... @@ -85,57 +126,50 @@ nsInputFrame::Paint(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect) { - static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID); - - nsPoint offset; - nsIView *parent; - GetOffsetFromView(offset, parent); - - //offset.x += padding + GetPadding(); // add back the padding if present - - if (nsnull == parent) { // a problem - NS_ASSERTION(0, "parent view was null\n"); - } else { - nsIView* view; - GetView(view); - float t2p = aPresContext.GetTwipsToPixels(); - //nsIWidget *widget = view->GetWindow(); - nsIWidget* widget; - nsresult result = GetWidget(view, &widget); - if (NS_OK == result) { - nsRect vBounds; - view->GetBounds(vBounds); - - if ((vBounds.x != offset.x) || (vBounds.y != offset.y)) - view->SetPosition(offset.x, offset.y); - - // initially the widget was created as hidden - if (nsViewVisibility_kHide == view->GetVisibility()) { - nsInput* content; - GetContent((nsIContent *&) content); - content->GetFormManager()->Init(PR_FALSE); // this only inits the 1st time - NS_RELEASE(content); - - view->SetVisibility(nsViewVisibility_kShow); - PostCreateWidget(&aPresContext, view); - } - } else { - NS_ASSERTION(0, "could not get widget"); - } - NS_IF_RELEASE(widget); - NS_RELEASE(view); - NS_RELEASE(parent); + // Make sure the widget is visible if it isn't currently visible + nsIView* view = nsnull; + GetView(view); + if (nsnull != view) { + SetViewVisiblity(&aPresContext, PR_TRUE); + NS_RELEASE(view); + } + + // Point borders/padding if any + return nsInputFrameSuper::Paint(aPresContext, aRenderingContext, aDirtyRect); +} + +void +nsInputFrame::SetViewVisiblity(nsIPresContext* aPresContext, PRBool aShow) +{ + nsIView* view = nsnull; + GetView(view); + if (nsnull != view) { + nsIWidget* widget; + nsresult result = GetWidget(view, &widget); + if (NS_OK == result) { + // initially the widget was created as hidden + nsViewVisibility newVisibility = + aShow ? nsViewVisibility_kShow : nsViewVisibility_kHide; + if (newVisibility != view->GetVisibility()) { + // this only inits the 1st time + // XXX kipp says: this is yucky; init on first visibility seems lame + ((nsInput*)mContent)->GetFormManager()->Init(PR_FALSE); + view->SetVisibility(newVisibility); + PostCreateWidget(aPresContext, view); + } + NS_IF_RELEASE(widget); + } + NS_RELEASE(view); } - return NS_OK; } PRBool nsInputFrame::BoundsAreSet() { - if ((0 != mCacheBounds.width) || (0 != mCacheBounds.height)) { + if ((0 != mRect.width) || (0 != mRect.height)) { return PR_TRUE; } else { - return PR_FALSE; + return PR_FALSE; } } @@ -181,11 +215,9 @@ nsInputFrame::ResizeReflow(nsIPresContext* aPresContext, nsSize* aMaxElementSize, ReflowStatus& aStatus) { - nsIView* view; + nsIView* view = nsnull; GetView(view); - if (nsnull == view) { - static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); @@ -194,21 +226,21 @@ nsInputFrame::ResizeReflow(nsIPresContext* aPresContext, GetStyleContext(aPresContext, mStyleContext); } nsresult result = - NSRepository::CreateInstance(kViewCID, nsnull, kIViewIID, (void **)&view);// need to release + NSRepository::CreateInstance(kViewCID, nsnull, kIViewIID, + (void **)&view); if (NS_OK != result) { NS_ASSERTION(0, "Could not create view for button"); aStatus = frNotComplete; - return NS_OK; + return result; } nsIPresShell *presShell = aPresContext->GetShell(); // need to release nsIViewManager *viewMan = presShell->GetViewManager(); // need to release - nsReflowMetrics layoutSize; nsSize widgetSize; - GetDesiredSize(aPresContext, aMaxSize, layoutSize, widgetSize); - mCacheBounds.width = layoutSize.width; // YYY what about caching widget size? - mCacheBounds.height = layoutSize.height; + GetDesiredSize(aPresContext, aMaxSize, aDesiredSize, widgetSize); + mViewBounds.width = widgetSize.width; + mViewBounds.height = widgetSize.height; nsRect boundBox(0, 0, widgetSize.width, widgetSize.height); nsIFrame* parWithView; @@ -220,8 +252,9 @@ nsInputFrame::ResizeReflow(nsIPresContext* aPresContext, const nsIID& id = GetCID(); nsInputWidgetData* initData = GetWidgetInitData(); // needs to be deleted // initialize the view as hidden since we don't know the (x,y) until Paint - result = view->Init(viewMan, boundBox, parView, &id, initData, nsnull, 0, nsnull, - 1.0f, nsViewVisibility_kHide); + result = view->Init(viewMan, boundBox, parView, &id, initData, + nsnull, 0, nsnull, + 1.0f, nsViewVisibility_kHide); if (nsnull != initData) { delete(initData); } @@ -243,19 +276,38 @@ nsInputFrame::ResizeReflow(nsIPresContext* aPresContext, } viewMan->InsertChild(parView, view, 0); - SetView(view); - //PostCreateWidget(aPresContext, view); + + SetView(view); + NS_RELEASE(view); NS_IF_RELEASE(parView); - NS_IF_RELEASE(view); NS_IF_RELEASE(viewMan); NS_IF_RELEASE(presShell); } - aDesiredSize.width = mCacheBounds.width; - aDesiredSize.height = mCacheBounds.height; - aDesiredSize.ascent = mCacheBounds.height; + else { + nsSize widgetSize; + GetDesiredSize(aPresContext, aMaxSize, aDesiredSize, widgetSize); + + // If we are being reflowed and have a view, hide the view until + // we are told to paint (which is when our location will have + // stabilized). + SetViewVisiblity(aPresContext, PR_FALSE); + } + + // Add in borders and padding + nsStyleSpacing* space = + (nsStyleSpacing*)mStyleContext->GetData(kStyleSpacingSID); + aDesiredSize.width += space->mBorderPadding.left + + space->mBorderPadding.right; + aDesiredSize.height += space->mBorderPadding.top + + space->mBorderPadding.bottom; + aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; + // Remember the view's offset coordinates + mViewBounds.x = space->mBorderPadding.left; + mViewBounds.y = space->mBorderPadding.top; + if (nsnull != aMaxElementSize) { aMaxElementSize->width = aDesiredSize.width; aMaxElementSize->height = aDesiredSize.height; @@ -469,7 +521,8 @@ nsInputFrame::CalculateSize (nsIPresContext* aPresContext, nsInputFrame* aFrame, nsSize textSize(0,0); nsInput* content; - aFrame->GetContent((nsIContent *&) content); + aFrame->GetContent((nsIContent*&) content); + nsAutoString valAttr; nsContentAttr valStatus = eContentAttr_NotThere; if (nsnull != aSpec.mColValueAttr) { @@ -553,15 +606,14 @@ nsInputFrame::CalculateSize (nsIPresContext* aPresContext, nsInputFrame* aFrame, aRowHeight = textSize.height; } - // add padding to width if width wasn't specified either from css or size attr + // add padding to width if width wasn't specified either from css or + // size attr if (!aWidthExplicit) { aBounds.width += charWidth; } NS_RELEASE(content); - return numRows; - } diff --git a/mozilla/layout/html/forms/src/nsInputFrame.h b/mozilla/layout/html/forms/src/nsInputFrame.h index c774e656db3..e0bda2f0789 100644 --- a/mozilla/layout/html/forms/src/nsInputFrame.h +++ b/mozilla/layout/html/forms/src/nsInputFrame.h @@ -90,6 +90,9 @@ public: PRBool& aHeightExplicit, nscoord& aRowSize); // nsLeafFrame overrides + NS_IMETHOD MoveTo(nscoord aX, nscoord aY); + NS_METHOD SizeTo(nscoord aWidth, nscoord aHeight); + /** * Respond to a gui event * @see nsIFrame::HandleEvent @@ -100,8 +103,6 @@ public: NS_IMETHOD SetRect(const nsRect& aRect); - virtual PRBool IsHidden(); - /** * Draw this frame within the context of a presentation context and rendering context * @see nsIFrame::Paint @@ -122,6 +123,11 @@ public: // new behavior + /** + * Return true if the underlying form element is a hidden form element + */ + PRBool IsHidden(); + /** * Get the class id of the widget associated with this frame * @return the class id @@ -175,6 +181,8 @@ protected: */ PRBool BoundsAreSet(); + void SetViewVisiblity(nsIPresContext* aPresContext, PRBool aShow); + /** * Get the size that this frame would occupy without any constraints * @param aPresContext the presentation context @@ -204,7 +212,10 @@ protected: nscoord GetStyleDim(nsIPresContext& aPresContext, nscoord aMaxDim, nscoord aMaxWidth, const nsStyleCoord& aCoord); - nsSize mCacheBounds; + // Location of the view within the frame. The view will be inset by + // the border+padding. + nsRect mViewBounds; + nsMouseState mLastMouseState; };