Support (mostly) border+padding around input form elements
git-svn-id: svn://10.0.0.236/trunk@1231 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
f62d45c7d8
commit
87a10a39d9
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user