mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-22 20:34:01 +00:00
Work in progress on scroll frame code
This commit is contained in:
parent
013f3adffa
commit
713db072d6
@ -325,6 +325,8 @@ protected:
|
||||
nsIFrame* aParentFrame,
|
||||
nsIFrame*& aFrame);
|
||||
|
||||
PRBool IsScrollable(nsIFrame* aFrame, const nsStyleDisplay* aDisplay);
|
||||
|
||||
protected:
|
||||
PRUint32 mInHeap : 1;
|
||||
PRUint32 mRefCnt : 31;
|
||||
@ -1351,6 +1353,28 @@ HTMLStyleSheetImpl::ConstructFrameByDisplayType(nsIPresContext* aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRBool
|
||||
HTMLStyleSheetImpl::IsScrollable(nsIFrame* aFrame,
|
||||
const nsStyleDisplay* aDisplay)
|
||||
{
|
||||
// If the overflow property is scroll then it's scrollable regardless
|
||||
// of whether the content overflows the block.
|
||||
// XXX This isn't correct. Only do this if the height is not allowed to
|
||||
// grow to accomodate its child frames...
|
||||
if (NS_STYLE_OVERFLOW_SCROLL == aDisplay->mOverflow) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ((NS_STYLE_OVERFLOW_SCROLL == aDisplay->mOverflow) ||
|
||||
// If the element has a fixed height (it isn't auto) and an overflow
|
||||
// property of scroll or auto, then it's potentially scrollable.
|
||||
// XXX Deal with width considerations, too
|
||||
(NS_STYLE_OVERFLOW_AUTO == aDisplay->mOverflow)) {
|
||||
#endif
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLStyleSheetImpl::ConstructFrame(nsIPresContext* aPresContext,
|
||||
nsIContent* aContent,
|
||||
@ -1406,20 +1430,32 @@ HTMLStyleSheetImpl::ConstructFrame(nsIPresContext* aPresContext,
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
// If the frame is a block-level frame and it has a fixed height and overflow
|
||||
// property of scroll, then wrap it in a scroll frame.
|
||||
// XXX Deal with replaced elements and overflow of auto and width, too
|
||||
nsIFrame* kidFrame = nsnull;
|
||||
nsresult rv;
|
||||
if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) ||
|
||||
(NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) {
|
||||
rv = NS_NewScrollFrame(&kidFrame, aKid, aParentFrame);
|
||||
if (NS_OK == rv) {
|
||||
kidFrame->SetStyleContext(aPresContext, kidSC);
|
||||
// If the frame is a block-level frame and is scrollable then wrap it
|
||||
// in a scroll frame.
|
||||
// XXX Applies to replaced elements, too, but how to tell if the element
|
||||
// is replaced?
|
||||
if (nsnull != aFrameSubTree) {
|
||||
if (display->IsBlockLevel() && IsScrollable(aFrameSubTree, display)) {
|
||||
nsIFrame* scrollFrame;
|
||||
|
||||
if NS_SUCCEEDED(NS_NewScrollFrame(aContent, aParentFrame, scrollFrame)) {
|
||||
// The scroll frame gets the original style context, and the scrolled
|
||||
// frame gets a pseudo style context.
|
||||
// XXX Is this the best way to do this?
|
||||
scrollFrame->SetStyleContext(aPresContext, styleContext);
|
||||
|
||||
nsIStyleContext* pseudoStyle;
|
||||
pseudoStyle = aPresContext->ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo,
|
||||
scrollFrame);
|
||||
aFrameSubTree->SetStyleContext(aPresContext, pseudoStyle);
|
||||
NS_RELEASE(pseudoStyle);
|
||||
|
||||
// Initialize the scroll frame
|
||||
scrollFrame->Init(*aPresContext, aFrameSubTree);
|
||||
aFrameSubTree = scrollFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
NS_RELEASE(styleContext);
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "nsPlaceholderFrame.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsScrollFrame.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsViewsCID.h"
|
||||
|
@ -303,6 +303,10 @@ nsresult
|
||||
NS_NewWBRFrame(nsIContent* aContent, nsIFrame* aParentFrame,
|
||||
nsIFrame*& aResult);
|
||||
|
||||
extern nsresult
|
||||
NS_NewScrollFrame(nsIContent* aContent, nsIFrame* aParentFrame,
|
||||
nsIFrame*& aResult);
|
||||
|
||||
// forms
|
||||
extern nsresult
|
||||
NS_NewFormFrame(nsIContent* aContent, nsIFrame* aParentFrame,
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "nsPlaceholderFrame.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsScrollFrame.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsViewsCID.h"
|
||||
|
@ -303,6 +303,10 @@ nsresult
|
||||
NS_NewWBRFrame(nsIContent* aContent, nsIFrame* aParentFrame,
|
||||
nsIFrame*& aResult);
|
||||
|
||||
extern nsresult
|
||||
NS_NewScrollFrame(nsIContent* aContent, nsIFrame* aParentFrame,
|
||||
nsIFrame*& aResult);
|
||||
|
||||
// forms
|
||||
extern nsresult
|
||||
NS_NewFormFrame(nsIContent* aContent, nsIFrame* aParentFrame,
|
||||
|
@ -15,7 +15,6 @@
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#include "nsScrollFrame.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsIReflowCommand.h"
|
||||
@ -27,264 +26,123 @@
|
||||
#include "nsBodyFrame.h"
|
||||
#include "nsHTMLContainerFrame.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsIScrollableView.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
|
||||
#include "nsBodyFrame.h"
|
||||
static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID);
|
||||
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
|
||||
|
||||
class nsScrollBodyFrame : public nsContainerFrame {
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class nsScrollViewFrame : public nsHTMLContainerFrame {
|
||||
public:
|
||||
nsScrollBodyFrame(nsIContent* aContent, nsIFrame* aParent);
|
||||
nsScrollViewFrame(nsIContent* aContent, nsIFrame* aParent);
|
||||
|
||||
NS_IMETHOD Init(nsIPresContext& aPresContext, nsIFrame* aChildList);
|
||||
|
||||
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
NS_IMETHOD Paint(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect);
|
||||
|
||||
NS_IMETHOD ListTag(FILE* out = stdout) const;
|
||||
|
||||
protected:
|
||||
void CreateFirstChild(nsIPresContext* aPresContext);
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
};
|
||||
|
||||
nsScrollBodyFrame::nsScrollBodyFrame(nsIContent* aContent, nsIFrame* aParent)
|
||||
: nsContainerFrame(aContent, aParent)
|
||||
nsScrollViewFrame::nsScrollViewFrame(nsIContent* aContent, nsIFrame* aParent)
|
||||
: nsHTMLContainerFrame(aContent, aParent)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsScrollBodyFrame::CreateFirstChild(nsIPresContext* aPresContext)
|
||||
{
|
||||
// Are we paginated?
|
||||
if (aPresContext->IsPaginated()) {
|
||||
// Yes. Create the first page frame
|
||||
mFirstChild = new nsPageFrame(mContent, this);/* XXX mContent won't work here */
|
||||
} else {
|
||||
if (nsnull != mContent) {
|
||||
#if 0
|
||||
// Create a frame for the child we are wrapping up
|
||||
nsIContentDelegate* cd = mContent->GetDelegate(aPresContext);
|
||||
if (nsnull != cd) {
|
||||
nsIStyleContext* kidStyleContext =
|
||||
aPresContext->ResolveStyleContextFor(mContent, this);
|
||||
nsresult rv = cd->CreateFrame(aPresContext, mContent, this,
|
||||
kidStyleContext, mFirstChild);
|
||||
NS_RELEASE(kidStyleContext);
|
||||
if (NS_OK == rv) {
|
||||
mChildCount = 1;
|
||||
mLastContentOffset = mFirstContentOffset;
|
||||
}
|
||||
NS_RELEASE(cd);
|
||||
}
|
||||
#else
|
||||
nsBodyFrame::NewFrame(&mFirstChild, mContent, this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Hack
|
||||
#define PAGE_SPACING 100
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScrollBodyFrame::Reflow(nsIPresContext& aPresContext,
|
||||
nsScrollViewFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList)
|
||||
{
|
||||
mFirstChild = aChildList;
|
||||
|
||||
// XXX Unless it's already a body frame, child frames that are containers
|
||||
// need to be wrapped in a body frame
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScrollViewFrame::Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, this,
|
||||
nsnull, PR_TRUE);
|
||||
|
||||
NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
|
||||
("enter nsScrollBodyFrame::Reflow: maxSize=%d,%d",
|
||||
("enter nsScrollViewFrame::Reflow: maxSize=%d,%d",
|
||||
aReflowState.maxSize.width,
|
||||
aReflowState.maxSize.height));
|
||||
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
// Create a view
|
||||
if (eReflowReason_Initial == aReflowState.reason) {
|
||||
// XXX It would be nice if we could do this sort of thing in our Init()
|
||||
// member function instead of here...
|
||||
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, this,
|
||||
nsnull, PR_TRUE);
|
||||
}
|
||||
|
||||
// XXX Incremental reflow code doesn't handle page mode at all...
|
||||
if (eReflowReason_Incremental == aReflowState.reason) {
|
||||
// We don't expect the target of the reflow command to be the root
|
||||
// content frame
|
||||
#ifdef NS_DEBUG
|
||||
nsIFrame* target;
|
||||
aReflowState.reflowCommand->GetTarget(target);
|
||||
NS_ASSERTION(target != this, "root content frame is reflow command target");
|
||||
#endif
|
||||
|
||||
// Verify the next frame in the reflow chain is our child frame
|
||||
nsIFrame* next;
|
||||
aReflowState.reflowCommand->GetNext(next);
|
||||
NS_ASSERTION(next == mFirstChild, "unexpected next reflow command frame");
|
||||
// Scroll frame handles the border, and we handle the padding and background
|
||||
const nsStyleSpacing* spacing = (const nsStyleSpacing*)
|
||||
mStyleContext->GetStyleData(eStyleStruct_Spacing);
|
||||
nsMargin padding;
|
||||
spacing->CalcPaddingFor(this, padding);
|
||||
|
||||
nsSize maxSize(aReflowState.maxSize.width, NS_UNCONSTRAINEDSIZE);
|
||||
nsHTMLReflowState kidReflowState(aPresContext, next, aReflowState, maxSize);
|
||||
nsIHTMLReflow* htmlReflow;
|
||||
|
||||
if (NS_OK == mFirstChild->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) {
|
||||
// Dispatch the reflow command to our child frame. Allow it to be as high
|
||||
// as it wants
|
||||
ReflowChild(mFirstChild, aPresContext, aDesiredSize, kidReflowState, aStatus);
|
||||
|
||||
// Place and size the child. Make sure the child is at least as
|
||||
// tall as our max size (the containing window)
|
||||
if (aDesiredSize.height < aReflowState.maxSize.height) {
|
||||
aDesiredSize.height = aReflowState.maxSize.height;
|
||||
}
|
||||
|
||||
nsRect rect(0, 0, aDesiredSize.width, aDesiredSize.height);
|
||||
mFirstChild->SetRect(rect);
|
||||
// XXX Why are we sending a DidReflow() notification here?
|
||||
htmlReflow->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED);
|
||||
}
|
||||
// Allow the child frame to be as wide as our max width (minus scrollbar
|
||||
// width and padding), and as high as it wants to be.
|
||||
nsSize maxSize;
|
||||
nsIDeviceContext* dc = aPresContext.GetDeviceContext();
|
||||
float sbWidth, sbHeight;
|
||||
|
||||
} else {
|
||||
// Do we have any children?
|
||||
if (nsnull == mFirstChild) {
|
||||
// No, create the first child frame
|
||||
CreateFirstChild(&aPresContext);
|
||||
}
|
||||
dc->GetScrollBarDimensions(sbWidth, sbHeight);
|
||||
maxSize.width = aReflowState.maxSize.width - NSToCoordRound(sbWidth) -
|
||||
(padding.left + padding.right);
|
||||
NS_RELEASE(dc);
|
||||
maxSize.height = NS_UNCONSTRAINEDSIZE;
|
||||
|
||||
// Resize our frames
|
||||
if (nsnull != mFirstChild) {
|
||||
if (aPresContext.IsPaginated()) {
|
||||
nscoord y = PAGE_SPACING;
|
||||
nsHTMLReflowMetrics kidSize(aDesiredSize.maxElementSize);
|
||||
nsSize pageSize(aPresContext.GetPageWidth(),
|
||||
aPresContext.GetPageHeight());
|
||||
|
||||
// Tile the pages vertically
|
||||
for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) {
|
||||
// Reflow the page
|
||||
nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aReflowState, pageSize);
|
||||
nsReflowStatus status;
|
||||
// Reflow the child
|
||||
nsHTMLReflowMetrics kidMetrics(aDesiredSize.maxElementSize);
|
||||
nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, aReflowState, maxSize);
|
||||
|
||||
// Place and size the page. If the page is narrower than our
|
||||
// max width then center it horizontally
|
||||
nsIDeviceContext *dx = aPresContext.GetDeviceContext();
|
||||
float sbWidth, sbHeight;
|
||||
dx->GetScrollBarDimensions(sbWidth, sbHeight);
|
||||
nscoord extra = aReflowState.maxSize.width - kidSize.width -
|
||||
NSToCoordRound(sbWidth);
|
||||
NS_RELEASE(dx);
|
||||
nscoord x = extra > 0 ? extra / 2 : 0;
|
||||
nsIHTMLReflow* htmlReflow;
|
||||
ReflowChild(mFirstChild, aPresContext, kidMetrics, kidReflowState, aStatus);
|
||||
NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
|
||||
|
||||
// Place and size the child
|
||||
nsRect rect(padding.left, padding.top, kidMetrics.width, kidMetrics.height);
|
||||
mFirstChild->SetRect(rect);
|
||||
|
||||
if (NS_OK == kidFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) {
|
||||
htmlReflow->WillReflow(aPresContext);
|
||||
ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, status);
|
||||
|
||||
kidFrame->SetRect(nsRect(x, y, kidSize.width, kidSize.height));
|
||||
htmlReflow->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED);
|
||||
y += kidSize.height;
|
||||
|
||||
// Leave a slight gap between the pages
|
||||
y += PAGE_SPACING;
|
||||
|
||||
// Is the page complete?
|
||||
nsIFrame* kidNextInFlow;
|
||||
|
||||
kidFrame->GetNextInFlow(kidNextInFlow);
|
||||
if (NS_FRAME_IS_COMPLETE(status)) {
|
||||
NS_ASSERTION(nsnull == kidNextInFlow, "bad child flow list");
|
||||
} else if (nsnull == kidNextInFlow) {
|
||||
// The page isn't complete and it doesn't have a next-in-flow so
|
||||
// create a continuing page
|
||||
nsIStyleContext* kidSC;
|
||||
kidFrame->GetStyleContext(&aPresContext, kidSC);
|
||||
nsIFrame* continuingPage;
|
||||
nsresult rv = kidFrame->CreateContinuingFrame(aPresContext, this,
|
||||
kidSC, continuingPage);
|
||||
NS_RELEASE(kidSC);
|
||||
|
||||
// Add it to our child list
|
||||
#ifdef NS_DEBUG
|
||||
nsIFrame* kidNextSibling;
|
||||
|
||||
kidFrame->GetNextSibling(kidNextSibling);
|
||||
NS_ASSERTION(nsnull == kidNextSibling, "unexpected sibling");
|
||||
#endif
|
||||
kidFrame->SetNextSibling(continuingPage);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the next page
|
||||
kidFrame->GetNextSibling(kidFrame);
|
||||
}
|
||||
|
||||
// Return our desired size
|
||||
aDesiredSize.width = aReflowState.maxSize.width;
|
||||
aDesiredSize.height = y;
|
||||
|
||||
} else {
|
||||
// Allow the frame to be as wide as our max width, and as high
|
||||
// as it wants to be.
|
||||
nsSize maxSize(aReflowState.maxSize.width, NS_UNCONSTRAINEDSIZE);
|
||||
nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, aReflowState, maxSize);
|
||||
nsIHTMLReflow* htmlReflow;
|
||||
|
||||
if (NS_OK == mFirstChild->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) {
|
||||
// Get the child's desired size. Our child's desired height is our
|
||||
// desired size
|
||||
htmlReflow->WillReflow(aPresContext);
|
||||
ReflowChild(mFirstChild, aPresContext, aDesiredSize, kidReflowState, aStatus);
|
||||
NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
|
||||
|
||||
#if 0
|
||||
// Place and size the child. Make sure the child is at least as
|
||||
// tall as our max size (the containing window)
|
||||
if (aDesiredSize.height < aReflowState.maxSize.height) {
|
||||
aDesiredSize.height = aReflowState.maxSize.height;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Place and size the child
|
||||
nsRect rect(0, 0, aDesiredSize.width, aDesiredSize.height);
|
||||
mFirstChild->SetRect(rect);
|
||||
htmlReflow->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
aDesiredSize.width = aReflowState.maxSize.width;
|
||||
aDesiredSize.height = 1;
|
||||
aDesiredSize.ascent = aDesiredSize.height;
|
||||
aDesiredSize.descent = 0;
|
||||
if (nsnull != aDesiredSize.maxElementSize) {
|
||||
aDesiredSize.maxElementSize->width = 0;
|
||||
aDesiredSize.maxElementSize->height = 0;
|
||||
}
|
||||
}
|
||||
// Determine our size. Our width is our maxWidth and our height is the max
|
||||
// of our child's height plus padding and our maxHeight (if our maxHeight is
|
||||
// constrained).
|
||||
aDesiredSize.width = aReflowState.maxSize.width;
|
||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.maxSize.height) {
|
||||
aDesiredSize.height = kidMetrics.height + padding.top + padding.bottom;
|
||||
}
|
||||
else {
|
||||
aDesiredSize.height = aReflowState.maxSize.height;
|
||||
}
|
||||
|
||||
NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
|
||||
("exit nsScrollBodyFrame::Reflow: status=%d width=%d height=%d",
|
||||
aStatus, aDesiredSize.width, aDesiredSize.height));
|
||||
("exit nsScrollViewFrame::Reflow: status=%d width=%d height=%d",
|
||||
aStatus, aDesiredSize.width, aDesiredSize.height));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScrollBodyFrame::Paint(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect)
|
||||
PRIntn
|
||||
nsScrollViewFrame::GetSkipSides() const
|
||||
{
|
||||
// If we're paginated then fill the dirty rect with white
|
||||
if (aPresContext.IsPaginated()) {
|
||||
// Cross hatching would be nicer...
|
||||
aRenderingContext.SetColor(NS_RGB(255,255,255));
|
||||
aRenderingContext.FillRect(aDirtyRect);
|
||||
}
|
||||
|
||||
nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect);
|
||||
return NS_OK;
|
||||
// Scroll frame handles the border...
|
||||
return 0xF;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScrollBodyFrame::ListTag(FILE* out) const
|
||||
nsScrollViewFrame::ListTag(FILE* out) const
|
||||
{
|
||||
fputs("*scrollbodyframe<", out);
|
||||
fputs("*scrollviewframe<", out);
|
||||
nsIAtom* atom;
|
||||
mContent->GetTag(atom);
|
||||
if (nsnull != atom) {
|
||||
@ -299,36 +157,70 @@ nsScrollBodyFrame::ListTag(FILE* out) const
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class nsScrollInnerFrame : public nsContainerFrame {
|
||||
/**
|
||||
* The scrolling view frame creates and manages the scrolling view.
|
||||
* It creates a nsScrollViewFrame which handles padding and rendering
|
||||
* of the background.
|
||||
*/
|
||||
class nsScrollingViewFrame : public nsHTMLContainerFrame {
|
||||
public:
|
||||
nsScrollInnerFrame(nsIContent* aContent, nsIFrame* aParent);
|
||||
nsScrollingViewFrame(nsIContent* aContent, nsIFrame* aParent);
|
||||
|
||||
NS_IMETHOD Init(nsIPresContext& aPresContext, nsIFrame* aChildList);
|
||||
|
||||
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
NS_IMETHOD Paint(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect);
|
||||
|
||||
NS_IMETHOD ListTag(FILE* out = stdout) const;
|
||||
|
||||
protected:
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
};
|
||||
|
||||
nsScrollInnerFrame::nsScrollInnerFrame(nsIContent* aContent, nsIFrame* aParent)
|
||||
: nsContainerFrame(aContent, aParent)
|
||||
nsScrollingViewFrame::nsScrollingViewFrame(nsIContent* aContent, nsIFrame* aParent)
|
||||
: nsHTMLContainerFrame(aContent, aParent)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScrollInnerFrame::Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
nsScrollingViewFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList)
|
||||
{
|
||||
// Create a scroll view frame
|
||||
mFirstChild = new nsScrollViewFrame(mContent, this);
|
||||
if (nsnull == mFirstChild) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
// Have it use our style context
|
||||
mFirstChild->SetStyleContext(&aPresContext, mStyleContext);
|
||||
|
||||
// Reset the child frame's geometric and content parent to be
|
||||
// the scroll view frame
|
||||
aChildList->SetGeometricParent(mFirstChild);
|
||||
aChildList->SetContentParent(mFirstChild);
|
||||
|
||||
// Init the scroll view frame passing it the child list
|
||||
return mFirstChild->Init(aPresContext, aChildList);
|
||||
}
|
||||
|
||||
//XXX incremental reflow pass through
|
||||
NS_IMETHODIMP
|
||||
nsScrollingViewFrame::Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
|
||||
("enter nsScrollInnerFrame::Reflow: maxSize=%d,%d",
|
||||
("enter nsScrollingViewFrame::Reflow: maxSize=%d,%d",
|
||||
aReflowState.maxSize.width,
|
||||
aReflowState.maxSize.height));
|
||||
|
||||
// Make sure we have a scrolling view
|
||||
nsIView* view;
|
||||
GetView(view);
|
||||
if (nsnull == view) {
|
||||
@ -350,77 +242,75 @@ nsScrollInnerFrame::Reflow(nsIPresContext& aPresContext,
|
||||
nsnull,
|
||||
kIViewIID,
|
||||
(void **)&view);
|
||||
// XXX We want the scrolling view to have a widget to clip any child
|
||||
// widgets that aren't visible, e.g. form elements, but there's currently
|
||||
// a bug which is why it's commented out
|
||||
if ((NS_OK != rv) || (NS_OK != view->Init(viewManager,
|
||||
mRect,
|
||||
parentView))) {
|
||||
parentView,
|
||||
nsnull))) {
|
||||
// &kWidgetCID))) {
|
||||
NS_RELEASE(viewManager);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Insert new view as a child of the parent view
|
||||
viewManager->InsertChild(parentView, view, 0);
|
||||
NS_RELEASE(viewManager);
|
||||
|
||||
// NS_RELEASE(parentView);
|
||||
SetView(view);
|
||||
NS_RELEASE(viewManager);
|
||||
}
|
||||
if (nsnull == view) {
|
||||
return NS_OK;
|
||||
}
|
||||
// NS_RELEASE(view);
|
||||
|
||||
if (nsnull == mFirstChild) {
|
||||
mFirstChild = new nsScrollBodyFrame(mContent, this);
|
||||
}
|
||||
// Reflow the child and get its desired size. Let the child's height be
|
||||
// whatever it wants
|
||||
nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, aReflowState,
|
||||
nsSize(aReflowState.maxSize.width, NS_UNCONSTRAINEDSIZE));
|
||||
|
||||
// Allow the child frame to be as wide as our max width (minus a
|
||||
// scroll bar width), and as high as it wants to be.
|
||||
nsSize maxSize;
|
||||
nsIDeviceContext* dc = aPresContext.GetDeviceContext();
|
||||
float sbWidth, sbHeight;
|
||||
dc->GetScrollBarDimensions(sbWidth, sbHeight);
|
||||
maxSize.width = aReflowState.maxSize.width - NSToCoordRound(sbWidth);
|
||||
NS_RELEASE(dc);
|
||||
maxSize.height = NS_UNCONSTRAINEDSIZE;
|
||||
ReflowChild(mFirstChild, aPresContext, aDesiredSize, kidReflowState, aStatus);
|
||||
NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
|
||||
|
||||
// Reflow the child
|
||||
nsHTMLReflowMetrics kidMetrics(aDesiredSize.maxElementSize);
|
||||
// Place and size the child
|
||||
nsRect rect(0, 0, aDesiredSize.width, aDesiredSize.height);
|
||||
mFirstChild->SetRect(rect);
|
||||
|
||||
nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, aReflowState, maxSize);
|
||||
nsIHTMLReflow* htmlReflow;
|
||||
|
||||
if (NS_OK == mFirstChild->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) {
|
||||
htmlReflow->WillReflow(aPresContext);
|
||||
ReflowChild(mFirstChild, aPresContext, kidMetrics, kidReflowState, aStatus);
|
||||
NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
|
||||
|
||||
// Place and size the child
|
||||
nsRect rect(0, 0, kidMetrics.width, kidMetrics.height);
|
||||
mFirstChild->SetRect(rect);
|
||||
htmlReflow->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED);
|
||||
// The scroll view frame either shrink wraps around it's single
|
||||
// child OR uses the style width/height.
|
||||
if (aReflowState.HaveConstrainedWidth()) {
|
||||
aDesiredSize.width = aReflowState.minWidth;
|
||||
}
|
||||
|
||||
// Determine our size. Our width is our maxWidth and our height is
|
||||
// either our child's height or our maxHeight if our maxHeight is
|
||||
// constrained.
|
||||
aDesiredSize.width = aReflowState.maxSize.width;
|
||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.maxSize.height) {
|
||||
aDesiredSize.height = kidMetrics.height;
|
||||
}
|
||||
else {
|
||||
aDesiredSize.height = aReflowState.maxSize.height;
|
||||
if (aReflowState.HaveConstrainedHeight()) {
|
||||
aDesiredSize.height = aReflowState.minHeight;
|
||||
}
|
||||
aDesiredSize.ascent = aDesiredSize.height;
|
||||
aDesiredSize.descent = 0;
|
||||
|
||||
NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
|
||||
("exit nsScrollInnerFrame::Reflow: status=%d width=%d height=%d",
|
||||
("exit nsScrollingViewFrame::Reflow: status=%d width=%d height=%d",
|
||||
aStatus, aDesiredSize.width, aDesiredSize.height));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScrollInnerFrame::ListTag(FILE* out) const
|
||||
nsScrollingViewFrame::Paint(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect)
|
||||
{
|
||||
fputs("*scrollinnerframe<", out);
|
||||
// Paint our children
|
||||
return nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect);
|
||||
}
|
||||
|
||||
PRIntn
|
||||
nsScrollingViewFrame::GetSkipSides() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScrollingViewFrame::ListTag(FILE* out) const
|
||||
{
|
||||
fputs("*scrollingviewframe<", out);
|
||||
nsIAtom* atom;
|
||||
mContent->GetTag(atom);
|
||||
if (nsnull != atom) {
|
||||
@ -435,108 +325,160 @@ nsScrollInnerFrame::ListTag(FILE* out) const
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class nsScrollOuterFrame : public nsHTMLContainerFrame {
|
||||
/**
|
||||
* The scroll frame basically acts as a border frame. It leaves room for and
|
||||
* renders the border. It creates a nsScrollingViewFrame which creates and
|
||||
* manages the scrollable view.
|
||||
*/
|
||||
class nsScrollFrame : public nsHTMLContainerFrame {
|
||||
public:
|
||||
nsScrollOuterFrame(nsIContent* aContent, nsIFrame* aParent);
|
||||
nsScrollFrame(nsIContent* aContent, nsIFrame* aParent);
|
||||
|
||||
NS_IMETHOD Init(nsIPresContext& aPresContext, nsIFrame* aChildList);
|
||||
|
||||
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
NS_IMETHOD Paint(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect);
|
||||
|
||||
NS_IMETHOD ListTag(FILE* out = stdout) const;
|
||||
|
||||
protected:
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
};
|
||||
|
||||
nsScrollOuterFrame::nsScrollOuterFrame(nsIContent* aContent, nsIFrame* aParent)
|
||||
nsScrollFrame::nsScrollFrame(nsIContent* aContent, nsIFrame* aParent)
|
||||
: nsHTMLContainerFrame(aContent, aParent)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScrollFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aChildList, "no child frame");
|
||||
|
||||
// Create a scrolling view frame
|
||||
mFirstChild = new nsScrollingViewFrame(mContent, this);
|
||||
if (nsnull == mFirstChild) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
// Have it use our style context
|
||||
mFirstChild->SetStyleContext(&aPresContext, mStyleContext);
|
||||
|
||||
// Reset the child frame's geometric and content parent to be
|
||||
// the scrolling view frame
|
||||
#ifdef NS_DEBUG
|
||||
// Verify that there's only one child frame
|
||||
nsIFrame* nextSibling;
|
||||
aChildList->GetNextSibling(nextSibling);
|
||||
NS_ASSERTION(nsnull == nextSibling, "expected only one child");
|
||||
#endif
|
||||
aChildList->SetGeometricParent(mFirstChild);
|
||||
aChildList->SetContentParent(mFirstChild);
|
||||
|
||||
// Init the scrollable view frame passing it the child list
|
||||
return mFirstChild->Init(aPresContext, aChildList);
|
||||
}
|
||||
|
||||
//XXX incremental reflow pass through
|
||||
NS_IMETHODIMP
|
||||
nsScrollOuterFrame::Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
nsScrollFrame::Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
|
||||
("enter nsScrollOuterFrame::Reflow: maxSize=%d,%d",
|
||||
("enter nsScrollFrame::Reflow: maxSize=%d,%d",
|
||||
aReflowState.maxSize.width,
|
||||
aReflowState.maxSize.height));
|
||||
|
||||
if (nsnull == mFirstChild) {
|
||||
mFirstChild = new nsScrollInnerFrame(mContent, this);
|
||||
}
|
||||
|
||||
// We handle the border only
|
||||
const nsStyleSpacing* spacing = (const nsStyleSpacing*)
|
||||
mStyleContext->GetStyleData(eStyleStruct_Spacing);
|
||||
nsMargin borderPadding;
|
||||
spacing->CalcBorderPaddingFor(this, borderPadding);
|
||||
nscoord lr = borderPadding.left + borderPadding.right;
|
||||
nscoord tb = borderPadding.top + borderPadding.bottom;
|
||||
nsMargin border;
|
||||
spacing->CalcBorderFor(this, border);
|
||||
nscoord lr = border.left + border.right;
|
||||
nscoord tb = border.top + border.bottom;
|
||||
|
||||
// Get style size and determine how much area is available for the
|
||||
// child (the scroll inner frame) to layout into.
|
||||
nsSize maxSize;
|
||||
// Compute the scrolling view frame's max size taking into account our
|
||||
// borders
|
||||
nsSize kidMaxSize;
|
||||
if (aReflowState.HaveConstrainedWidth()) {
|
||||
maxSize.width = aReflowState.minWidth - lr;
|
||||
// This value reflects space for the content area only, so don't
|
||||
// subtract for borders...
|
||||
kidMaxSize.width = aReflowState.minWidth;
|
||||
}
|
||||
else {
|
||||
maxSize.width = aReflowState.maxSize.width;
|
||||
kidMaxSize.width = aReflowState.maxSize.width;
|
||||
if (NS_UNCONSTRAINEDSIZE != kidMaxSize.width) {
|
||||
kidMaxSize.width -= lr;
|
||||
}
|
||||
}
|
||||
if (aReflowState.HaveConstrainedHeight()) {
|
||||
maxSize.height = aReflowState.minHeight - tb;
|
||||
// This value reflects space for the content area only, so don't
|
||||
// subtract for borders...
|
||||
kidMaxSize.height = aReflowState.minHeight;
|
||||
}
|
||||
else {
|
||||
maxSize.height = NS_UNCONSTRAINEDSIZE;
|
||||
kidMaxSize.height = NS_UNCONSTRAINEDSIZE;
|
||||
if (NS_UNCONSTRAINEDSIZE != kidMaxSize.height) {
|
||||
kidMaxSize.height -= tb;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Reflow the child and get its desired size
|
||||
nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, aReflowState, maxSize);
|
||||
nsIHTMLReflow* htmlReflow;
|
||||
nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, aReflowState, kidMaxSize);
|
||||
|
||||
if (NS_OK == mFirstChild->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) {
|
||||
htmlReflow->WillReflow(aPresContext);
|
||||
ReflowChild(mFirstChild, aPresContext, aDesiredSize, kidReflowState, aStatus);
|
||||
NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
|
||||
ReflowChild(mFirstChild, aPresContext, aDesiredSize, kidReflowState, aStatus);
|
||||
NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
|
||||
|
||||
// Place and size the child
|
||||
nsRect rect(borderPadding.left, borderPadding.top,
|
||||
aDesiredSize.width, aDesiredSize.height);
|
||||
mFirstChild->SetRect(rect);
|
||||
htmlReflow->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED);
|
||||
}
|
||||
// Place and size the child
|
||||
nsRect rect(border.left, border.top, aDesiredSize.width, aDesiredSize.height);
|
||||
mFirstChild->SetRect(rect);
|
||||
|
||||
// The scroll outer frame either shrink wraps around it's single
|
||||
// child OR uses the style width/height.
|
||||
if (aReflowState.HaveConstrainedWidth()) {
|
||||
aDesiredSize.width = aReflowState.minWidth;
|
||||
}
|
||||
else {
|
||||
aDesiredSize.width += lr;
|
||||
}
|
||||
if (aReflowState.HaveConstrainedHeight()) {
|
||||
aDesiredSize.height = aReflowState.minHeight;
|
||||
}
|
||||
else {
|
||||
aDesiredSize.height += tb;
|
||||
}
|
||||
// Compute our desired size by adding in space for the borders
|
||||
aDesiredSize.width += lr;
|
||||
aDesiredSize.height += tb;
|
||||
aDesiredSize.ascent = aDesiredSize.height;
|
||||
aDesiredSize.descent = 0;
|
||||
|
||||
NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
|
||||
("exit nsScrollOuterFrame::Reflow: status=%d width=%d height=%d",
|
||||
("exit nsScrollFrame::Reflow: status=%d width=%d height=%d",
|
||||
aStatus, aDesiredSize.width, aDesiredSize.height));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScrollOuterFrame::ListTag(FILE* out) const
|
||||
nsScrollFrame::Paint(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect)
|
||||
{
|
||||
fputs("*scrollouterframe<", out);
|
||||
// Paint our border only (no background)
|
||||
const nsStyleSpacing* spacing =
|
||||
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
|
||||
|
||||
nsRect rect(0, 0, mRect.width, mRect.height);
|
||||
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
|
||||
aDirtyRect, rect, *spacing, 0);
|
||||
|
||||
// Paint our children
|
||||
return nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect);
|
||||
}
|
||||
|
||||
PRIntn
|
||||
nsScrollFrame::GetSkipSides() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScrollFrame::ListTag(FILE* out) const
|
||||
{
|
||||
fputs("*scrollframe<", out);
|
||||
nsIAtom* atom;
|
||||
mContent->GetTag(atom);
|
||||
if (nsnull != atom) {
|
||||
@ -549,27 +491,16 @@ nsScrollOuterFrame::ListTag(FILE* out) const
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRIntn
|
||||
nsScrollOuterFrame::GetSkipSides() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
NS_NewScrollFrame(nsIFrame** aInstancePtrResult,
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent)
|
||||
NS_NewScrollFrame(nsIContent* aContent,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIFrame*& aResult)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if (nsnull == aInstancePtrResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
nsIFrame* it = new nsScrollOuterFrame(aContent, aParent);
|
||||
if (nsnull == it) {
|
||||
aResult = new nsScrollFrame(aContent, aParentFrame);
|
||||
if (nsnull == aResult) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
*aInstancePtrResult = it;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1,27 +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.
|
||||
*/
|
||||
#ifndef nsScrollFrame_h___
|
||||
#define nsScrollFrame_h___
|
||||
|
||||
#include "nsHTMLContainerFrame.h"
|
||||
|
||||
extern nsresult NS_NewScrollFrame(nsIFrame** aInstancePtrResult,
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent);
|
||||
|
||||
#endif /* nsScrollFrame_h___ */
|
@ -325,6 +325,8 @@ protected:
|
||||
nsIFrame* aParentFrame,
|
||||
nsIFrame*& aFrame);
|
||||
|
||||
PRBool IsScrollable(nsIFrame* aFrame, const nsStyleDisplay* aDisplay);
|
||||
|
||||
protected:
|
||||
PRUint32 mInHeap : 1;
|
||||
PRUint32 mRefCnt : 31;
|
||||
@ -1351,6 +1353,28 @@ HTMLStyleSheetImpl::ConstructFrameByDisplayType(nsIPresContext* aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRBool
|
||||
HTMLStyleSheetImpl::IsScrollable(nsIFrame* aFrame,
|
||||
const nsStyleDisplay* aDisplay)
|
||||
{
|
||||
// If the overflow property is scroll then it's scrollable regardless
|
||||
// of whether the content overflows the block.
|
||||
// XXX This isn't correct. Only do this if the height is not allowed to
|
||||
// grow to accomodate its child frames...
|
||||
if (NS_STYLE_OVERFLOW_SCROLL == aDisplay->mOverflow) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ((NS_STYLE_OVERFLOW_SCROLL == aDisplay->mOverflow) ||
|
||||
// If the element has a fixed height (it isn't auto) and an overflow
|
||||
// property of scroll or auto, then it's potentially scrollable.
|
||||
// XXX Deal with width considerations, too
|
||||
(NS_STYLE_OVERFLOW_AUTO == aDisplay->mOverflow)) {
|
||||
#endif
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLStyleSheetImpl::ConstructFrame(nsIPresContext* aPresContext,
|
||||
nsIContent* aContent,
|
||||
@ -1406,20 +1430,32 @@ HTMLStyleSheetImpl::ConstructFrame(nsIPresContext* aPresContext,
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
// If the frame is a block-level frame and it has a fixed height and overflow
|
||||
// property of scroll, then wrap it in a scroll frame.
|
||||
// XXX Deal with replaced elements and overflow of auto and width, too
|
||||
nsIFrame* kidFrame = nsnull;
|
||||
nsresult rv;
|
||||
if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) ||
|
||||
(NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) {
|
||||
rv = NS_NewScrollFrame(&kidFrame, aKid, aParentFrame);
|
||||
if (NS_OK == rv) {
|
||||
kidFrame->SetStyleContext(aPresContext, kidSC);
|
||||
// If the frame is a block-level frame and is scrollable then wrap it
|
||||
// in a scroll frame.
|
||||
// XXX Applies to replaced elements, too, but how to tell if the element
|
||||
// is replaced?
|
||||
if (nsnull != aFrameSubTree) {
|
||||
if (display->IsBlockLevel() && IsScrollable(aFrameSubTree, display)) {
|
||||
nsIFrame* scrollFrame;
|
||||
|
||||
if NS_SUCCEEDED(NS_NewScrollFrame(aContent, aParentFrame, scrollFrame)) {
|
||||
// The scroll frame gets the original style context, and the scrolled
|
||||
// frame gets a pseudo style context.
|
||||
// XXX Is this the best way to do this?
|
||||
scrollFrame->SetStyleContext(aPresContext, styleContext);
|
||||
|
||||
nsIStyleContext* pseudoStyle;
|
||||
pseudoStyle = aPresContext->ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo,
|
||||
scrollFrame);
|
||||
aFrameSubTree->SetStyleContext(aPresContext, pseudoStyle);
|
||||
NS_RELEASE(pseudoStyle);
|
||||
|
||||
// Initialize the scroll frame
|
||||
scrollFrame->Init(*aPresContext, aFrameSubTree);
|
||||
aFrameSubTree = scrollFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
NS_RELEASE(styleContext);
|
||||
|
@ -325,6 +325,8 @@ protected:
|
||||
nsIFrame* aParentFrame,
|
||||
nsIFrame*& aFrame);
|
||||
|
||||
PRBool IsScrollable(nsIFrame* aFrame, const nsStyleDisplay* aDisplay);
|
||||
|
||||
protected:
|
||||
PRUint32 mInHeap : 1;
|
||||
PRUint32 mRefCnt : 31;
|
||||
@ -1351,6 +1353,28 @@ HTMLStyleSheetImpl::ConstructFrameByDisplayType(nsIPresContext* aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRBool
|
||||
HTMLStyleSheetImpl::IsScrollable(nsIFrame* aFrame,
|
||||
const nsStyleDisplay* aDisplay)
|
||||
{
|
||||
// If the overflow property is scroll then it's scrollable regardless
|
||||
// of whether the content overflows the block.
|
||||
// XXX This isn't correct. Only do this if the height is not allowed to
|
||||
// grow to accomodate its child frames...
|
||||
if (NS_STYLE_OVERFLOW_SCROLL == aDisplay->mOverflow) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ((NS_STYLE_OVERFLOW_SCROLL == aDisplay->mOverflow) ||
|
||||
// If the element has a fixed height (it isn't auto) and an overflow
|
||||
// property of scroll or auto, then it's potentially scrollable.
|
||||
// XXX Deal with width considerations, too
|
||||
(NS_STYLE_OVERFLOW_AUTO == aDisplay->mOverflow)) {
|
||||
#endif
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLStyleSheetImpl::ConstructFrame(nsIPresContext* aPresContext,
|
||||
nsIContent* aContent,
|
||||
@ -1406,20 +1430,32 @@ HTMLStyleSheetImpl::ConstructFrame(nsIPresContext* aPresContext,
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
// If the frame is a block-level frame and it has a fixed height and overflow
|
||||
// property of scroll, then wrap it in a scroll frame.
|
||||
// XXX Deal with replaced elements and overflow of auto and width, too
|
||||
nsIFrame* kidFrame = nsnull;
|
||||
nsresult rv;
|
||||
if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) ||
|
||||
(NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) {
|
||||
rv = NS_NewScrollFrame(&kidFrame, aKid, aParentFrame);
|
||||
if (NS_OK == rv) {
|
||||
kidFrame->SetStyleContext(aPresContext, kidSC);
|
||||
// If the frame is a block-level frame and is scrollable then wrap it
|
||||
// in a scroll frame.
|
||||
// XXX Applies to replaced elements, too, but how to tell if the element
|
||||
// is replaced?
|
||||
if (nsnull != aFrameSubTree) {
|
||||
if (display->IsBlockLevel() && IsScrollable(aFrameSubTree, display)) {
|
||||
nsIFrame* scrollFrame;
|
||||
|
||||
if NS_SUCCEEDED(NS_NewScrollFrame(aContent, aParentFrame, scrollFrame)) {
|
||||
// The scroll frame gets the original style context, and the scrolled
|
||||
// frame gets a pseudo style context.
|
||||
// XXX Is this the best way to do this?
|
||||
scrollFrame->SetStyleContext(aPresContext, styleContext);
|
||||
|
||||
nsIStyleContext* pseudoStyle;
|
||||
pseudoStyle = aPresContext->ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo,
|
||||
scrollFrame);
|
||||
aFrameSubTree->SetStyleContext(aPresContext, pseudoStyle);
|
||||
NS_RELEASE(pseudoStyle);
|
||||
|
||||
// Initialize the scroll frame
|
||||
scrollFrame->Init(*aPresContext, aFrameSubTree);
|
||||
aFrameSubTree = scrollFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
NS_RELEASE(styleContext);
|
||||
|
Loading…
x
Reference in New Issue
Block a user