mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-06 00:31:27 +00:00
Changed to table incremental reflow
This commit is contained in:
parent
b5adb52af2
commit
f901be20dc
@ -59,66 +59,6 @@ public:
|
||||
static const nsIID& GetIID() { static nsIID iid = NS_IREFLOWCOMMAND_IID; return iid; }
|
||||
|
||||
enum ReflowType {
|
||||
/**
|
||||
* Reflow command generated by the style system in response to a
|
||||
* ContentAppended content notification. The target frame of the reflow
|
||||
* command is the container frame itself. The "child frame" is a linked
|
||||
* list of newly created child frames.
|
||||
*
|
||||
* The target frame should insert the new frames into the specified child
|
||||
* list, and then reflow the child frames using an eReflowReason_Initial
|
||||
* reflow reason.
|
||||
*
|
||||
* ContentInserted content notifications also generate a FrameAppended reflow
|
||||
* command if the container frame has no existing child frames.
|
||||
*
|
||||
* @see #GetTarget()
|
||||
* @see #GetChildFrame()
|
||||
* @see #GetChildListName()
|
||||
*/
|
||||
FrameAppended = 0,
|
||||
|
||||
/**
|
||||
* Reflow command generated by the style system in response to a
|
||||
* ContentInserted content notification. The target frame of the reflow
|
||||
* command is the container frame itself. The "child frame" is a linked
|
||||
* list of newly created child frames. The "previous sibling" frame is the
|
||||
* existing frame immediately preceding where the first of the newly created
|
||||
* frames should be inserted. If the newly created frames should be the
|
||||
* target frame's first child frames then "previous sibling" will be nsnull.
|
||||
*
|
||||
* The target frame should insert the new frames immediately after the previous
|
||||
* sibling frame, and then reflow the new frames using an eReflowReason_Initial
|
||||
* reflow reason. Use GetChildListName() to get the name of the child list to
|
||||
* which you should insert the new frames.
|
||||
*
|
||||
* The target frame is determined as follows:
|
||||
* - find the previous existing frame and use its content parent
|
||||
* - if there is no previous frame then find the frame that follows and use
|
||||
* its content parent
|
||||
*
|
||||
* @see #GetTarget()
|
||||
* @see #GetChildFrame()
|
||||
* @see #GetPrevSiblingFrame()
|
||||
* @see #GetChildListName()
|
||||
*/
|
||||
FrameInserted,
|
||||
|
||||
/**
|
||||
* Reflow command generated by the style system in response to a
|
||||
* ContentRemoved content notification. The "child frame" is the frame
|
||||
* associated with the content that has been removed. The target frame
|
||||
* is the content parent of the "child frame".
|
||||
*
|
||||
* Use GetChildListName() to get the name of the child list associated with
|
||||
* the frame to be deleted
|
||||
*
|
||||
* @see #GetTarget()
|
||||
* @see #GetChildFrame()
|
||||
* @see #GetChildListName()
|
||||
*/
|
||||
FrameRemoved,
|
||||
|
||||
// This reflow command is used when a leaf node's content changes
|
||||
// (e.g. some text in a text run, an image's source, etc.). The
|
||||
// target of the reflow command is the frame that changed (see
|
||||
@ -132,8 +72,6 @@ public:
|
||||
// reflow command is the frame that changed style.
|
||||
StyleChanged,
|
||||
|
||||
// XXX Everything below is speculative...
|
||||
|
||||
// When an incremental reflow operation affects a next-in-flow,
|
||||
// these commands are used to get the next-in-flow to update
|
||||
// itself.
|
||||
|
@ -49,7 +49,7 @@ Components {
|
||||
margin-left: .5in;
|
||||
border: dotted 1px black;
|
||||
}
|
||||
*[xml:link]:hover {
|
||||
:link:hover {
|
||||
background-color: blue;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
|
@ -1189,11 +1189,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
||||
printf(": reflow=incremental type=%d\n", type);
|
||||
#endif
|
||||
switch (type) {
|
||||
case nsIReflowCommand::FrameAppended:
|
||||
case nsIReflowCommand::FrameInserted:
|
||||
case nsIReflowCommand::FrameRemoved:
|
||||
NS_NOTREACHED("invalid reflow command");
|
||||
break;
|
||||
case nsIReflowCommand::StyleChanged:
|
||||
rv = PrepareStyleChangedReflow(state);
|
||||
break;
|
||||
|
@ -1189,11 +1189,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
||||
printf(": reflow=incremental type=%d\n", type);
|
||||
#endif
|
||||
switch (type) {
|
||||
case nsIReflowCommand::FrameAppended:
|
||||
case nsIReflowCommand::FrameInserted:
|
||||
case nsIReflowCommand::FrameRemoved:
|
||||
NS_NOTREACHED("invalid reflow command");
|
||||
break;
|
||||
case nsIReflowCommand::StyleChanged:
|
||||
rv = PrepareStyleChangedReflow(state);
|
||||
break;
|
||||
|
@ -1189,11 +1189,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
||||
printf(": reflow=incremental type=%d\n", type);
|
||||
#endif
|
||||
switch (type) {
|
||||
case nsIReflowCommand::FrameAppended:
|
||||
case nsIReflowCommand::FrameInserted:
|
||||
case nsIReflowCommand::FrameRemoved:
|
||||
NS_NOTREACHED("invalid reflow command");
|
||||
break;
|
||||
case nsIReflowCommand::StyleChanged:
|
||||
rv = PrepareStyleChangedReflow(state);
|
||||
break;
|
||||
|
@ -604,36 +604,6 @@ nsContainerFrame::MoveOverflowToChildList()
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsContainerFrame::AddFrame(const nsHTMLReflowState& aReflowState,
|
||||
nsIFrame * aAddedFrame)
|
||||
{
|
||||
nsresult rv=NS_OK;
|
||||
nsIReflowCommand::ReflowType type;
|
||||
aReflowState.reflowCommand->GetType(type);
|
||||
|
||||
// we have a generic frame that gets inserted but doesn't effect
|
||||
// reflow hook it up then ignore it
|
||||
if (nsIReflowCommand::FrameAppended == type) {
|
||||
// Append aAddedFrame to the list of frames
|
||||
mFrames.AppendFrame(nsnull, aAddedFrame);
|
||||
}
|
||||
else if (nsIReflowCommand::FrameInserted == type) {
|
||||
// Insert aAddedFrame into the list of frames
|
||||
nsIFrame *prevSibling=nsnull;
|
||||
rv = aReflowState.reflowCommand->GetPrevSiblingFrame(prevSibling);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mFrames.InsertFrame(nsnull, prevSibling, aAddedFrame);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERTION(PR_FALSE, "bad reflow type");
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Debugging
|
||||
|
||||
|
@ -122,11 +122,6 @@ protected:
|
||||
*/
|
||||
void PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling);
|
||||
|
||||
/**
|
||||
*/
|
||||
nsresult AddFrame(const nsHTMLReflowState& aReflowState,
|
||||
nsIFrame * aAddedFrame);
|
||||
|
||||
nsFrameList mFrames;
|
||||
nsFrameList mOverflowFrames;
|
||||
};
|
||||
|
@ -264,29 +264,8 @@ nsFrame::AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
#if 0
|
||||
NS_PRECONDITION(PR_FALSE, "not a container");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
#else
|
||||
#ifdef NS_DEBUG
|
||||
nsFrameList tmp(aFrameList);
|
||||
tmp.VerifyParent(this);
|
||||
#endif
|
||||
// XXX temporary code until frame containers stop using the old
|
||||
// reflow command api's
|
||||
nsIReflowCommand* reflowCmd = nsnull;
|
||||
nsresult rv;
|
||||
rv = NS_NewHTMLReflowCommand(&reflowCmd, this,
|
||||
nsIReflowCommand::FrameAppended,
|
||||
aFrameList);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (nsnull != aListName) {
|
||||
reflowCmd->SetChildListName(aListName);
|
||||
}
|
||||
aPresShell.AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
return rv;
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -296,37 +275,8 @@ nsFrame::InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
#if 0
|
||||
NS_PRECONDITION(PR_FALSE, "not a container");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
#else
|
||||
#ifdef NS_DEBUG
|
||||
nsFrameList tmp(aFrameList);
|
||||
tmp.VerifyParent(this);
|
||||
#endif
|
||||
|
||||
// XXX temporary code until frame containers stop using the old
|
||||
// reflow command api's
|
||||
|
||||
// By default, the reflow command is aimed at the first-in-flow. We
|
||||
// map that to the flow block that contains aPrevFrame for
|
||||
// compatability.
|
||||
nsIFrame* target = this;
|
||||
if (nsnull != aPrevFrame) {
|
||||
aPrevFrame->GetParent(&target);
|
||||
}
|
||||
|
||||
nsIReflowCommand* reflowCmd = nsnull;
|
||||
nsresult rv;
|
||||
rv = NS_NewHTMLReflowCommand(&reflowCmd, target, aFrameList, aPrevFrame);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (nsnull != aListName) {
|
||||
reflowCmd->SetChildListName(aListName);
|
||||
}
|
||||
aPresShell.AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
return rv;
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -335,40 +285,8 @@ nsFrame::RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame)
|
||||
{
|
||||
#if 0
|
||||
NS_PRECONDITION(PR_FALSE, "not a container");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
#else
|
||||
#ifdef NS_DEBUG
|
||||
nsIFrame* parent;
|
||||
aOldFrame->GetParent(&parent);
|
||||
NS_ASSERTION(parent == this, "bad child parent");
|
||||
#endif
|
||||
|
||||
// XXX temporary code until frame containers stop using the old
|
||||
// reflow command api's
|
||||
|
||||
// By default, the reflow command is aimed at the first-in-flow. We
|
||||
// map that to the flow block that contains aPrevFrame for
|
||||
// compatability.
|
||||
nsIFrame* target = this;
|
||||
if (nsnull != aOldFrame) {
|
||||
aOldFrame->GetParent(&target);
|
||||
}
|
||||
|
||||
nsIReflowCommand* reflowCmd = nsnull;
|
||||
nsresult rv;
|
||||
rv = NS_NewHTMLReflowCommand(&reflowCmd, target,
|
||||
nsIReflowCommand::FrameRemoved,
|
||||
aOldFrame);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (nsnull != aListName) {
|
||||
reflowCmd->SetChildListName(aListName);
|
||||
}
|
||||
aPresShell.AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
return rv;
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -378,6 +296,7 @@ nsFrame::ReplaceFrame(nsIPresContext& aPresContext,
|
||||
nsIFrame* aOldFrame,
|
||||
nsIFrame* aNewFrame)
|
||||
{
|
||||
NS_PRECONDITION(PR_FALSE, "not a container");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
@ -1060,6 +979,40 @@ nsFrame::DidReflow(nsIPresContext& aPresContext,
|
||||
mView->GetViewManager(vm);
|
||||
vm->ResizeView(mView, mRect.width, mRect.height);
|
||||
vm->MoveViewTo(mView, origin.x, origin.y);
|
||||
|
||||
// Clip applies to block-level and replaced elements with overflow
|
||||
// set to other than 'visible'
|
||||
const nsStyleDisplay* display =
|
||||
(const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display);
|
||||
if (display->IsBlockLevel()) {
|
||||
if (display->mOverflow == NS_STYLE_OVERFLOW_HIDDEN) {
|
||||
nscoord left, top, right, bottom;
|
||||
|
||||
// Start with the 'auto' values and then factor in user
|
||||
// specified values
|
||||
left = top = 0;
|
||||
right = mRect.width;
|
||||
bottom = mRect.height;
|
||||
|
||||
if (0 == (NS_STYLE_CLIP_TOP_AUTO & display->mClipFlags)) {
|
||||
top += display->mClip.top;
|
||||
}
|
||||
if (0 == (NS_STYLE_CLIP_RIGHT_AUTO & display->mClipFlags)) {
|
||||
right -= display->mClip.right;
|
||||
}
|
||||
if (0 == (NS_STYLE_CLIP_BOTTOM_AUTO & display->mClipFlags)) {
|
||||
bottom -= display->mClip.bottom;
|
||||
}
|
||||
if (0 == (NS_STYLE_CLIP_LEFT_AUTO & display->mClipFlags)) {
|
||||
left += display->mClip.left;
|
||||
}
|
||||
mView->SetClip(left, top, right, bottom);
|
||||
|
||||
} else {
|
||||
// Make sure no clip is set
|
||||
mView->SetClip(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
NS_RELEASE(vm);
|
||||
}
|
||||
}
|
||||
|
@ -357,11 +357,4 @@ NS_NewHTMLReflowCommand(nsIReflowCommand** aInstancePtrResult,
|
||||
nsIFrame* aChildFrame = nsnull,
|
||||
nsIAtom* aAttribute = nsnull);
|
||||
|
||||
/** Create a new HTML 'FrameInserted' reflow command */
|
||||
extern nsresult
|
||||
NS_NewHTMLReflowCommand(nsIReflowCommand** aInstancePtrResult,
|
||||
nsIFrame* aTargetFrame,
|
||||
nsIFrame* aChildFrame,
|
||||
nsIFrame* aPrevSiblingFrame);
|
||||
|
||||
#endif /* nsHTMLParts_h___ */
|
||||
|
@ -48,25 +48,6 @@ NS_NewHTMLReflowCommand(nsIReflowCommand** aInstancePtrResult,
|
||||
return cmd->QueryInterface(kIReflowCommandIID, (void**)aInstancePtrResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewHTMLReflowCommand(nsIReflowCommand** aInstancePtrResult,
|
||||
nsIFrame* aTargetFrame,
|
||||
nsIFrame* aChildFrame,
|
||||
nsIFrame* aPrevSiblingFrame)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if (nsnull == aInstancePtrResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
nsHTMLReflowCommand* cmd = new nsHTMLReflowCommand(aTargetFrame, aChildFrame,
|
||||
aPrevSiblingFrame);
|
||||
if (nsnull == cmd) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return cmd->QueryInterface(kIReflowCommandIID, (void**)aInstancePtrResult);
|
||||
}
|
||||
|
||||
// Construct a reflow command given a target frame, reflow command type,
|
||||
// and optional child frame
|
||||
nsHTMLReflowCommand::nsHTMLReflowCommand(nsIFrame* aTargetFrame,
|
||||
@ -84,16 +65,6 @@ nsHTMLReflowCommand::nsHTMLReflowCommand(nsIFrame* aTargetFrame,
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsHTMLReflowCommand::nsHTMLReflowCommand(nsIFrame* aTargetFrame,
|
||||
nsIFrame* aChildFrame,
|
||||
nsIFrame* aPrevSiblingFrame)
|
||||
: mType(FrameInserted), mTargetFrame(aTargetFrame), mChildFrame(aChildFrame),
|
||||
mPrevSiblingFrame(aPrevSiblingFrame), mAttribute(nsnull), mListName(nsnull)
|
||||
{
|
||||
NS_PRECONDITION(mTargetFrame != nsnull, "null target frame");
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsHTMLReflowCommand::~nsHTMLReflowCommand()
|
||||
{
|
||||
NS_IF_RELEASE(mAttribute);
|
||||
|
@ -38,15 +38,6 @@ public:
|
||||
nsIFrame* aChildFrame = nsnull,
|
||||
nsIAtom* aAttribute = nsnull);
|
||||
|
||||
/**
|
||||
* Construct an HTML reflow command of type FrameInserted, with target
|
||||
* frame aTargetFrame, and with the specified child and previous sibling
|
||||
* frames.
|
||||
*/
|
||||
nsHTMLReflowCommand(nsIFrame* aTargetFrame,
|
||||
nsIFrame* aChildFrame,
|
||||
nsIFrame* aPrevSiblingFrame);
|
||||
|
||||
virtual ~nsHTMLReflowCommand();
|
||||
|
||||
// nsISupports
|
||||
|
@ -1189,11 +1189,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
||||
printf(": reflow=incremental type=%d\n", type);
|
||||
#endif
|
||||
switch (type) {
|
||||
case nsIReflowCommand::FrameAppended:
|
||||
case nsIReflowCommand::FrameInserted:
|
||||
case nsIReflowCommand::FrameRemoved:
|
||||
NS_NOTREACHED("invalid reflow command");
|
||||
break;
|
||||
case nsIReflowCommand::StyleChanged:
|
||||
rv = PrepareStyleChangedReflow(state);
|
||||
break;
|
||||
|
@ -1189,11 +1189,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
||||
printf(": reflow=incremental type=%d\n", type);
|
||||
#endif
|
||||
switch (type) {
|
||||
case nsIReflowCommand::FrameAppended:
|
||||
case nsIReflowCommand::FrameInserted:
|
||||
case nsIReflowCommand::FrameRemoved:
|
||||
NS_NOTREACHED("invalid reflow command");
|
||||
break;
|
||||
case nsIReflowCommand::StyleChanged:
|
||||
rv = PrepareStyleChangedReflow(state);
|
||||
break;
|
||||
|
@ -1189,11 +1189,6 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
||||
printf(": reflow=incremental type=%d\n", type);
|
||||
#endif
|
||||
switch (type) {
|
||||
case nsIReflowCommand::FrameAppended:
|
||||
case nsIReflowCommand::FrameInserted:
|
||||
case nsIReflowCommand::FrameRemoved:
|
||||
NS_NOTREACHED("invalid reflow command");
|
||||
break;
|
||||
case nsIReflowCommand::StyleChanged:
|
||||
rv = PrepareStyleChangedReflow(state);
|
||||
break;
|
||||
|
@ -604,36 +604,6 @@ nsContainerFrame::MoveOverflowToChildList()
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsContainerFrame::AddFrame(const nsHTMLReflowState& aReflowState,
|
||||
nsIFrame * aAddedFrame)
|
||||
{
|
||||
nsresult rv=NS_OK;
|
||||
nsIReflowCommand::ReflowType type;
|
||||
aReflowState.reflowCommand->GetType(type);
|
||||
|
||||
// we have a generic frame that gets inserted but doesn't effect
|
||||
// reflow hook it up then ignore it
|
||||
if (nsIReflowCommand::FrameAppended == type) {
|
||||
// Append aAddedFrame to the list of frames
|
||||
mFrames.AppendFrame(nsnull, aAddedFrame);
|
||||
}
|
||||
else if (nsIReflowCommand::FrameInserted == type) {
|
||||
// Insert aAddedFrame into the list of frames
|
||||
nsIFrame *prevSibling=nsnull;
|
||||
rv = aReflowState.reflowCommand->GetPrevSiblingFrame(prevSibling);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mFrames.InsertFrame(nsnull, prevSibling, aAddedFrame);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERTION(PR_FALSE, "bad reflow type");
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Debugging
|
||||
|
||||
|
@ -122,11 +122,6 @@ protected:
|
||||
*/
|
||||
void PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling);
|
||||
|
||||
/**
|
||||
*/
|
||||
nsresult AddFrame(const nsHTMLReflowState& aReflowState,
|
||||
nsIFrame * aAddedFrame);
|
||||
|
||||
nsFrameList mFrames;
|
||||
nsFrameList mOverflowFrames;
|
||||
};
|
||||
|
@ -25,11 +25,14 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Structure that represents a node in the DST
|
||||
|
||||
// Constructor
|
||||
inline nsDST::Node::Node(void* aKey, void* aValue)
|
||||
: mKey(aKey), mValue(aValue), mLeft(0), mRight(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Helper function that returns TRUE if the node is a leaf (i.e., no left or
|
||||
// right child), and FALSE otherwise
|
||||
inline int nsDST::Node::IsLeaf() const
|
||||
{
|
||||
return !mLeft && !mRight;
|
||||
@ -47,18 +50,23 @@ inline void* nsDST::Node::operator new(size_t aSize, NodeArena& aArena)
|
||||
|
||||
#define NS_DST_ARENA_BLOCK_SIZE 1024
|
||||
|
||||
// Constructor
|
||||
nsDST::NodeArena::NodeArena()
|
||||
: mFreeList(0)
|
||||
{
|
||||
PL_INIT_ARENA_POOL(&mPool, "DSTNodeArena", NS_DST_ARENA_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
nsDST::NodeArena::~NodeArena()
|
||||
{
|
||||
// Free the arena in the pool and finish using it
|
||||
PL_FinishArenaPool(&mPool);
|
||||
}
|
||||
|
||||
// Called by the nsDST::Node's overloaded placement operator when allocating
|
||||
// a new node. First checks the free list. If the free list is empty, then
|
||||
// it allocates memory from the arena
|
||||
void*
|
||||
nsDST::NodeArena::AllocNode(size_t aSize)
|
||||
{
|
||||
@ -74,6 +82,8 @@ nsDST::NodeArena::AllocNode(size_t aSize)
|
||||
return p;
|
||||
}
|
||||
|
||||
// Called by the DST's DestroyNode() function. Adds the node to the head
|
||||
// of the free list where it can be reused by AllocateNode()
|
||||
void
|
||||
nsDST::NodeArena::FreeNode(void* p)
|
||||
{
|
||||
@ -85,26 +95,33 @@ nsDST::NodeArena::FreeNode(void* p)
|
||||
mFreeList = (Node*)p;
|
||||
}
|
||||
|
||||
// Called by the DST's Clear() function when we want to free the memory
|
||||
// in the arena pool, but continue using the arena
|
||||
void
|
||||
nsDST::NodeArena::FreeArenaPool()
|
||||
{
|
||||
// Free the arena in the pool, but continue using it
|
||||
PL_FreeArenaPool(&mPool);
|
||||
|
||||
// Clear the free list
|
||||
mFreeList = 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Digital search tree for doing a radix-search of pointer-based keys
|
||||
|
||||
// Constructor
|
||||
nsDST::nsDST(PtrBits aLevelZeroBit)
|
||||
: mRoot(0), mLevelZeroBit(aLevelZeroBit)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
nsDST::~nsDST()
|
||||
{
|
||||
}
|
||||
|
||||
// Removes all nodes from the tree
|
||||
void
|
||||
nsDST::Clear()
|
||||
{
|
||||
@ -112,6 +129,9 @@ nsDST::Clear()
|
||||
mRoot = 0;
|
||||
}
|
||||
|
||||
// Adds a new key to the tree. If the specified key is already in the
|
||||
// tree, then the existing value is replaced by the new value. Returns
|
||||
// the old value, or NULL if this is a new key
|
||||
void*
|
||||
nsDST::Insert(void* aKey, void* aValue)
|
||||
{
|
||||
@ -160,6 +180,8 @@ keepLooking:
|
||||
}
|
||||
}
|
||||
|
||||
// Called by Remove() to destroy a node. Explicitly calls the destructor
|
||||
// and then asks the memory arena to free the memory
|
||||
inline void
|
||||
nsDST::DestroyNode(Node* aNode)
|
||||
{
|
||||
@ -167,6 +189,8 @@ nsDST::DestroyNode(Node* aNode)
|
||||
mArena.FreeNode(aNode); // free memory
|
||||
}
|
||||
|
||||
// Removes a key from the tree. Returns the current value, or NULL if
|
||||
// the key is not in the tree
|
||||
void*
|
||||
nsDST::Remove(void* aKey)
|
||||
{
|
||||
@ -209,6 +233,8 @@ nsDST::Remove(void* aKey)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Searches the tree for a node with the specified key. Return the value
|
||||
// or NULL if the key is not in the tree
|
||||
void*
|
||||
nsDST::Search(void* aKey) const
|
||||
{
|
||||
@ -226,7 +252,7 @@ nsDST::Search(void* aKey) const
|
||||
}
|
||||
|
||||
// Non-recursive search function. Returns a pointer to the pointer to the
|
||||
// node
|
||||
// node. Called by Search(), Insert(), and Remove()
|
||||
nsDST::Node**
|
||||
nsDST::SearchTree(void* aKey) const
|
||||
{
|
||||
@ -248,6 +274,7 @@ nsDST::SearchTree(void* aKey) const
|
||||
} else {
|
||||
result = &(*result)->mRight;
|
||||
}
|
||||
// Move to the next bit in the key
|
||||
bitMask <<= 1;
|
||||
}
|
||||
|
||||
@ -256,6 +283,9 @@ nsDST::SearchTree(void* aKey) const
|
||||
}
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
// Helper function used to verify the integrity of the tree. Does a
|
||||
// depth-first search of the tree looking for a node with the specified
|
||||
// key. Called by Search() if we don't find the key using the radix-search
|
||||
nsDST::Node*
|
||||
nsDST::DepthFirstSearch(Node* aNode, void* aKey) const
|
||||
{
|
||||
@ -274,7 +304,8 @@ nsDST::DepthFirstSearch(Node* aNode, void* aKey) const
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function that verifies the integrity of the tree
|
||||
// Helper function that verifies the integrity of the tree. Called
|
||||
// by Insert() and Remove()
|
||||
void
|
||||
nsDST::VerifyTree(Node* aNode, int aLevel, PtrBits aLevelKeyBits) const
|
||||
{
|
||||
|
@ -264,29 +264,8 @@ nsFrame::AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
#if 0
|
||||
NS_PRECONDITION(PR_FALSE, "not a container");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
#else
|
||||
#ifdef NS_DEBUG
|
||||
nsFrameList tmp(aFrameList);
|
||||
tmp.VerifyParent(this);
|
||||
#endif
|
||||
// XXX temporary code until frame containers stop using the old
|
||||
// reflow command api's
|
||||
nsIReflowCommand* reflowCmd = nsnull;
|
||||
nsresult rv;
|
||||
rv = NS_NewHTMLReflowCommand(&reflowCmd, this,
|
||||
nsIReflowCommand::FrameAppended,
|
||||
aFrameList);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (nsnull != aListName) {
|
||||
reflowCmd->SetChildListName(aListName);
|
||||
}
|
||||
aPresShell.AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
return rv;
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -296,37 +275,8 @@ nsFrame::InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
#if 0
|
||||
NS_PRECONDITION(PR_FALSE, "not a container");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
#else
|
||||
#ifdef NS_DEBUG
|
||||
nsFrameList tmp(aFrameList);
|
||||
tmp.VerifyParent(this);
|
||||
#endif
|
||||
|
||||
// XXX temporary code until frame containers stop using the old
|
||||
// reflow command api's
|
||||
|
||||
// By default, the reflow command is aimed at the first-in-flow. We
|
||||
// map that to the flow block that contains aPrevFrame for
|
||||
// compatability.
|
||||
nsIFrame* target = this;
|
||||
if (nsnull != aPrevFrame) {
|
||||
aPrevFrame->GetParent(&target);
|
||||
}
|
||||
|
||||
nsIReflowCommand* reflowCmd = nsnull;
|
||||
nsresult rv;
|
||||
rv = NS_NewHTMLReflowCommand(&reflowCmd, target, aFrameList, aPrevFrame);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (nsnull != aListName) {
|
||||
reflowCmd->SetChildListName(aListName);
|
||||
}
|
||||
aPresShell.AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
return rv;
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -335,40 +285,8 @@ nsFrame::RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame)
|
||||
{
|
||||
#if 0
|
||||
NS_PRECONDITION(PR_FALSE, "not a container");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
#else
|
||||
#ifdef NS_DEBUG
|
||||
nsIFrame* parent;
|
||||
aOldFrame->GetParent(&parent);
|
||||
NS_ASSERTION(parent == this, "bad child parent");
|
||||
#endif
|
||||
|
||||
// XXX temporary code until frame containers stop using the old
|
||||
// reflow command api's
|
||||
|
||||
// By default, the reflow command is aimed at the first-in-flow. We
|
||||
// map that to the flow block that contains aPrevFrame for
|
||||
// compatability.
|
||||
nsIFrame* target = this;
|
||||
if (nsnull != aOldFrame) {
|
||||
aOldFrame->GetParent(&target);
|
||||
}
|
||||
|
||||
nsIReflowCommand* reflowCmd = nsnull;
|
||||
nsresult rv;
|
||||
rv = NS_NewHTMLReflowCommand(&reflowCmd, target,
|
||||
nsIReflowCommand::FrameRemoved,
|
||||
aOldFrame);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (nsnull != aListName) {
|
||||
reflowCmd->SetChildListName(aListName);
|
||||
}
|
||||
aPresShell.AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
return rv;
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -378,6 +296,7 @@ nsFrame::ReplaceFrame(nsIPresContext& aPresContext,
|
||||
nsIFrame* aOldFrame,
|
||||
nsIFrame* aNewFrame)
|
||||
{
|
||||
NS_PRECONDITION(PR_FALSE, "not a container");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
@ -1060,6 +979,40 @@ nsFrame::DidReflow(nsIPresContext& aPresContext,
|
||||
mView->GetViewManager(vm);
|
||||
vm->ResizeView(mView, mRect.width, mRect.height);
|
||||
vm->MoveViewTo(mView, origin.x, origin.y);
|
||||
|
||||
// Clip applies to block-level and replaced elements with overflow
|
||||
// set to other than 'visible'
|
||||
const nsStyleDisplay* display =
|
||||
(const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display);
|
||||
if (display->IsBlockLevel()) {
|
||||
if (display->mOverflow == NS_STYLE_OVERFLOW_HIDDEN) {
|
||||
nscoord left, top, right, bottom;
|
||||
|
||||
// Start with the 'auto' values and then factor in user
|
||||
// specified values
|
||||
left = top = 0;
|
||||
right = mRect.width;
|
||||
bottom = mRect.height;
|
||||
|
||||
if (0 == (NS_STYLE_CLIP_TOP_AUTO & display->mClipFlags)) {
|
||||
top += display->mClip.top;
|
||||
}
|
||||
if (0 == (NS_STYLE_CLIP_RIGHT_AUTO & display->mClipFlags)) {
|
||||
right -= display->mClip.right;
|
||||
}
|
||||
if (0 == (NS_STYLE_CLIP_BOTTOM_AUTO & display->mClipFlags)) {
|
||||
bottom -= display->mClip.bottom;
|
||||
}
|
||||
if (0 == (NS_STYLE_CLIP_LEFT_AUTO & display->mClipFlags)) {
|
||||
left += display->mClip.left;
|
||||
}
|
||||
mView->SetClip(left, top, right, bottom);
|
||||
|
||||
} else {
|
||||
// Make sure no clip is set
|
||||
mView->SetClip(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
NS_RELEASE(vm);
|
||||
}
|
||||
}
|
||||
|
@ -357,11 +357,4 @@ NS_NewHTMLReflowCommand(nsIReflowCommand** aInstancePtrResult,
|
||||
nsIFrame* aChildFrame = nsnull,
|
||||
nsIAtom* aAttribute = nsnull);
|
||||
|
||||
/** Create a new HTML 'FrameInserted' reflow command */
|
||||
extern nsresult
|
||||
NS_NewHTMLReflowCommand(nsIReflowCommand** aInstancePtrResult,
|
||||
nsIFrame* aTargetFrame,
|
||||
nsIFrame* aChildFrame,
|
||||
nsIFrame* aPrevSiblingFrame);
|
||||
|
||||
#endif /* nsHTMLParts_h___ */
|
||||
|
@ -48,25 +48,6 @@ NS_NewHTMLReflowCommand(nsIReflowCommand** aInstancePtrResult,
|
||||
return cmd->QueryInterface(kIReflowCommandIID, (void**)aInstancePtrResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewHTMLReflowCommand(nsIReflowCommand** aInstancePtrResult,
|
||||
nsIFrame* aTargetFrame,
|
||||
nsIFrame* aChildFrame,
|
||||
nsIFrame* aPrevSiblingFrame)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if (nsnull == aInstancePtrResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
nsHTMLReflowCommand* cmd = new nsHTMLReflowCommand(aTargetFrame, aChildFrame,
|
||||
aPrevSiblingFrame);
|
||||
if (nsnull == cmd) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return cmd->QueryInterface(kIReflowCommandIID, (void**)aInstancePtrResult);
|
||||
}
|
||||
|
||||
// Construct a reflow command given a target frame, reflow command type,
|
||||
// and optional child frame
|
||||
nsHTMLReflowCommand::nsHTMLReflowCommand(nsIFrame* aTargetFrame,
|
||||
@ -84,16 +65,6 @@ nsHTMLReflowCommand::nsHTMLReflowCommand(nsIFrame* aTargetFrame,
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsHTMLReflowCommand::nsHTMLReflowCommand(nsIFrame* aTargetFrame,
|
||||
nsIFrame* aChildFrame,
|
||||
nsIFrame* aPrevSiblingFrame)
|
||||
: mType(FrameInserted), mTargetFrame(aTargetFrame), mChildFrame(aChildFrame),
|
||||
mPrevSiblingFrame(aPrevSiblingFrame), mAttribute(nsnull), mListName(nsnull)
|
||||
{
|
||||
NS_PRECONDITION(mTargetFrame != nsnull, "null target frame");
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsHTMLReflowCommand::~nsHTMLReflowCommand()
|
||||
{
|
||||
NS_IF_RELEASE(mAttribute);
|
||||
|
@ -38,15 +38,6 @@ public:
|
||||
nsIFrame* aChildFrame = nsnull,
|
||||
nsIAtom* aAttribute = nsnull);
|
||||
|
||||
/**
|
||||
* Construct an HTML reflow command of type FrameInserted, with target
|
||||
* frame aTargetFrame, and with the specified child and previous sibling
|
||||
* frames.
|
||||
*/
|
||||
nsHTMLReflowCommand(nsIFrame* aTargetFrame,
|
||||
nsIFrame* aChildFrame,
|
||||
nsIFrame* aPrevSiblingFrame);
|
||||
|
||||
virtual ~nsHTMLReflowCommand();
|
||||
|
||||
// nsISupports
|
||||
|
@ -722,21 +722,6 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext& aPresContext,
|
||||
aDesiredSize.ascent=aDesiredSize.height;
|
||||
aDesiredSize.descent=0;
|
||||
|
||||
// if we got this far with an incremental reflow, the reflow was targeted
|
||||
// at the cell's content. We should only have to redo pass1 for this cell
|
||||
// then rebalance columns. The pass1 is handled by the cell's parent row.
|
||||
// So here all we have to do is tell the table to rebalance.
|
||||
if (eReflowReason_Incremental == aReflowState.reason)
|
||||
{
|
||||
nsTableFrame* tableFrame=nsnull;
|
||||
rv = nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
|
||||
{
|
||||
tableFrame->InvalidateColumnWidths();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
//PostReflowCheck(result);
|
||||
#endif
|
||||
|
@ -2090,7 +2090,7 @@ nsTableFrame::GetSkipSides() const
|
||||
return skip;
|
||||
}
|
||||
|
||||
PRBool nsTableFrame::NeedsReflow(const nsHTMLReflowState& aReflowState, const nsSize& aMaxSize)
|
||||
PRBool nsTableFrame::NeedsReflow(const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
PRBool result = PR_TRUE;
|
||||
|
||||
@ -2115,49 +2115,60 @@ PRBool nsTableFrame::NeedsReflow(const nsHTMLReflowState& aReflowState, const ns
|
||||
//
|
||||
// Slides all the row groups following aKidFrame by the specified
|
||||
// amount
|
||||
//
|
||||
// XXX This is kind of klunky because the InnerTableReflowState::y
|
||||
// data member does not include the table's border/padding...
|
||||
nsresult nsTableFrame::AdjustSiblingsAfterReflow(nsIPresContext& aPresContext,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nscoord aDeltaY)
|
||||
{
|
||||
NS_PRECONDITION(NS_UNCONSTRAINEDSIZE == aReflowState.reflowState.availableHeight,
|
||||
"not in galley mode");
|
||||
nsIFrame* lastKidFrame = aKidFrame;
|
||||
"we're not in galley mode");
|
||||
|
||||
if (aDeltaY != 0) {
|
||||
// Move the frames that follow aKidFrame by aDeltaY
|
||||
// If it's the footer that was reflowed, then we don't need to adjust any of
|
||||
// the frames, because the footer is the bottom most frame
|
||||
if (aKidFrame != aReflowState.footerFrame) {
|
||||
nsIFrame* kidFrame;
|
||||
|
||||
aKidFrame->GetNextSibling(&kidFrame);
|
||||
while (nsnull != kidFrame) {
|
||||
nsPoint origin;
|
||||
nsIHTMLReflow* htmlReflow;
|
||||
nsRect kidRect;
|
||||
PRBool movedFooter = PR_FALSE;
|
||||
|
||||
// XXX We can't just slide the child if it has a next-in-flow
|
||||
kidFrame->GetOrigin(origin);
|
||||
origin.y += aDeltaY;
|
||||
|
||||
// XXX We need to send move notifications to the frame...
|
||||
if (NS_OK == kidFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) {
|
||||
htmlReflow->WillReflow(aPresContext);
|
||||
// Move the frames that follow aKidFrame by aDeltaY, and update the running
|
||||
// y-offset
|
||||
for (aKidFrame->GetNextSibling(&kidFrame); kidFrame; kidFrame->GetNextSibling(&kidFrame)) {
|
||||
// See if it's the footer we're moving
|
||||
if (kidFrame == aReflowState.footerFrame) {
|
||||
movedFooter = PR_TRUE;
|
||||
}
|
||||
|
||||
// Get the frame's bounding rect
|
||||
kidFrame->GetRect(kidRect);
|
||||
|
||||
// Adjust the running y-offset
|
||||
aReflowState.y += kidRect.height;
|
||||
|
||||
// Adjust the y-origin if its position actually changed
|
||||
if (aDeltaY != 0) {
|
||||
kidRect.y += aDeltaY;
|
||||
kidFrame->MoveTo(kidRect.x, kidRect.y);
|
||||
}
|
||||
}
|
||||
|
||||
// We also need to move the footer if there is one and we haven't already
|
||||
// moved it
|
||||
if (aReflowState.footerFrame && !movedFooter) {
|
||||
aReflowState.footerFrame->GetRect(kidRect);
|
||||
|
||||
// Adjust the running y-offset
|
||||
aReflowState.y += kidRect.height;
|
||||
|
||||
if (aDeltaY != 0) {
|
||||
kidRect.y += aDeltaY;
|
||||
aReflowState.footerFrame->MoveTo(kidRect.x, kidRect.y);
|
||||
}
|
||||
kidFrame->MoveTo(origin.x, origin.y);
|
||||
|
||||
// Get the next frame
|
||||
lastKidFrame = kidFrame;
|
||||
kidFrame->GetNextSibling(&kidFrame);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Get the last frame
|
||||
lastKidFrame = mFrames.LastChild();
|
||||
}
|
||||
|
||||
// Update our running y-offset to reflect the bottommost child
|
||||
nsRect rect;
|
||||
lastKidFrame->GetRect(rect);
|
||||
aReflowState.y = rect.YMost();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2253,7 +2264,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
|
||||
}
|
||||
|
||||
// NeedsReflow and IsFirstPassValid take into account reflow type = Initial_Reflow
|
||||
if (PR_TRUE==NeedsReflow(aReflowState, nsSize(aReflowState.availableWidth, aReflowState.availableHeight)))
|
||||
if (PR_TRUE==NeedsReflow(aReflowState))
|
||||
{
|
||||
PRBool needsRecalc=PR_FALSE;
|
||||
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: needs reflow\n");
|
||||
@ -2938,6 +2949,240 @@ NS_METHOD nsTableFrame::GetBorderPlusMarginPadding(nsMargin& aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Sets the starting column index for aColGroupFrame and the siblings frames that
|
||||
// follow
|
||||
void
|
||||
nsTableFrame::SetStartingColumnIndexFor(nsTableColGroupFrame* aColGroupFrame,
|
||||
PRInt32 aIndex)
|
||||
{
|
||||
while (aColGroupFrame) {
|
||||
aIndex += aColGroupFrame->SetStartColumnIndex(aIndex);
|
||||
aColGroupFrame->GetNextSibling((nsIFrame**)&aColGroupFrame);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the starting column index to use for the specified col group frame
|
||||
PRInt32
|
||||
nsTableFrame::CalculateStartingColumnIndexFor(nsTableColGroupFrame* aColGroupFrame)
|
||||
{
|
||||
PRInt32 index = 0;
|
||||
for (nsTableColGroupFrame* colGroupFrame = (nsTableColGroupFrame*)mColGroups.FirstChild();
|
||||
colGroupFrame && (colGroupFrame != aColGroupFrame);
|
||||
colGroupFrame->GetNextSibling((nsIFrame**)&colGroupFrame))
|
||||
{
|
||||
index += colGroupFrame->GetColumnCount();
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTableFrame::AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
PRInt32 startingColIndex = -1;
|
||||
|
||||
// Because we actually have two child lists, one for col group frames and one
|
||||
// for everything else, we need to look at each frame individually
|
||||
nsIFrame* f = aFrameList;
|
||||
while (f) {
|
||||
nsIFrame* next;
|
||||
|
||||
// Get the next frame and disconnect this frame from its sibling
|
||||
f->GetNextSibling(&next);
|
||||
f->SetNextSibling(nsnull);
|
||||
|
||||
// See what kind of frame we have
|
||||
const nsStyleDisplay *display;
|
||||
f->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
|
||||
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) {
|
||||
// Append the new col group frame
|
||||
mColGroups.AppendFrame(nsnull, f);
|
||||
|
||||
// Set its starting column index
|
||||
if (-1 == startingColIndex) {
|
||||
startingColIndex = CalculateStartingColumnIndexFor((nsTableColGroupFrame*)f);
|
||||
}
|
||||
((nsTableColGroupFrame*)f)->SetStartColumnIndex(startingColIndex);
|
||||
startingColIndex += ((nsTableColGroupFrame *)f)->GetColumnCount();
|
||||
|
||||
} else if (IsRowGroup(display->mDisplay)) {
|
||||
// Append the new row group frame
|
||||
mFrames.AppendFrame(nsnull, f);
|
||||
|
||||
// Add the content of the row group to the cell map
|
||||
DidAppendRowGroup((nsTableRowGroupFrame*)f);
|
||||
|
||||
} else {
|
||||
// Nothing special to do, just add the frame to our child list
|
||||
mFrames.AppendFrame(nsnull, f);
|
||||
}
|
||||
|
||||
// Move to the next frame
|
||||
f = next;
|
||||
}
|
||||
|
||||
// We'll need to do a pass-1 layout of all cells in all the rows of the
|
||||
// rowgroup
|
||||
InvalidateFirstPassCache();
|
||||
|
||||
// If we've added any columns, we need to rebuild the column cache.
|
||||
InvalidateColumnCache();
|
||||
|
||||
// Because the number of columns may have changed invalidate the column
|
||||
// cache. Note that this has the side effect of recomputing the column
|
||||
// widths, so we don't need to call InvalidateColumnWidths()
|
||||
InvalidateColumnWidths();
|
||||
|
||||
// Mark the table as dirty and generate a reflow command targeted at the
|
||||
// outer table frame
|
||||
nsIReflowCommand* reflowCmd;
|
||||
nsresult rv;
|
||||
|
||||
mState |= NS_FRAME_IS_DIRTY;
|
||||
rv = NS_NewHTMLReflowCommand(&reflowCmd, mParent, nsIReflowCommand::ReflowDirty);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Add the reflow command
|
||||
rv = aPresShell.AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTableFrame::InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
// Asssume there's only one frame being inserted. The problem is that
|
||||
// row group frames and col group frames go in separate child lists and
|
||||
// so if there's more than one this gets messy...
|
||||
// XXX The frame construction code should be separating out child frames
|
||||
// based on the type...
|
||||
nsIFrame* nextSibling;
|
||||
aFrameList->GetNextSibling(&nextSibling);
|
||||
NS_PRECONDITION(!nextSibling, "expected only one child frame");
|
||||
|
||||
// See what kind of frame we have
|
||||
const nsStyleDisplay *display=nsnull;
|
||||
aFrameList->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
|
||||
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) {
|
||||
// Insert the column group frame
|
||||
mColGroups.InsertFrame(nsnull, aPrevFrame, aFrameList);
|
||||
|
||||
// Set its starting column index and adjust the index of the
|
||||
// col group frames that follow
|
||||
SetStartingColumnIndexFor((nsTableColGroupFrame*)aFrameList,
|
||||
CalculateStartingColumnIndexFor((nsTableColGroupFrame*)aFrameList));
|
||||
|
||||
} else if (IsRowGroup(display->mDisplay)) {
|
||||
// Insert the frame
|
||||
mFrames.InsertFrame(nsnull, aPrevFrame, aFrameList);
|
||||
|
||||
// We'll need to do a pass-1 layout of all cells in all the rows of the
|
||||
// rowgroup
|
||||
InvalidateFirstPassCache();
|
||||
|
||||
// We need to rebuild the cell map, because currently we can't insert
|
||||
// new frames except at the end (append)
|
||||
InvalidateCellMap();
|
||||
|
||||
} else {
|
||||
// Just insert the frame and don't worry about reflowing it
|
||||
mFrames.InsertFrame(nsnull, aPrevFrame, aFrameList);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we've added any columns, we need to rebuild the column cache.
|
||||
InvalidateColumnCache();
|
||||
|
||||
// Because the number of columns may have changed invalidate the column
|
||||
// cache. Note that this has the side effect of recomputing the column
|
||||
// widths, so we don't need to call InvalidateColumnWidths()
|
||||
InvalidateColumnWidths();
|
||||
|
||||
// Mark the table as dirty and generate a reflow command targeted at the
|
||||
// outer table frame
|
||||
nsIReflowCommand* reflowCmd;
|
||||
nsresult rv;
|
||||
|
||||
mState |= NS_FRAME_IS_DIRTY;
|
||||
rv = NS_NewHTMLReflowCommand(&reflowCmd, mParent, nsIReflowCommand::ReflowDirty);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Add the reflow command
|
||||
rv = aPresShell.AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTableFrame::RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame)
|
||||
{
|
||||
// See what kind of frame we have
|
||||
const nsStyleDisplay *display=nsnull;
|
||||
aOldFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
|
||||
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) {
|
||||
nsIFrame* nextColGroupFrame;
|
||||
aOldFrame->GetNextSibling(&nextColGroupFrame);
|
||||
|
||||
// Remove the col group frame
|
||||
mColGroups.DestroyFrame(aPresContext, aOldFrame);
|
||||
|
||||
// Adjust the starting column index of the frames that follow
|
||||
SetStartingColumnIndexFor((nsTableColGroupFrame*)nextColGroupFrame,
|
||||
CalculateStartingColumnIndexFor((nsTableColGroupFrame*)nextColGroupFrame));
|
||||
|
||||
} else if (IsRowGroup(display->mDisplay)) {
|
||||
mFrames.DestroyFrame(aPresContext, aOldFrame);
|
||||
|
||||
// We need to rebuild the cell map, because currently we can't incrementally
|
||||
// remove rows
|
||||
InvalidateCellMap();
|
||||
|
||||
} else {
|
||||
// Just remove the frame
|
||||
mFrames.DestroyFrame(aPresContext, aOldFrame);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Because the number of columns may have changed invalidate the column
|
||||
// cache. Note that this has the side effect of recomputing the column
|
||||
// widths, so we don't need to call InvalidateColumnWidths()
|
||||
InvalidateColumnCache();
|
||||
|
||||
// Because the number of columns may have changed invalidate the column
|
||||
// cache. Note that this has the side effect of recomputing the column
|
||||
// widths, so we don't need to call InvalidateColumnWidths()
|
||||
InvalidateColumnWidths();
|
||||
|
||||
// Mark the table as dirty and generate a reflow command targeted at the
|
||||
// outer table frame
|
||||
nsIReflowCommand* reflowCmd;
|
||||
nsresult rv;
|
||||
|
||||
mState |= NS_FRAME_IS_DIRTY;
|
||||
rv = NS_NewHTMLReflowCommand(&reflowCmd, mParent, nsIReflowCommand::ReflowDirty);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Add the reflow command
|
||||
rv = aPresShell.AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::IncrementalReflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -2946,13 +3191,23 @@ NS_METHOD nsTableFrame::IncrementalReflow(nsIPresContext& aPresContext,
|
||||
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: IncrementalReflow\n");
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Constrain our reflow width to the computed table width. Note: this is
|
||||
// based on the width of the first-in-flow
|
||||
nsHTMLReflowState reflowState(aReflowState);
|
||||
PRInt32 pass1Width = mRect.width;
|
||||
if (mPrevInFlow) {
|
||||
nsTableFrame* table = (nsTableFrame*)GetFirstInFlow();
|
||||
pass1Width = table->mRect.width;
|
||||
}
|
||||
reflowState.availableWidth = pass1Width;
|
||||
|
||||
nsMargin borderPadding;
|
||||
GetBorderPlusMarginPadding(borderPadding);
|
||||
InnerTableReflowState state(aPresContext, aReflowState, borderPadding);
|
||||
InnerTableReflowState state(aPresContext, reflowState, borderPadding);
|
||||
|
||||
// determine if this frame is the target or not
|
||||
nsIFrame *target=nsnull;
|
||||
rv = aReflowState.reflowCommand->GetTarget(target);
|
||||
rv = reflowState.reflowCommand->GetTarget(target);
|
||||
if ((PR_TRUE==NS_SUCCEEDED(rv)) && (nsnull!=target))
|
||||
{
|
||||
// this is the target if target is either this or the outer table frame containing this inner frame
|
||||
@ -2964,10 +3219,9 @@ NS_METHOD nsTableFrame::IncrementalReflow(nsIPresContext& aPresContext,
|
||||
{
|
||||
// Get the next frame in the reflow chain
|
||||
nsIFrame* nextFrame;
|
||||
aReflowState.reflowCommand->GetNext(nextFrame);
|
||||
reflowState.reflowCommand->GetNext(nextFrame);
|
||||
|
||||
// Recover our reflow state
|
||||
//RecoverState(state, nextFrame);
|
||||
rv = IR_TargetIsChild(aPresContext, aDesiredSize, state, aStatus, nextFrame);
|
||||
}
|
||||
}
|
||||
@ -2991,73 +3245,6 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: IncrementalReflow_TargetIsMe with type=%d\n", type);
|
||||
switch (type)
|
||||
{
|
||||
case nsIReflowCommand::FrameInserted :
|
||||
NS_ASSERTION(nsnull!=objectFrame, "bad objectFrame");
|
||||
NS_ASSERTION(nsnull!=childDisplay, "bad childDisplay");
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
||||
{
|
||||
rv = IR_ColGroupInserted(aPresContext, aDesiredSize, aReflowState, aStatus,
|
||||
(nsTableColGroupFrame*)objectFrame, PR_FALSE);
|
||||
}
|
||||
else if (IsRowGroup(childDisplay->mDisplay))
|
||||
{
|
||||
rv = IR_RowGroupInserted(aPresContext, aDesiredSize, aReflowState, aStatus,
|
||||
GetRowGroupFrameFor(objectFrame, childDisplay), PR_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = AddFrame(aReflowState.reflowState, objectFrame);
|
||||
}
|
||||
break;
|
||||
|
||||
case nsIReflowCommand::FrameAppended :
|
||||
if (!objectFrame)
|
||||
break;
|
||||
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
||||
{
|
||||
rv = IR_ColGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus,
|
||||
(nsTableColGroupFrame*)objectFrame);
|
||||
}
|
||||
else if (IsRowGroup(childDisplay->mDisplay))
|
||||
{
|
||||
rv = IR_RowGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus,
|
||||
GetRowGroupFrameFor(objectFrame, childDisplay));
|
||||
}
|
||||
else
|
||||
{ // no optimization to be done for Unknown frame types, so just reuse the Inserted method
|
||||
rv = AddFrame(aReflowState.reflowState, objectFrame);
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
case nsIReflowCommand::FrameReplaced :
|
||||
NS_ASSERTION(nsnull!=objectFrame, "bad objectFrame");
|
||||
NS_ASSERTION(nsnull!=childDisplay, "bad childDisplay");
|
||||
|
||||
*/
|
||||
|
||||
case nsIReflowCommand::FrameRemoved :
|
||||
if (!objectFrame)
|
||||
break;
|
||||
|
||||
NS_ASSERTION(nsnull!=childDisplay, "bad childDisplay");
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
||||
{
|
||||
rv = IR_ColGroupRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
|
||||
(nsTableColGroupFrame*)objectFrame);
|
||||
}
|
||||
else if (IsRowGroup(childDisplay->mDisplay))
|
||||
{
|
||||
rv = IR_RowGroupRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
|
||||
GetRowGroupFrameFor(objectFrame, childDisplay));
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = mFrames.DestroyFrame(aPresContext, objectFrame);
|
||||
}
|
||||
break;
|
||||
|
||||
case nsIReflowCommand::StyleChanged :
|
||||
rv = IR_StyleChanged(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
break;
|
||||
@ -3067,12 +3254,8 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
|
||||
rv = NS_ERROR_ILLEGAL_VALUE;
|
||||
break;
|
||||
|
||||
case nsIReflowCommand::PullupReflow:
|
||||
case nsIReflowCommand::PushReflow:
|
||||
case nsIReflowCommand::CheckPullupReflow :
|
||||
case nsIReflowCommand::UserDefined :
|
||||
default:
|
||||
NS_NOTYETIMPLEMENTED("unimplemented reflow command type");
|
||||
NS_NOTYETIMPLEMENTED("unexpected reflow command type");
|
||||
rv = NS_ERROR_NOT_IMPLEMENTED;
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: reflow command not implemented.\n");
|
||||
break;
|
||||
@ -3081,187 +3264,6 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::IR_ColGroupInserted(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableColGroupFrame * aInsertedFrame,
|
||||
PRBool aReplace)
|
||||
{
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: IR_ColGroupInserted for frame %p\n", aInsertedFrame);
|
||||
nsresult rv=NS_OK;
|
||||
PRBool adjustStartingColIndex=PR_FALSE;
|
||||
PRInt32 startingColIndex=0;
|
||||
// find out what frame to insert aInsertedFrame after
|
||||
nsIFrame *frameToInsertAfter=nsnull;
|
||||
rv = aReflowState.reflowState.reflowCommand->GetPrevSiblingFrame(frameToInsertAfter);
|
||||
// insert aInsertedFrame as the first child. Set its start col index to 0
|
||||
if (nsnull==frameToInsertAfter)
|
||||
{
|
||||
mColGroups.InsertFrame(nsnull, nsnull, aInsertedFrame);
|
||||
startingColIndex += aInsertedFrame->SetStartColumnIndex(0);
|
||||
adjustStartingColIndex=PR_TRUE;
|
||||
}
|
||||
nsIFrame *childFrame=mColGroups.FirstChild();
|
||||
nsIFrame *prevSib=nsnull;
|
||||
while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
|
||||
{
|
||||
if ((nsnull!=frameToInsertAfter) && (childFrame==frameToInsertAfter))
|
||||
{
|
||||
nsIFrame *nextSib=nsnull;
|
||||
frameToInsertAfter->GetNextSibling(&nextSib);
|
||||
aInsertedFrame->SetNextSibling(nextSib);
|
||||
frameToInsertAfter->SetNextSibling(aInsertedFrame);
|
||||
// account for childFrame being a COLGROUP now
|
||||
if (PR_FALSE==adjustStartingColIndex) // we haven't gotten to aDeletedFrame yet
|
||||
startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
|
||||
// skip ahead to aInsertedFrame, since we just handled the frame we inserted after
|
||||
childFrame=aInsertedFrame;
|
||||
adjustStartingColIndex=PR_TRUE; // now that we've inserted aInsertedFrame,
|
||||
// start adjusting subsequent col groups' starting col index including aInsertedFrame
|
||||
}
|
||||
if (PR_FALSE==adjustStartingColIndex) // we haven't gotten to aDeletedFrame yet
|
||||
startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
|
||||
else // we've removed aDeletedFrame, now adjust the starting col index of all subsequent col groups
|
||||
startingColIndex += ((nsTableColGroupFrame *)childFrame)->SetStartColumnIndex(startingColIndex);
|
||||
prevSib=childFrame;
|
||||
rv = childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
|
||||
InvalidateColumnCache();
|
||||
//XXX: what we want to do here is determine if the new COL information changes anything about layout
|
||||
// if not, skip invalidating the first passs
|
||||
// if so, and we can fix the first pass info
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::IR_ColGroupAppended(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableColGroupFrame * aAppendedFrame)
|
||||
{
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: IR_ColGroupAppended for frame %p\n", aAppendedFrame);
|
||||
nsresult rv=NS_OK;
|
||||
PRInt32 startingColIndex=0;
|
||||
nsIFrame *childFrame=mColGroups.FirstChild();
|
||||
nsIFrame *lastChild=childFrame;
|
||||
while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
|
||||
{
|
||||
startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
|
||||
lastChild=childFrame;
|
||||
rv = childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
|
||||
// append aAppendedFrame
|
||||
if (nsnull!=lastChild)
|
||||
lastChild->SetNextSibling(aAppendedFrame);
|
||||
else
|
||||
mColGroups.SetFrames(aAppendedFrame);
|
||||
|
||||
aAppendedFrame->SetStartColumnIndex(startingColIndex);
|
||||
|
||||
#if 0
|
||||
|
||||
we would only want to do this if manufactured col groups were invisible to the DOM. Since they
|
||||
currently are visible, they should behave just as if they were content-backed "real" colgroups
|
||||
If this decision is changed, the code below is a half-finished attempt to rationalize the situation.
|
||||
It requires having built a list of the colGroups before we get to this point.
|
||||
|
||||
// look at the last col group. If it is implicit, and it's cols are implicit, then
|
||||
// it and its cols were manufactured for table layout.
|
||||
// Delete it if possible, otherwise move it to the end of the list
|
||||
|
||||
if (0<colGroupCount)
|
||||
{
|
||||
nsTableColGroupFrame *colGroup = (nsTableColGroupFrame *)(colGroupList.ElementAt(colGroupCount-1));
|
||||
if (PR_TRUE==colGroup->IsManufactured())
|
||||
{ // account for the new COLs that were added in aAppendedFrame
|
||||
// first, try to delete the implicit colgroup
|
||||
|
||||
// if we couldn't delete it, move the implicit colgroup to the end of the list
|
||||
// and adjust it's col indexes
|
||||
nsIFrame *colGroupNextSib;
|
||||
colGroup->GetNextSibling(colGroupNextSib);
|
||||
childFrame=mColGroups.FirstChild();
|
||||
nsIFrame * prevSib=nsnull;
|
||||
rv = NS_OK;
|
||||
while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
|
||||
{
|
||||
if (childFrame==colGroup)
|
||||
{
|
||||
if (nsnull!=prevSib) // colGroup is in the middle of the list, remove it
|
||||
prevSib->SetNextSibling(colGroupNextSib);
|
||||
else // colGroup was the first child, so set it's next sib to first child
|
||||
mColGroups.SetFrames(colGroupNextSib);
|
||||
aAppendedFrame->SetNextSibling(colGroup); // place colGroup at the end of the list
|
||||
colGroup->SetNextSibling(nsnull);
|
||||
break;
|
||||
}
|
||||
prevSib=childFrame;
|
||||
rv = childFrame->GetNextSibling(childFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
InvalidateColumnCache();
|
||||
//XXX: what we want to do here is determine if the new COL information changes anything about layout
|
||||
// if not, skip invalidating the first passs
|
||||
// if so, and we can fix the first pass info
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_METHOD nsTableFrame::IR_ColGroupRemoved(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableColGroupFrame * aDeletedFrame)
|
||||
{
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: IR_ColGroupRemoved for frame %p\n", aDeletedFrame);
|
||||
nsresult rv=NS_OK;
|
||||
PRBool adjustStartingColIndex=PR_FALSE;
|
||||
PRInt32 startingColIndex=0;
|
||||
nsIFrame *childFrame=mColGroups.FirstChild();
|
||||
nsIFrame *prevSib=nsnull;
|
||||
while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
|
||||
{
|
||||
if (childFrame==aDeletedFrame)
|
||||
{
|
||||
nsIFrame *deleteFrameNextSib=nsnull;
|
||||
aDeletedFrame->GetNextSibling(&deleteFrameNextSib);
|
||||
if (nsnull!=prevSib)
|
||||
prevSib->SetNextSibling(deleteFrameNextSib);
|
||||
else
|
||||
mColGroups.SetFrames(deleteFrameNextSib);
|
||||
childFrame=deleteFrameNextSib;
|
||||
if (nsnull==childFrame)
|
||||
break;
|
||||
adjustStartingColIndex=PR_TRUE; // now that we've removed aDeletedFrame, start adjusting subsequent col groups' starting col index
|
||||
}
|
||||
const nsStyleDisplay *display;
|
||||
childFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)display);
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay)
|
||||
{
|
||||
if (PR_FALSE==adjustStartingColIndex) // we haven't gotten to aDeletedFrame yet
|
||||
startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
|
||||
else // we've removed aDeletedFrame, now adjust the starting col index of all subsequent col groups
|
||||
startingColIndex += ((nsTableColGroupFrame *)childFrame)->SetStartColumnIndex(startingColIndex);
|
||||
}
|
||||
prevSib=childFrame;
|
||||
rv = childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
|
||||
InvalidateColumnCache();
|
||||
//XXX: what we want to do here is determine if the new COL information changes anything about layout
|
||||
// if not, skip invalidating the first passs
|
||||
// if so, and we can fix the first pass info
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::IR_StyleChanged(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
@ -3277,85 +3279,69 @@ NS_METHOD nsTableFrame::IR_StyleChanged(nsIPresContext& aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::IR_RowGroupInserted(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableRowGroupFrame * aInsertedFrame,
|
||||
PRBool aReplace)
|
||||
// Recovers the reflow state to what it should be if aKidFrame is about
|
||||
// to be reflowed. Restores the following:
|
||||
// - availSize
|
||||
// - y
|
||||
// - footerFrame
|
||||
// - firstBodySection
|
||||
//
|
||||
// In the case of the footer frame the y-offset is set to its current
|
||||
// y-offset. Note that this is different from resize reflow when the
|
||||
// footer is positioned higher up and then moves down as each row
|
||||
// group frame is relowed
|
||||
//
|
||||
// XXX This is kind of klunky because the InnerTableReflowState::y
|
||||
// data member does not include the table's border/padding...
|
||||
nsresult
|
||||
nsTableFrame::RecoverState(InnerTableReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame)
|
||||
{
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: IR_RowGroupInserted for frame %p\n", aInsertedFrame);
|
||||
nsresult rv = AddFrame(aReflowState.reflowState, aInsertedFrame);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// do a pass-1 layout of all the cells in all the rows of the rowgroup
|
||||
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState.reflowState, aStatus,
|
||||
aInsertedFrame, eReflowReason_Initial, PR_FALSE);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
// Walk the list of children looking for aKidFrame
|
||||
for (nsIFrame* frame = mFrames.FirstChild(); frame; frame->GetNextSibling(&frame)) {
|
||||
// If this is a footer row group, remember it
|
||||
const nsStyleDisplay *display;
|
||||
frame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
|
||||
|
||||
InvalidateCellMap();
|
||||
InvalidateColumnCache();
|
||||
// We only allow a single footer frame, and the footer frame must occur before
|
||||
// any body section row groups
|
||||
if ((NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == display->mDisplay) &&
|
||||
!aReflowState.footerFrame && !aReflowState.firstBodySection) {
|
||||
aReflowState.footerFrame = frame;
|
||||
|
||||
} else if ((NS_STYLE_DISPLAY_TABLE_ROW_GROUP == display->mDisplay) &&
|
||||
!aReflowState.firstBodySection) {
|
||||
aReflowState.firstBodySection = frame;
|
||||
}
|
||||
|
||||
// See if this is the frame we're looking for
|
||||
if (frame == aKidFrame) {
|
||||
// If it's the footer, then keep going because the footer is at the
|
||||
// very bottom
|
||||
if (frame != aReflowState.footerFrame) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
// Get the frame's height
|
||||
nsSize kidSize;
|
||||
frame->GetSize(kidSize);
|
||||
|
||||
// If our height is constrained then update the available height. Do
|
||||
// this for all frames including the footer frame
|
||||
if (PR_FALSE == aReflowState.unconstrainedHeight) {
|
||||
aReflowState.availSize.height -= kidSize.height;
|
||||
}
|
||||
|
||||
// Update the running y-offset. Don't do this for the footer frame
|
||||
if (frame != aReflowState.footerFrame) {
|
||||
aReflowState.y += kidSize.height;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// since we know we're doing an append here, we can optimize
|
||||
NS_METHOD nsTableFrame::IR_RowGroupAppended(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableRowGroupFrame * aAppendedFrame)
|
||||
{
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: IR_RowGroupAppended for frame %p\n", aAppendedFrame);
|
||||
// hook aAppendedFrame into the child list
|
||||
nsresult rv = AddFrame(aReflowState.reflowState, aAppendedFrame);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// account for the cells in the rows that are children of aAppendedFrame
|
||||
// this will add the content of the rowgroup to the cell map
|
||||
rv = DidAppendRowGroup(aAppendedFrame);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// do a pass-1 layout of all the cells in all the rows of the rowgroup
|
||||
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState.reflowState, aStatus,
|
||||
aAppendedFrame, eReflowReason_Initial, PR_TRUE);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// if we've added any columns, we need to rebuild the column cache
|
||||
// XXX: it would be nice to have a mechanism to just extend the column cache, rather than rebuild it completely
|
||||
InvalidateColumnCache();
|
||||
|
||||
// if any column widths have to change due to this, rebalance column widths
|
||||
//XXX need to calculate this, but for now just do it
|
||||
InvalidateColumnWidths();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::IR_RowGroupRemoved(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableRowGroupFrame * aDeletedFrame)
|
||||
{
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: IR_RowGroupRemoved for frame %p\n", aDeletedFrame);
|
||||
nsresult rv = mFrames.DestroyFrame(aPresContext, aDeletedFrame);
|
||||
InvalidateCellMap();
|
||||
InvalidateColumnCache();
|
||||
|
||||
// if any column widths have to change due to this, rebalance column widths
|
||||
//XXX need to calculate this, but for now just do it
|
||||
InvalidateColumnWidths();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_METHOD nsTableFrame::IR_TargetIsChild(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
@ -3365,6 +3351,8 @@ NS_METHOD nsTableFrame::IR_TargetIsChild(nsIPresContext& aPresContext,
|
||||
{
|
||||
nsresult rv;
|
||||
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: IR_TargetIsChild\n");
|
||||
// Recover the state as if aNextFrame is about to be reflowed
|
||||
RecoverState(aReflowState, aNextFrame);
|
||||
|
||||
// Remember the old rect
|
||||
nsRect oldKidRect;
|
||||
@ -3372,24 +3360,31 @@ NS_METHOD nsTableFrame::IR_TargetIsChild(nsIPresContext& aPresContext,
|
||||
|
||||
// Pass along the reflow command
|
||||
nsHTMLReflowMetrics desiredSize(nsnull);
|
||||
// XXX Correctly compute the available space...
|
||||
nsSize availSpace(aReflowState.reflowState.availableWidth, aReflowState.reflowState.availableHeight);
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState,
|
||||
aNextFrame, availSpace);
|
||||
aNextFrame, aReflowState.availSize);
|
||||
|
||||
rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
|
||||
|
||||
// Resize the row group frame
|
||||
nsRect kidRect;
|
||||
aNextFrame->GetRect(kidRect);
|
||||
aNextFrame->SizeTo(desiredSize.width, desiredSize.height);
|
||||
// Place the row group frame. Don't use PlaceChild(), because it moves
|
||||
// the footer frame as well. We'll adjust the footer frame later on in
|
||||
// AdjustSiblingsAfterReflow()
|
||||
nscoord x = aReflowState.mBorderPadding.left;
|
||||
nscoord y = aReflowState.mBorderPadding.top + aReflowState.y;
|
||||
nsRect kidRect(x, y, desiredSize.width, desiredSize.height);
|
||||
aNextFrame->SetRect(kidRect);
|
||||
|
||||
// Adjust the running y-offset
|
||||
aReflowState.y += kidRect.height;
|
||||
|
||||
// If our height is constrained, then update the available height
|
||||
if (PR_FALSE == aReflowState.unconstrainedHeight) {
|
||||
aReflowState.availSize.height -= kidRect.height;
|
||||
}
|
||||
|
||||
// If the column width info is valid, then adjust the row group frames
|
||||
// that follow. Otherwise, return and we'll recompute the column widths
|
||||
// and reflow all the row group frames
|
||||
if (!NeedsReflow(aReflowState.reflowState,
|
||||
nsSize(aReflowState.reflowState.availableWidth,
|
||||
aReflowState.reflowState.availableHeight))) {
|
||||
if (!NeedsReflow(aReflowState.reflowState)) {
|
||||
// Adjust the row groups that follow
|
||||
AdjustSiblingsAfterReflow(aPresContext, aReflowState, aNextFrame, desiredSize.height -
|
||||
oldKidRect.height);
|
||||
|
@ -95,6 +95,20 @@ public:
|
||||
/** @see nsIFrame::Destroy */
|
||||
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
|
||||
|
||||
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList);
|
||||
NS_IMETHOD InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList);
|
||||
NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame);
|
||||
|
||||
/** helper method to find the table parent of any table frame object */
|
||||
// TODO: today, this depends on display types. This should be changed to rely
|
||||
// on stronger criteria, like an inner table frame atom
|
||||
@ -439,6 +453,14 @@ protected:
|
||||
* @return PR_TRUE if this table is nested inside another table.
|
||||
*/
|
||||
PRBool IsNested(const nsHTMLReflowState& aReflowState, const nsStylePosition *& aPosition) const;
|
||||
|
||||
// Sets the starting column index for aColGroupFrame and the siblings frames that
|
||||
// follow
|
||||
void SetStartingColumnIndexFor(nsTableColGroupFrame* aColGroupFrame,
|
||||
PRInt32 aIndex);
|
||||
|
||||
// Calculate the starting column index to use for the specified col group frame
|
||||
PRInt32 CalculateStartingColumnIndexFor(nsTableColGroupFrame* aColGroupFrame);
|
||||
|
||||
public:
|
||||
/** first pass of ResizeReflow.
|
||||
@ -463,6 +485,9 @@ public:
|
||||
NS_IMETHOD GetTableSpecifiedHeight(nscoord& aHeight, const nsHTMLReflowState& aReflowState);
|
||||
virtual PRBool RowGroupsShouldBeConstrained() { return PR_FALSE; }
|
||||
|
||||
/** do I need to do a reflow? */
|
||||
virtual PRBool NeedsReflow(const nsHTMLReflowState& aReflowState);
|
||||
|
||||
protected:
|
||||
/** second pass of ResizeReflow.
|
||||
* lays out all table content with aMaxSize(computed_table_width, given_table_height)
|
||||
@ -509,72 +534,6 @@ protected:
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
/** process a colgroup inserted notification
|
||||
* @param aInsertedFrame the new colgroup frame
|
||||
* @param aReplace PR_TRUE if aInsertedFrame is replacing an existing frame
|
||||
* Not Yet Implemented.
|
||||
* @see nsIFrameReflow::Reflow
|
||||
*/
|
||||
NS_IMETHOD IR_ColGroupInserted(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableColGroupFrame * aInsertedFrame,
|
||||
PRBool aReplace);
|
||||
|
||||
/** process a colgroup appended notification. This method is optimized for append.
|
||||
* @param aAppendedFrame the new colgroup frame
|
||||
* @see nsIFrameReflow::Reflow
|
||||
*/
|
||||
NS_IMETHOD IR_ColGroupAppended(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableColGroupFrame * aAppendedFrame);
|
||||
|
||||
/** process a colgroup removed notification.
|
||||
* @param aDeletedFrame the colgroup frame to remove
|
||||
* @see nsIFrameReflow::Reflow
|
||||
*/
|
||||
NS_IMETHOD IR_ColGroupRemoved(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableColGroupFrame * aDeletedFrame);
|
||||
|
||||
/** process a rowgroup inserted notification
|
||||
* @param aInsertedFrame the new rowgroup frame
|
||||
* @param aReplace PR_TRUE if aInsertedFrame is replacing an existing frame
|
||||
* Not Yet Implemented.
|
||||
* @see nsIFrameReflow::Reflow
|
||||
*/
|
||||
NS_IMETHOD IR_RowGroupInserted(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableRowGroupFrame * aInsertedFrame,
|
||||
PRBool aReplace);
|
||||
|
||||
/** process a rowgroup appended notification. This method is optimized for append.
|
||||
* @param aAppendedFrame the new rowgroup frame
|
||||
* @see nsIFrameReflow::Reflow
|
||||
*/
|
||||
NS_IMETHOD IR_RowGroupAppended(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableRowGroupFrame * aAppendedFrame);
|
||||
|
||||
/** process a rowgroup removed notification.
|
||||
* @param aDeletedFrame the rowgroup frame to remove
|
||||
* @see nsIFrameReflow::Reflow
|
||||
*/
|
||||
NS_IMETHOD IR_RowGroupRemoved(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableRowGroupFrame * aDeletedFrame);
|
||||
|
||||
/** process a style chnaged notification.
|
||||
* @see nsIFrameReflow::Reflow
|
||||
* TODO: needs to be optimized for which attribute was actually changed.
|
||||
@ -588,6 +547,9 @@ protected:
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nscoord aDeltaY);
|
||||
|
||||
nsresult RecoverState(InnerTableReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame);
|
||||
|
||||
NS_METHOD AdjustForCollapsingRowGroup(nsIFrame* aRowGroupFrame,
|
||||
PRInt32& aRowX);
|
||||
@ -676,10 +638,6 @@ protected:
|
||||
/** sets the width of the table according to the computed widths of each column. */
|
||||
virtual void SetTableWidth(nsIPresContext& aPresContext);
|
||||
|
||||
/** given the new parent size, do I really need to do a reflow? */
|
||||
virtual PRBool NeedsReflow(const nsHTMLReflowState& aReflowState,
|
||||
const nsSize& aMaxSize);
|
||||
|
||||
/** returns PR_TRUE if the cached pass 1 data is still valid */
|
||||
virtual PRBool IsFirstPassValid() const;
|
||||
|
||||
|
@ -337,11 +337,11 @@ NS_IMETHODIMP nsTableOuterFrame::SetSelected(nsIDOMRange *aRange,PRBool aSelecte
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool nsTableOuterFrame::NeedsReflow(const nsHTMLReflowState& aReflowState, const nsSize& aMaxSize)
|
||||
PRBool nsTableOuterFrame::NeedsReflow(const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
PRBool result=PR_TRUE;
|
||||
if (nsnull != mInnerTableFrame) {
|
||||
result = ((nsTableFrame *)mInnerTableFrame)->NeedsReflow(aReflowState, aMaxSize);
|
||||
result = ((nsTableFrame *)mInnerTableFrame)->NeedsReflow(aReflowState);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ protected:
|
||||
* or if the table style attributes or parent max height/width have
|
||||
* changed.
|
||||
*/
|
||||
PRBool NeedsReflow(const nsHTMLReflowState& aReflowState, const nsSize& aMaxSize);
|
||||
PRBool NeedsReflow(const nsHTMLReflowState& aReflowState);
|
||||
|
||||
/** position the child frame
|
||||
* @param aReflowState the state of the reflow process
|
||||
|
@ -1373,26 +1373,29 @@ NS_METHOD nsTableRowFrame::IR_TargetIsChild(nsIPresContext& aPresContext,
|
||||
// size.
|
||||
// XXX It would be nice if we could skip this step and the next step if the
|
||||
// column width isn't dependent on the max cell width...
|
||||
kidReflowState.reason = eReflowReason_Initial;
|
||||
kidReflowState.reflowCommand = nsnull;
|
||||
kidReflowState.availableWidth = NS_UNCONSTRAINEDSIZE;
|
||||
rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
|
||||
if (gsDebug)
|
||||
printf ("TR %p for cell %p Incremental Reflow: desired=%d, MES=%d\n",
|
||||
this, aNextFrame, desiredSize.width, kidMaxElementSize.width);
|
||||
// Update the cell layout data.
|
||||
//XXX: this is a hack, shouldn't it be the case that a min size is
|
||||
// never larger than a desired size?
|
||||
if (kidMaxElementSize.width>desiredSize.width)
|
||||
desiredSize.width = kidMaxElementSize.width;
|
||||
if (kidMaxElementSize.height>desiredSize.height)
|
||||
desiredSize.height = kidMaxElementSize.height;
|
||||
((nsTableCellFrame *)aNextFrame)->SetPass1DesiredSize(desiredSize);
|
||||
((nsTableCellFrame *)aNextFrame)->SetPass1MaxElementSize(kidMaxElementSize);
|
||||
// Now reflow the cell again this time constraining the width
|
||||
// XXX Ignore for now the possibility that the column width has changed...
|
||||
kidReflowState.availableWidth = availWidth;
|
||||
rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
|
||||
if (aReflowState.tableFrame->RequiresPass1Layout()) {
|
||||
kidReflowState.reason = eReflowReason_Initial;
|
||||
kidReflowState.reflowCommand = nsnull;
|
||||
kidReflowState.availableWidth = NS_UNCONSTRAINEDSIZE;
|
||||
rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
|
||||
if (gsDebug)
|
||||
printf ("TR %p for cell %p Incremental Reflow: desired=%d, MES=%d\n",
|
||||
this, aNextFrame, desiredSize.width, kidMaxElementSize.width);
|
||||
// Update the cell layout data.
|
||||
//XXX: this is a hack, shouldn't it be the case that a min size is
|
||||
// never larger than a desired size?
|
||||
if (kidMaxElementSize.width>desiredSize.width)
|
||||
desiredSize.width = kidMaxElementSize.width;
|
||||
if (kidMaxElementSize.height>desiredSize.height)
|
||||
desiredSize.height = kidMaxElementSize.height;
|
||||
((nsTableCellFrame *)aNextFrame)->SetPass1DesiredSize(desiredSize);
|
||||
((nsTableCellFrame *)aNextFrame)->SetPass1MaxElementSize(kidMaxElementSize);
|
||||
|
||||
// Now reflow the cell again this time constraining the width
|
||||
// XXX Ignore for now the possibility that the column width has changed...
|
||||
kidReflowState.availableWidth = availWidth;
|
||||
rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
|
||||
}
|
||||
|
||||
// Place the child after taking into account it's margin and attributes
|
||||
// XXX We need to ask the table (or the table layout strategy) if the column
|
||||
@ -1434,6 +1437,12 @@ NS_METHOD nsTableRowFrame::IR_TargetIsChild(nsIPresContext& aPresContext,
|
||||
|
||||
SetMaxChildHeight(aReflowState.maxCellHeight, maxCellTopMargin, maxCellBottomMargin);
|
||||
|
||||
// If the column widths have changed, then tell the table to rebalance
|
||||
// the column widths
|
||||
if (aReflowState.tableFrame->RequiresPass1Layout()) {
|
||||
aReflowState.tableFrame->InvalidateColumnWidths();
|
||||
}
|
||||
|
||||
// Return our desired size. Note that our desired width is just whatever width
|
||||
// we were given by the row group frame
|
||||
aDesiredSize.width = aReflowState.availSize.width;
|
||||
|
@ -361,7 +361,6 @@ void nsTableRowGroupFrame::PlaceChild(nsIPresContext& aPresContext,
|
||||
if (PR_TRUE==aReflowState.firstRow)
|
||||
{
|
||||
aReflowState.firstRow = PR_FALSE;
|
||||
aReflowState.firstRowHeight = aKidRect.height;
|
||||
if (nsnull != aMaxElementSize) {
|
||||
aMaxElementSize->width = aKidMaxElementSize.width;
|
||||
aMaxElementSize->height = aKidMaxElementSize.height;
|
||||
@ -597,14 +596,15 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
|
||||
// all table cells have the same top and bottom margins, namely cellSpacingY
|
||||
nscoord cellSpacingY = tableFrame->GetCellSpacingY();
|
||||
|
||||
// iterate children and for each row get its height
|
||||
// iterate children and for each row get the height of the tallest cell
|
||||
PRInt32 numRows;
|
||||
GetRowCount(numRows, PR_FALSE);
|
||||
PRInt32 *rowHeights = new PRInt32[numRows];
|
||||
nsCRT::memset (rowHeights, 0, numRows*sizeof(PRInt32));
|
||||
nscoord *rowHeights = new nscoord[numRows];
|
||||
nsCRT::memset (rowHeights, 0, numRows*sizeof(nscoord));
|
||||
|
||||
/* Step 1: get the height of the tallest cell in the row and save it for
|
||||
* pass 2
|
||||
* pass 2. This height is for table cells that originate in this
|
||||
* row and that don't span into the rows that follow
|
||||
*/
|
||||
nsIFrame* rowFrame = GetFirstFrame();
|
||||
PRInt32 rowIndex = 0;
|
||||
@ -649,7 +649,7 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
|
||||
* If the cell's desired height is the larger value, resize the rows and contained
|
||||
* cells by an equal percentage of the additional space.
|
||||
* We go through this loop twice. The first time, we are adjusting cell heights
|
||||
* and row y-offsets on the fly.
|
||||
* on the fly.
|
||||
* The second time through the loop, we're ensuring that subsequent row-spanning cells
|
||||
* didn't change prior calculations.
|
||||
* Since we are guaranteed to have found the max height spanners the first time through,
|
||||
@ -661,6 +661,7 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
|
||||
*/
|
||||
|
||||
PRInt32 rowGroupHeight;
|
||||
nscoord deltaY = 0;
|
||||
for (PRInt32 counter=0; counter<2; counter++)
|
||||
{
|
||||
rowGroupHeight = 0;
|
||||
@ -686,90 +687,96 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
|
||||
PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(rowIndex + startRowIndex,
|
||||
(nsTableCellFrame*)cellFrame);
|
||||
if (rowSpan > 1)
|
||||
{ // found a cell with rowspan > 1, determine its height
|
||||
{ // found a cell with rowspan > 1, determine the height of the rows it
|
||||
// spans
|
||||
if (gsDebug) printf("TRGF CalcRowH: cell %p has rowspan=%d\n", cellFrame, rowSpan);
|
||||
nscoord heightOfRowsSpanned = 0;
|
||||
PRInt32 i;
|
||||
for (i = 0; i < rowSpan; i++) {
|
||||
heightOfRowsSpanned += rowHeights[rowIndex + i];
|
||||
}
|
||||
// the avail height needs to reduce by top and bottom margins
|
||||
// reduce the height by top and bottom margins
|
||||
nscoord availHeightOfRowsSpanned = heightOfRowsSpanned - cellSpacingY - cellSpacingY;
|
||||
if (gsDebug) printf("TRGF CalcRowH: availHeightOfRowsSpanned=%d\n", availHeightOfRowsSpanned);
|
||||
/* if the cell height fits in the rows, expand the spanning cell's height and slap it in */
|
||||
|
||||
// see if the cell's height fits within the rows it spans. If this is
|
||||
// pass 1 then use the cell's desired height and not the current height
|
||||
// of its frame. That way this works for incremental reflow, too
|
||||
nsSize cellFrameSize;
|
||||
cellFrame->GetSize(cellFrameSize);
|
||||
if (availHeightOfRowsSpanned > cellFrameSize.height)
|
||||
if (0 == counter) {
|
||||
nsSize cellDesiredSize = ((nsTableCellFrame*)cellFrame)->GetDesiredSize();
|
||||
cellFrameSize.height = cellDesiredSize.height;
|
||||
}
|
||||
|
||||
if (availHeightOfRowsSpanned >= cellFrameSize.height)
|
||||
{
|
||||
// yes the cell's height fits with the available space of the rows it
|
||||
// spans. Set the cell frame's height
|
||||
if (gsDebug) printf("TRGF CalcRowH: spanning cell fits in rows spanned, had h=%d, expanded to %d\n",
|
||||
cellFrameSize.height, availHeightOfRowsSpanned);
|
||||
cellFrame->SizeTo(cellFrameSize.width, availHeightOfRowsSpanned);
|
||||
// Realign cell content based on new height
|
||||
((nsTableCellFrame*)cellFrame)->VerticallyAlignChild();
|
||||
}
|
||||
/* otherwise, distribute the excess height to the rows effected.
|
||||
* push all subsequent rows down by the total change in height of all the rows above it
|
||||
*/
|
||||
else
|
||||
{
|
||||
// the cell's height is larger than the available space of the rows it
|
||||
// spans so distribute the excess height to the rows affected
|
||||
PRInt32 excessHeight = cellFrameSize.height - availHeightOfRowsSpanned;
|
||||
if (gsDebug) printf("TRGF CalcRowH: excessHeight=%d\n", excessHeight);
|
||||
// for every row starting at the row with the spanning cell...
|
||||
|
||||
// for every row starting at the row with the spanning cell and down
|
||||
// to the last row spanned by the cell
|
||||
nsTableRowFrame *rowFrameToBeResized = (nsTableRowFrame *)rowFrame;
|
||||
PRInt32 *excessForRow = new PRInt32[numRows];
|
||||
nsCRT::memset (excessForRow, 0, numRows*sizeof(PRInt32));
|
||||
nscoord excessAllocated = 0;
|
||||
for (i = rowIndex; i < numRows; i++) {
|
||||
for (i = rowIndex; i < (rowIndex + rowSpan); i++) {
|
||||
if (gsDebug) printf("TRGF CalcRowH: for row index=%d\n", i);
|
||||
// if the row is within the spanned range, resize the row
|
||||
if (i < (rowIndex + rowSpan)) {
|
||||
//float percent = ((float)rowHeights[i]) / ((float)availHeightOfRowsSpanned);
|
||||
//excessForRow[i] = NSToCoordRound(((float)(excessHeight)) * percent);
|
||||
float percent = ((float)rowHeights[i]) / ((float)heightOfRowsSpanned);
|
||||
// give rows their percentage, except the last row gets the remainder
|
||||
excessForRow[i] = ((i - 1) == (rowIndex + rowSpan))
|
||||
? excessHeight - excessAllocated
|
||||
: NSToCoordRound(((float)(excessHeight)) * percent);
|
||||
excessAllocated += excessForRow[i];
|
||||
if (gsDebug) printf("TRGF CalcRowH: for row %d, excessHeight=%d from percent %f\n",
|
||||
i, excessForRow[i], percent);
|
||||
// update the row height
|
||||
rowHeights[i] += excessForRow[i];
|
||||
// The amount of additional space each row gets is based on the
|
||||
// percentage of space it occupies, i.e. they don't all get the
|
||||
// same amount of available space
|
||||
float percent = ((float)rowHeights[i]) / ((float)heightOfRowsSpanned);
|
||||
|
||||
// give rows their percentage, except for the last row which gets
|
||||
// the remainder
|
||||
nscoord excessForRow = ((i + 1) == (rowIndex + rowSpan)) ?
|
||||
excessHeight - excessAllocated :
|
||||
NSToCoordRound(((float)(excessHeight)) * percent);
|
||||
excessAllocated += excessForRow;
|
||||
if (gsDebug) printf("TRGF CalcRowH: for row %d, excessHeight=%d from percent %f\n",
|
||||
i, excessForRow, percent);
|
||||
|
||||
// adjust the height of the row
|
||||
nsSize rowFrameSize;
|
||||
rowFrameToBeResized->GetSize(rowFrameSize);
|
||||
rowFrameToBeResized->SizeTo(rowFrameSize.width, rowHeights[i]);
|
||||
if (gsDebug) printf("TRGF CalcRowH: row %d (%p) sized to %d\n",
|
||||
i, rowFrameToBeResized, rowHeights[i]);
|
||||
}
|
||||
// update the row height
|
||||
rowHeights[i] += excessForRow;
|
||||
|
||||
// if we're dealing with a row below the row containing the spanning cell,
|
||||
// push that row down by the amount we've expanded the cell heights by
|
||||
if ((i >= rowIndex) && (i != 0))
|
||||
{
|
||||
nsRect rowRect;
|
||||
|
||||
rowFrameToBeResized->GetRect(rowRect);
|
||||
nscoord delta=0;
|
||||
for (PRInt32 j=0; j<i; j++)
|
||||
delta += excessForRow[j];
|
||||
if (delta > excessHeight)
|
||||
delta = excessHeight;
|
||||
rowFrameToBeResized->MoveTo(rowRect.x, rowRect.y + delta);
|
||||
if (gsDebug) printf("TRGF CalcRowH: row %d (%p) moved to %d after delta %d\n",
|
||||
i, rowFrameToBeResized, rowRect.y + delta, delta);
|
||||
}
|
||||
// Get the next row frame
|
||||
GetNextRowSibling((nsIFrame**)&rowFrameToBeResized);
|
||||
}
|
||||
delete []excessForRow;
|
||||
NS_ASSERTION(excessAllocated == excessHeight, "excess distribution failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Get the next row child (cell frame)
|
||||
cellFrame->GetNextSibling(&cellFrame);
|
||||
}
|
||||
|
||||
// If this is pass 2 then resize the row to its final size and move the
|
||||
// row's position if the previous rows have caused a shift
|
||||
if (1 == counter) {
|
||||
nsRect rowBounds;
|
||||
rowFrame->GetRect(rowBounds);
|
||||
|
||||
// Move the row to the correct position
|
||||
rowBounds.y += deltaY;
|
||||
|
||||
// Adjust our running delta
|
||||
deltaY += rowHeights[rowIndex] - rowBounds.height;
|
||||
|
||||
// Resize the row to its final size and position
|
||||
rowBounds.height = rowHeights[rowIndex];
|
||||
rowFrame->SetRect(rowBounds);
|
||||
}
|
||||
|
||||
// Update the running row group height
|
||||
rowGroupHeight += rowHeights[rowIndex];
|
||||
rowIndex++;
|
||||
@ -780,23 +787,26 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
|
||||
rowFrame->GetSize(frameSize);
|
||||
rowGroupHeight += frameSize.height;
|
||||
}
|
||||
|
||||
|
||||
// Get the next rowgroup child (row frame)
|
||||
GetNextFrame(rowFrame, &rowFrame);
|
||||
}
|
||||
}
|
||||
|
||||
/* step 3: finally, notify the rows of their new heights */
|
||||
// step 3: notify the rows of their new heights
|
||||
rowFrame = GetFirstFrame();
|
||||
rowIndex = 0;
|
||||
while (nsnull != rowFrame)
|
||||
{
|
||||
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
|
||||
{
|
||||
// Notify the row of the new size
|
||||
((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState);
|
||||
}
|
||||
// Get the next row
|
||||
GetNextFrame(rowFrame, &rowFrame);
|
||||
rowIndex++;
|
||||
}
|
||||
|
||||
// Adjust our desired size
|
||||
@ -806,11 +816,20 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
|
||||
delete []rowHeights;
|
||||
}
|
||||
|
||||
nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext& aPresContext,
|
||||
RowGroupReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nscoord aDeltaY)
|
||||
// Called by IR_TargetIsChild() to adjust the sibling frames that follow
|
||||
// after an incremental reflow of aKidFrame.
|
||||
// This function is not used for paginated mode so we don't need to deal
|
||||
// with continuing frames, and it's only called if aKidFrame has no
|
||||
// cells that span into it and no cells that span across it. That way
|
||||
// we don't have to deal with rowspans
|
||||
nsresult
|
||||
nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext& aPresContext,
|
||||
RowGroupReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nscoord aDeltaY)
|
||||
{
|
||||
NS_PRECONDITION(NS_UNCONSTRAINEDSIZE == aReflowState.reflowState.availableHeight,
|
||||
"we're not in galley mode");
|
||||
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: AdjustSiblingsAfterReflow\n");
|
||||
nsIFrame* lastKidFrame = aKidFrame;
|
||||
|
||||
@ -823,11 +842,12 @@ nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext& aP
|
||||
while (nsnull != kidFrame) {
|
||||
nsPoint origin;
|
||||
|
||||
// XXX We can't just slide the child if it has a next-in-flow
|
||||
// Adjust the y-origin
|
||||
kidFrame->GetOrigin(origin);
|
||||
origin.y += aDeltaY;
|
||||
|
||||
// XXX We need to send move notifications to the frame...
|
||||
// XXX We need to send move notifications to the frame. At least see if
|
||||
// views need to be repositioned
|
||||
nsIHTMLReflow* htmlReflow;
|
||||
if (NS_OK == kidFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) {
|
||||
htmlReflow->WillReflow(aPresContext);
|
||||
@ -844,8 +864,6 @@ nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext& aP
|
||||
lastKidFrame = GetLastFrame();
|
||||
}
|
||||
|
||||
// XXX Deal with cells that have rowspans.
|
||||
|
||||
// Update our running y-offset to reflect the bottommost child
|
||||
nsRect rect;
|
||||
lastKidFrame->GetRect(rect);
|
||||
@ -1125,8 +1143,6 @@ NS_METHOD nsTableRowGroupFrame::IncrementalReflow(nsIPresContext& aPresContext,
|
||||
nsIFrame* nextFrame;
|
||||
aReflowState.reflowState.reflowCommand->GetNext(nextFrame);
|
||||
|
||||
// Recover our reflow state
|
||||
//RecoverState(state, nextFrame);
|
||||
rv = IR_TargetIsChild(aPresContext, aDesiredSize, aReflowState, aStatus, nextFrame);
|
||||
}
|
||||
}
|
||||
@ -1429,6 +1445,51 @@ NS_METHOD nsTableRowGroupFrame::GetHeightOfRows(nscoord& aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Recovers the reflow state to what it should be if aKidFrame is about
|
||||
// to be reflowed. Restores the following:
|
||||
// - availSize
|
||||
// - y
|
||||
// - firstRow
|
||||
nsresult
|
||||
nsTableRowGroupFrame::RecoverState(RowGroupReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame)
|
||||
{
|
||||
// Walk the list of children looking for aKidFrame
|
||||
for (nsIFrame* frame = mFrames.FirstChild(); frame; frame->GetNextSibling(&frame)) {
|
||||
if (frame == aKidFrame) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Update the running y-offset
|
||||
nsSize kidSize;
|
||||
frame->GetSize(kidSize);
|
||||
aReflowState.y += kidSize.height;
|
||||
|
||||
// If our height is constrained then update the available height
|
||||
if (PR_FALSE == aReflowState.unconstrainedHeight) {
|
||||
aReflowState.availSize.height -= kidSize.height;
|
||||
}
|
||||
|
||||
// Update the maximum element size
|
||||
if (aReflowState.firstRow) {
|
||||
aReflowState.firstRow = PR_FALSE;
|
||||
// XXX Today you can't ask for max-element-size when doing an
|
||||
// incremental reflow
|
||||
#if 0
|
||||
if (aMaxElementSize) {
|
||||
aMaxElementSize->width = aKidMaxElementSize.width;
|
||||
aMaxElementSize->height = aKidMaxElementSize.height;
|
||||
}
|
||||
|
||||
} else if (aMaxElementSize) {
|
||||
aMaxElementSize->width = PR_MAX(aMaxElementSize->width, aKidMaxElementSize.width);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableRowGroupFrame::IR_TargetIsChild(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
RowGroupReflowState& aReflowState,
|
||||
@ -1438,35 +1499,53 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsChild(nsIPresContext& aPresConte
|
||||
{
|
||||
nsresult rv;
|
||||
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IR_TargetIsChild\n");
|
||||
// XXX Recover state
|
||||
// Recover the state as if aNextFrame is about to be reflowed
|
||||
RecoverState(aReflowState, aNextFrame);
|
||||
|
||||
// Remember the old rect
|
||||
nsRect oldKidRect;
|
||||
aNextFrame->GetRect(oldKidRect);
|
||||
|
||||
// Pass along the reflow command
|
||||
// XXX Correctly compute the available space...
|
||||
nsSize availSpace(aReflowState.reflowState.availableWidth, aReflowState.reflowState.availableHeight);
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState, aNextFrame, availSpace);
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState,
|
||||
aNextFrame, aReflowState.availSize);
|
||||
nsHTMLReflowMetrics desiredSize(nsnull);
|
||||
|
||||
rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
|
||||
// XXX Check aStatus to see if the frame is complete...
|
||||
|
||||
// Resize the row frame
|
||||
nsRect kidRect;
|
||||
aNextFrame->GetRect(kidRect);
|
||||
aNextFrame->SizeTo(desiredSize.width, desiredSize.height);
|
||||
// Place the row frame
|
||||
nsSize kidMaxElementSize;
|
||||
nsRect kidRect(0, aReflowState.y, desiredSize.width, desiredSize.height);
|
||||
PlaceChild(aPresContext, aReflowState, aNextFrame, kidRect, nsnull,
|
||||
kidMaxElementSize);
|
||||
|
||||
// Adjust the frames that follow...
|
||||
AdjustSiblingsAfterReflow(aPresContext, aReflowState, aNextFrame, desiredSize.height -
|
||||
oldKidRect.height);
|
||||
|
||||
// Return of desired size
|
||||
// See if the table needs a reflow (e.g., if the column widths have
|
||||
// changed). If so, just return and don't bother adjusting the rows
|
||||
// that follow
|
||||
if (!aReflowState.tableFrame->NeedsReflow(aReflowState.reflowState)) {
|
||||
// Inform the row of its new height.
|
||||
PRBool isJustSingleRow = PR_FALSE; /* how to determine this now? */
|
||||
if (isJustSingleRow) {
|
||||
((nsTableRowFrame*)aNextFrame)->DidResize(aPresContext, aReflowState.reflowState);
|
||||
|
||||
// Adjust the frames that follow...
|
||||
AdjustSiblingsAfterReflow(aPresContext, aReflowState, aNextFrame, desiredSize.height -
|
||||
oldKidRect.height);
|
||||
aDesiredSize.height = aReflowState.y;
|
||||
|
||||
} else {
|
||||
// Adjust the frames that follow...
|
||||
AdjustSiblingsAfterReflow(aPresContext, aReflowState, aNextFrame, desiredSize.height -
|
||||
oldKidRect.height);
|
||||
|
||||
// Now recalculate the row heights
|
||||
CalculateRowHeights(aPresContext, aDesiredSize, aReflowState.reflowState);
|
||||
}
|
||||
}
|
||||
|
||||
// Return our desired width
|
||||
aDesiredSize.width = aReflowState.reflowState.availableWidth;
|
||||
aDesiredSize.height = aReflowState.y;
|
||||
|
||||
// XXX If we have a next-in-flow, then we're not complete
|
||||
if (mNextInFlow) {
|
||||
aStatus = NS_FRAME_NOT_COMPLETE;
|
||||
}
|
||||
|
@ -44,9 +44,6 @@ struct RowGroupReflowState {
|
||||
// Flag used to set maxElementSize to my first row
|
||||
PRBool firstRow;
|
||||
|
||||
// Remember the height of the first row, because it's our maxElementHeight (plus header/footers)
|
||||
nscoord firstRowHeight;
|
||||
|
||||
nsTableFrame *tableFrame;
|
||||
|
||||
RowGroupReflowState(nsIPresContext& aPresContext,
|
||||
@ -61,7 +58,6 @@ struct RowGroupReflowState {
|
||||
unconstrainedWidth = PRBool(reflowState.availableWidth == NS_UNCONSTRAINEDSIZE);
|
||||
unconstrainedHeight = PRBool(reflowState.availableHeight == NS_UNCONSTRAINEDSIZE);
|
||||
firstRow = PR_TRUE;
|
||||
firstRowHeight=0;
|
||||
tableFrame = aTableFrame;
|
||||
}
|
||||
|
||||
@ -245,6 +241,9 @@ protected:
|
||||
RowGroupReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nscoord aDeltaY);
|
||||
|
||||
nsresult RecoverState(RowGroupReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame);
|
||||
|
||||
/**
|
||||
* Reflow the frames we've already created
|
||||
|
@ -722,21 +722,6 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext& aPresContext,
|
||||
aDesiredSize.ascent=aDesiredSize.height;
|
||||
aDesiredSize.descent=0;
|
||||
|
||||
// if we got this far with an incremental reflow, the reflow was targeted
|
||||
// at the cell's content. We should only have to redo pass1 for this cell
|
||||
// then rebalance columns. The pass1 is handled by the cell's parent row.
|
||||
// So here all we have to do is tell the table to rebalance.
|
||||
if (eReflowReason_Incremental == aReflowState.reason)
|
||||
{
|
||||
nsTableFrame* tableFrame=nsnull;
|
||||
rv = nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
|
||||
{
|
||||
tableFrame->InvalidateColumnWidths();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
//PostReflowCheck(result);
|
||||
#endif
|
||||
|
@ -2090,7 +2090,7 @@ nsTableFrame::GetSkipSides() const
|
||||
return skip;
|
||||
}
|
||||
|
||||
PRBool nsTableFrame::NeedsReflow(const nsHTMLReflowState& aReflowState, const nsSize& aMaxSize)
|
||||
PRBool nsTableFrame::NeedsReflow(const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
PRBool result = PR_TRUE;
|
||||
|
||||
@ -2115,49 +2115,60 @@ PRBool nsTableFrame::NeedsReflow(const nsHTMLReflowState& aReflowState, const ns
|
||||
//
|
||||
// Slides all the row groups following aKidFrame by the specified
|
||||
// amount
|
||||
//
|
||||
// XXX This is kind of klunky because the InnerTableReflowState::y
|
||||
// data member does not include the table's border/padding...
|
||||
nsresult nsTableFrame::AdjustSiblingsAfterReflow(nsIPresContext& aPresContext,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nscoord aDeltaY)
|
||||
{
|
||||
NS_PRECONDITION(NS_UNCONSTRAINEDSIZE == aReflowState.reflowState.availableHeight,
|
||||
"not in galley mode");
|
||||
nsIFrame* lastKidFrame = aKidFrame;
|
||||
"we're not in galley mode");
|
||||
|
||||
if (aDeltaY != 0) {
|
||||
// Move the frames that follow aKidFrame by aDeltaY
|
||||
// If it's the footer that was reflowed, then we don't need to adjust any of
|
||||
// the frames, because the footer is the bottom most frame
|
||||
if (aKidFrame != aReflowState.footerFrame) {
|
||||
nsIFrame* kidFrame;
|
||||
|
||||
aKidFrame->GetNextSibling(&kidFrame);
|
||||
while (nsnull != kidFrame) {
|
||||
nsPoint origin;
|
||||
nsIHTMLReflow* htmlReflow;
|
||||
nsRect kidRect;
|
||||
PRBool movedFooter = PR_FALSE;
|
||||
|
||||
// XXX We can't just slide the child if it has a next-in-flow
|
||||
kidFrame->GetOrigin(origin);
|
||||
origin.y += aDeltaY;
|
||||
|
||||
// XXX We need to send move notifications to the frame...
|
||||
if (NS_OK == kidFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) {
|
||||
htmlReflow->WillReflow(aPresContext);
|
||||
// Move the frames that follow aKidFrame by aDeltaY, and update the running
|
||||
// y-offset
|
||||
for (aKidFrame->GetNextSibling(&kidFrame); kidFrame; kidFrame->GetNextSibling(&kidFrame)) {
|
||||
// See if it's the footer we're moving
|
||||
if (kidFrame == aReflowState.footerFrame) {
|
||||
movedFooter = PR_TRUE;
|
||||
}
|
||||
|
||||
// Get the frame's bounding rect
|
||||
kidFrame->GetRect(kidRect);
|
||||
|
||||
// Adjust the running y-offset
|
||||
aReflowState.y += kidRect.height;
|
||||
|
||||
// Adjust the y-origin if its position actually changed
|
||||
if (aDeltaY != 0) {
|
||||
kidRect.y += aDeltaY;
|
||||
kidFrame->MoveTo(kidRect.x, kidRect.y);
|
||||
}
|
||||
}
|
||||
|
||||
// We also need to move the footer if there is one and we haven't already
|
||||
// moved it
|
||||
if (aReflowState.footerFrame && !movedFooter) {
|
||||
aReflowState.footerFrame->GetRect(kidRect);
|
||||
|
||||
// Adjust the running y-offset
|
||||
aReflowState.y += kidRect.height;
|
||||
|
||||
if (aDeltaY != 0) {
|
||||
kidRect.y += aDeltaY;
|
||||
aReflowState.footerFrame->MoveTo(kidRect.x, kidRect.y);
|
||||
}
|
||||
kidFrame->MoveTo(origin.x, origin.y);
|
||||
|
||||
// Get the next frame
|
||||
lastKidFrame = kidFrame;
|
||||
kidFrame->GetNextSibling(&kidFrame);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Get the last frame
|
||||
lastKidFrame = mFrames.LastChild();
|
||||
}
|
||||
|
||||
// Update our running y-offset to reflect the bottommost child
|
||||
nsRect rect;
|
||||
lastKidFrame->GetRect(rect);
|
||||
aReflowState.y = rect.YMost();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2253,7 +2264,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
|
||||
}
|
||||
|
||||
// NeedsReflow and IsFirstPassValid take into account reflow type = Initial_Reflow
|
||||
if (PR_TRUE==NeedsReflow(aReflowState, nsSize(aReflowState.availableWidth, aReflowState.availableHeight)))
|
||||
if (PR_TRUE==NeedsReflow(aReflowState))
|
||||
{
|
||||
PRBool needsRecalc=PR_FALSE;
|
||||
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: needs reflow\n");
|
||||
@ -2938,6 +2949,240 @@ NS_METHOD nsTableFrame::GetBorderPlusMarginPadding(nsMargin& aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Sets the starting column index for aColGroupFrame and the siblings frames that
|
||||
// follow
|
||||
void
|
||||
nsTableFrame::SetStartingColumnIndexFor(nsTableColGroupFrame* aColGroupFrame,
|
||||
PRInt32 aIndex)
|
||||
{
|
||||
while (aColGroupFrame) {
|
||||
aIndex += aColGroupFrame->SetStartColumnIndex(aIndex);
|
||||
aColGroupFrame->GetNextSibling((nsIFrame**)&aColGroupFrame);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the starting column index to use for the specified col group frame
|
||||
PRInt32
|
||||
nsTableFrame::CalculateStartingColumnIndexFor(nsTableColGroupFrame* aColGroupFrame)
|
||||
{
|
||||
PRInt32 index = 0;
|
||||
for (nsTableColGroupFrame* colGroupFrame = (nsTableColGroupFrame*)mColGroups.FirstChild();
|
||||
colGroupFrame && (colGroupFrame != aColGroupFrame);
|
||||
colGroupFrame->GetNextSibling((nsIFrame**)&colGroupFrame))
|
||||
{
|
||||
index += colGroupFrame->GetColumnCount();
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTableFrame::AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
PRInt32 startingColIndex = -1;
|
||||
|
||||
// Because we actually have two child lists, one for col group frames and one
|
||||
// for everything else, we need to look at each frame individually
|
||||
nsIFrame* f = aFrameList;
|
||||
while (f) {
|
||||
nsIFrame* next;
|
||||
|
||||
// Get the next frame and disconnect this frame from its sibling
|
||||
f->GetNextSibling(&next);
|
||||
f->SetNextSibling(nsnull);
|
||||
|
||||
// See what kind of frame we have
|
||||
const nsStyleDisplay *display;
|
||||
f->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
|
||||
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) {
|
||||
// Append the new col group frame
|
||||
mColGroups.AppendFrame(nsnull, f);
|
||||
|
||||
// Set its starting column index
|
||||
if (-1 == startingColIndex) {
|
||||
startingColIndex = CalculateStartingColumnIndexFor((nsTableColGroupFrame*)f);
|
||||
}
|
||||
((nsTableColGroupFrame*)f)->SetStartColumnIndex(startingColIndex);
|
||||
startingColIndex += ((nsTableColGroupFrame *)f)->GetColumnCount();
|
||||
|
||||
} else if (IsRowGroup(display->mDisplay)) {
|
||||
// Append the new row group frame
|
||||
mFrames.AppendFrame(nsnull, f);
|
||||
|
||||
// Add the content of the row group to the cell map
|
||||
DidAppendRowGroup((nsTableRowGroupFrame*)f);
|
||||
|
||||
} else {
|
||||
// Nothing special to do, just add the frame to our child list
|
||||
mFrames.AppendFrame(nsnull, f);
|
||||
}
|
||||
|
||||
// Move to the next frame
|
||||
f = next;
|
||||
}
|
||||
|
||||
// We'll need to do a pass-1 layout of all cells in all the rows of the
|
||||
// rowgroup
|
||||
InvalidateFirstPassCache();
|
||||
|
||||
// If we've added any columns, we need to rebuild the column cache.
|
||||
InvalidateColumnCache();
|
||||
|
||||
// Because the number of columns may have changed invalidate the column
|
||||
// cache. Note that this has the side effect of recomputing the column
|
||||
// widths, so we don't need to call InvalidateColumnWidths()
|
||||
InvalidateColumnWidths();
|
||||
|
||||
// Mark the table as dirty and generate a reflow command targeted at the
|
||||
// outer table frame
|
||||
nsIReflowCommand* reflowCmd;
|
||||
nsresult rv;
|
||||
|
||||
mState |= NS_FRAME_IS_DIRTY;
|
||||
rv = NS_NewHTMLReflowCommand(&reflowCmd, mParent, nsIReflowCommand::ReflowDirty);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Add the reflow command
|
||||
rv = aPresShell.AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTableFrame::InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
// Asssume there's only one frame being inserted. The problem is that
|
||||
// row group frames and col group frames go in separate child lists and
|
||||
// so if there's more than one this gets messy...
|
||||
// XXX The frame construction code should be separating out child frames
|
||||
// based on the type...
|
||||
nsIFrame* nextSibling;
|
||||
aFrameList->GetNextSibling(&nextSibling);
|
||||
NS_PRECONDITION(!nextSibling, "expected only one child frame");
|
||||
|
||||
// See what kind of frame we have
|
||||
const nsStyleDisplay *display=nsnull;
|
||||
aFrameList->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
|
||||
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) {
|
||||
// Insert the column group frame
|
||||
mColGroups.InsertFrame(nsnull, aPrevFrame, aFrameList);
|
||||
|
||||
// Set its starting column index and adjust the index of the
|
||||
// col group frames that follow
|
||||
SetStartingColumnIndexFor((nsTableColGroupFrame*)aFrameList,
|
||||
CalculateStartingColumnIndexFor((nsTableColGroupFrame*)aFrameList));
|
||||
|
||||
} else if (IsRowGroup(display->mDisplay)) {
|
||||
// Insert the frame
|
||||
mFrames.InsertFrame(nsnull, aPrevFrame, aFrameList);
|
||||
|
||||
// We'll need to do a pass-1 layout of all cells in all the rows of the
|
||||
// rowgroup
|
||||
InvalidateFirstPassCache();
|
||||
|
||||
// We need to rebuild the cell map, because currently we can't insert
|
||||
// new frames except at the end (append)
|
||||
InvalidateCellMap();
|
||||
|
||||
} else {
|
||||
// Just insert the frame and don't worry about reflowing it
|
||||
mFrames.InsertFrame(nsnull, aPrevFrame, aFrameList);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we've added any columns, we need to rebuild the column cache.
|
||||
InvalidateColumnCache();
|
||||
|
||||
// Because the number of columns may have changed invalidate the column
|
||||
// cache. Note that this has the side effect of recomputing the column
|
||||
// widths, so we don't need to call InvalidateColumnWidths()
|
||||
InvalidateColumnWidths();
|
||||
|
||||
// Mark the table as dirty and generate a reflow command targeted at the
|
||||
// outer table frame
|
||||
nsIReflowCommand* reflowCmd;
|
||||
nsresult rv;
|
||||
|
||||
mState |= NS_FRAME_IS_DIRTY;
|
||||
rv = NS_NewHTMLReflowCommand(&reflowCmd, mParent, nsIReflowCommand::ReflowDirty);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Add the reflow command
|
||||
rv = aPresShell.AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTableFrame::RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame)
|
||||
{
|
||||
// See what kind of frame we have
|
||||
const nsStyleDisplay *display=nsnull;
|
||||
aOldFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
|
||||
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) {
|
||||
nsIFrame* nextColGroupFrame;
|
||||
aOldFrame->GetNextSibling(&nextColGroupFrame);
|
||||
|
||||
// Remove the col group frame
|
||||
mColGroups.DestroyFrame(aPresContext, aOldFrame);
|
||||
|
||||
// Adjust the starting column index of the frames that follow
|
||||
SetStartingColumnIndexFor((nsTableColGroupFrame*)nextColGroupFrame,
|
||||
CalculateStartingColumnIndexFor((nsTableColGroupFrame*)nextColGroupFrame));
|
||||
|
||||
} else if (IsRowGroup(display->mDisplay)) {
|
||||
mFrames.DestroyFrame(aPresContext, aOldFrame);
|
||||
|
||||
// We need to rebuild the cell map, because currently we can't incrementally
|
||||
// remove rows
|
||||
InvalidateCellMap();
|
||||
|
||||
} else {
|
||||
// Just remove the frame
|
||||
mFrames.DestroyFrame(aPresContext, aOldFrame);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Because the number of columns may have changed invalidate the column
|
||||
// cache. Note that this has the side effect of recomputing the column
|
||||
// widths, so we don't need to call InvalidateColumnWidths()
|
||||
InvalidateColumnCache();
|
||||
|
||||
// Because the number of columns may have changed invalidate the column
|
||||
// cache. Note that this has the side effect of recomputing the column
|
||||
// widths, so we don't need to call InvalidateColumnWidths()
|
||||
InvalidateColumnWidths();
|
||||
|
||||
// Mark the table as dirty and generate a reflow command targeted at the
|
||||
// outer table frame
|
||||
nsIReflowCommand* reflowCmd;
|
||||
nsresult rv;
|
||||
|
||||
mState |= NS_FRAME_IS_DIRTY;
|
||||
rv = NS_NewHTMLReflowCommand(&reflowCmd, mParent, nsIReflowCommand::ReflowDirty);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Add the reflow command
|
||||
rv = aPresShell.AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::IncrementalReflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -2946,13 +3191,23 @@ NS_METHOD nsTableFrame::IncrementalReflow(nsIPresContext& aPresContext,
|
||||
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: IncrementalReflow\n");
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Constrain our reflow width to the computed table width. Note: this is
|
||||
// based on the width of the first-in-flow
|
||||
nsHTMLReflowState reflowState(aReflowState);
|
||||
PRInt32 pass1Width = mRect.width;
|
||||
if (mPrevInFlow) {
|
||||
nsTableFrame* table = (nsTableFrame*)GetFirstInFlow();
|
||||
pass1Width = table->mRect.width;
|
||||
}
|
||||
reflowState.availableWidth = pass1Width;
|
||||
|
||||
nsMargin borderPadding;
|
||||
GetBorderPlusMarginPadding(borderPadding);
|
||||
InnerTableReflowState state(aPresContext, aReflowState, borderPadding);
|
||||
InnerTableReflowState state(aPresContext, reflowState, borderPadding);
|
||||
|
||||
// determine if this frame is the target or not
|
||||
nsIFrame *target=nsnull;
|
||||
rv = aReflowState.reflowCommand->GetTarget(target);
|
||||
rv = reflowState.reflowCommand->GetTarget(target);
|
||||
if ((PR_TRUE==NS_SUCCEEDED(rv)) && (nsnull!=target))
|
||||
{
|
||||
// this is the target if target is either this or the outer table frame containing this inner frame
|
||||
@ -2964,10 +3219,9 @@ NS_METHOD nsTableFrame::IncrementalReflow(nsIPresContext& aPresContext,
|
||||
{
|
||||
// Get the next frame in the reflow chain
|
||||
nsIFrame* nextFrame;
|
||||
aReflowState.reflowCommand->GetNext(nextFrame);
|
||||
reflowState.reflowCommand->GetNext(nextFrame);
|
||||
|
||||
// Recover our reflow state
|
||||
//RecoverState(state, nextFrame);
|
||||
rv = IR_TargetIsChild(aPresContext, aDesiredSize, state, aStatus, nextFrame);
|
||||
}
|
||||
}
|
||||
@ -2991,73 +3245,6 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: IncrementalReflow_TargetIsMe with type=%d\n", type);
|
||||
switch (type)
|
||||
{
|
||||
case nsIReflowCommand::FrameInserted :
|
||||
NS_ASSERTION(nsnull!=objectFrame, "bad objectFrame");
|
||||
NS_ASSERTION(nsnull!=childDisplay, "bad childDisplay");
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
||||
{
|
||||
rv = IR_ColGroupInserted(aPresContext, aDesiredSize, aReflowState, aStatus,
|
||||
(nsTableColGroupFrame*)objectFrame, PR_FALSE);
|
||||
}
|
||||
else if (IsRowGroup(childDisplay->mDisplay))
|
||||
{
|
||||
rv = IR_RowGroupInserted(aPresContext, aDesiredSize, aReflowState, aStatus,
|
||||
GetRowGroupFrameFor(objectFrame, childDisplay), PR_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = AddFrame(aReflowState.reflowState, objectFrame);
|
||||
}
|
||||
break;
|
||||
|
||||
case nsIReflowCommand::FrameAppended :
|
||||
if (!objectFrame)
|
||||
break;
|
||||
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
||||
{
|
||||
rv = IR_ColGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus,
|
||||
(nsTableColGroupFrame*)objectFrame);
|
||||
}
|
||||
else if (IsRowGroup(childDisplay->mDisplay))
|
||||
{
|
||||
rv = IR_RowGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus,
|
||||
GetRowGroupFrameFor(objectFrame, childDisplay));
|
||||
}
|
||||
else
|
||||
{ // no optimization to be done for Unknown frame types, so just reuse the Inserted method
|
||||
rv = AddFrame(aReflowState.reflowState, objectFrame);
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
case nsIReflowCommand::FrameReplaced :
|
||||
NS_ASSERTION(nsnull!=objectFrame, "bad objectFrame");
|
||||
NS_ASSERTION(nsnull!=childDisplay, "bad childDisplay");
|
||||
|
||||
*/
|
||||
|
||||
case nsIReflowCommand::FrameRemoved :
|
||||
if (!objectFrame)
|
||||
break;
|
||||
|
||||
NS_ASSERTION(nsnull!=childDisplay, "bad childDisplay");
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
||||
{
|
||||
rv = IR_ColGroupRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
|
||||
(nsTableColGroupFrame*)objectFrame);
|
||||
}
|
||||
else if (IsRowGroup(childDisplay->mDisplay))
|
||||
{
|
||||
rv = IR_RowGroupRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
|
||||
GetRowGroupFrameFor(objectFrame, childDisplay));
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = mFrames.DestroyFrame(aPresContext, objectFrame);
|
||||
}
|
||||
break;
|
||||
|
||||
case nsIReflowCommand::StyleChanged :
|
||||
rv = IR_StyleChanged(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
break;
|
||||
@ -3067,12 +3254,8 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
|
||||
rv = NS_ERROR_ILLEGAL_VALUE;
|
||||
break;
|
||||
|
||||
case nsIReflowCommand::PullupReflow:
|
||||
case nsIReflowCommand::PushReflow:
|
||||
case nsIReflowCommand::CheckPullupReflow :
|
||||
case nsIReflowCommand::UserDefined :
|
||||
default:
|
||||
NS_NOTYETIMPLEMENTED("unimplemented reflow command type");
|
||||
NS_NOTYETIMPLEMENTED("unexpected reflow command type");
|
||||
rv = NS_ERROR_NOT_IMPLEMENTED;
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: reflow command not implemented.\n");
|
||||
break;
|
||||
@ -3081,187 +3264,6 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::IR_ColGroupInserted(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableColGroupFrame * aInsertedFrame,
|
||||
PRBool aReplace)
|
||||
{
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: IR_ColGroupInserted for frame %p\n", aInsertedFrame);
|
||||
nsresult rv=NS_OK;
|
||||
PRBool adjustStartingColIndex=PR_FALSE;
|
||||
PRInt32 startingColIndex=0;
|
||||
// find out what frame to insert aInsertedFrame after
|
||||
nsIFrame *frameToInsertAfter=nsnull;
|
||||
rv = aReflowState.reflowState.reflowCommand->GetPrevSiblingFrame(frameToInsertAfter);
|
||||
// insert aInsertedFrame as the first child. Set its start col index to 0
|
||||
if (nsnull==frameToInsertAfter)
|
||||
{
|
||||
mColGroups.InsertFrame(nsnull, nsnull, aInsertedFrame);
|
||||
startingColIndex += aInsertedFrame->SetStartColumnIndex(0);
|
||||
adjustStartingColIndex=PR_TRUE;
|
||||
}
|
||||
nsIFrame *childFrame=mColGroups.FirstChild();
|
||||
nsIFrame *prevSib=nsnull;
|
||||
while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
|
||||
{
|
||||
if ((nsnull!=frameToInsertAfter) && (childFrame==frameToInsertAfter))
|
||||
{
|
||||
nsIFrame *nextSib=nsnull;
|
||||
frameToInsertAfter->GetNextSibling(&nextSib);
|
||||
aInsertedFrame->SetNextSibling(nextSib);
|
||||
frameToInsertAfter->SetNextSibling(aInsertedFrame);
|
||||
// account for childFrame being a COLGROUP now
|
||||
if (PR_FALSE==adjustStartingColIndex) // we haven't gotten to aDeletedFrame yet
|
||||
startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
|
||||
// skip ahead to aInsertedFrame, since we just handled the frame we inserted after
|
||||
childFrame=aInsertedFrame;
|
||||
adjustStartingColIndex=PR_TRUE; // now that we've inserted aInsertedFrame,
|
||||
// start adjusting subsequent col groups' starting col index including aInsertedFrame
|
||||
}
|
||||
if (PR_FALSE==adjustStartingColIndex) // we haven't gotten to aDeletedFrame yet
|
||||
startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
|
||||
else // we've removed aDeletedFrame, now adjust the starting col index of all subsequent col groups
|
||||
startingColIndex += ((nsTableColGroupFrame *)childFrame)->SetStartColumnIndex(startingColIndex);
|
||||
prevSib=childFrame;
|
||||
rv = childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
|
||||
InvalidateColumnCache();
|
||||
//XXX: what we want to do here is determine if the new COL information changes anything about layout
|
||||
// if not, skip invalidating the first passs
|
||||
// if so, and we can fix the first pass info
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::IR_ColGroupAppended(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableColGroupFrame * aAppendedFrame)
|
||||
{
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: IR_ColGroupAppended for frame %p\n", aAppendedFrame);
|
||||
nsresult rv=NS_OK;
|
||||
PRInt32 startingColIndex=0;
|
||||
nsIFrame *childFrame=mColGroups.FirstChild();
|
||||
nsIFrame *lastChild=childFrame;
|
||||
while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
|
||||
{
|
||||
startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
|
||||
lastChild=childFrame;
|
||||
rv = childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
|
||||
// append aAppendedFrame
|
||||
if (nsnull!=lastChild)
|
||||
lastChild->SetNextSibling(aAppendedFrame);
|
||||
else
|
||||
mColGroups.SetFrames(aAppendedFrame);
|
||||
|
||||
aAppendedFrame->SetStartColumnIndex(startingColIndex);
|
||||
|
||||
#if 0
|
||||
|
||||
we would only want to do this if manufactured col groups were invisible to the DOM. Since they
|
||||
currently are visible, they should behave just as if they were content-backed "real" colgroups
|
||||
If this decision is changed, the code below is a half-finished attempt to rationalize the situation.
|
||||
It requires having built a list of the colGroups before we get to this point.
|
||||
|
||||
// look at the last col group. If it is implicit, and it's cols are implicit, then
|
||||
// it and its cols were manufactured for table layout.
|
||||
// Delete it if possible, otherwise move it to the end of the list
|
||||
|
||||
if (0<colGroupCount)
|
||||
{
|
||||
nsTableColGroupFrame *colGroup = (nsTableColGroupFrame *)(colGroupList.ElementAt(colGroupCount-1));
|
||||
if (PR_TRUE==colGroup->IsManufactured())
|
||||
{ // account for the new COLs that were added in aAppendedFrame
|
||||
// first, try to delete the implicit colgroup
|
||||
|
||||
// if we couldn't delete it, move the implicit colgroup to the end of the list
|
||||
// and adjust it's col indexes
|
||||
nsIFrame *colGroupNextSib;
|
||||
colGroup->GetNextSibling(colGroupNextSib);
|
||||
childFrame=mColGroups.FirstChild();
|
||||
nsIFrame * prevSib=nsnull;
|
||||
rv = NS_OK;
|
||||
while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
|
||||
{
|
||||
if (childFrame==colGroup)
|
||||
{
|
||||
if (nsnull!=prevSib) // colGroup is in the middle of the list, remove it
|
||||
prevSib->SetNextSibling(colGroupNextSib);
|
||||
else // colGroup was the first child, so set it's next sib to first child
|
||||
mColGroups.SetFrames(colGroupNextSib);
|
||||
aAppendedFrame->SetNextSibling(colGroup); // place colGroup at the end of the list
|
||||
colGroup->SetNextSibling(nsnull);
|
||||
break;
|
||||
}
|
||||
prevSib=childFrame;
|
||||
rv = childFrame->GetNextSibling(childFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
InvalidateColumnCache();
|
||||
//XXX: what we want to do here is determine if the new COL information changes anything about layout
|
||||
// if not, skip invalidating the first passs
|
||||
// if so, and we can fix the first pass info
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_METHOD nsTableFrame::IR_ColGroupRemoved(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableColGroupFrame * aDeletedFrame)
|
||||
{
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: IR_ColGroupRemoved for frame %p\n", aDeletedFrame);
|
||||
nsresult rv=NS_OK;
|
||||
PRBool adjustStartingColIndex=PR_FALSE;
|
||||
PRInt32 startingColIndex=0;
|
||||
nsIFrame *childFrame=mColGroups.FirstChild();
|
||||
nsIFrame *prevSib=nsnull;
|
||||
while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
|
||||
{
|
||||
if (childFrame==aDeletedFrame)
|
||||
{
|
||||
nsIFrame *deleteFrameNextSib=nsnull;
|
||||
aDeletedFrame->GetNextSibling(&deleteFrameNextSib);
|
||||
if (nsnull!=prevSib)
|
||||
prevSib->SetNextSibling(deleteFrameNextSib);
|
||||
else
|
||||
mColGroups.SetFrames(deleteFrameNextSib);
|
||||
childFrame=deleteFrameNextSib;
|
||||
if (nsnull==childFrame)
|
||||
break;
|
||||
adjustStartingColIndex=PR_TRUE; // now that we've removed aDeletedFrame, start adjusting subsequent col groups' starting col index
|
||||
}
|
||||
const nsStyleDisplay *display;
|
||||
childFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)display);
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay)
|
||||
{
|
||||
if (PR_FALSE==adjustStartingColIndex) // we haven't gotten to aDeletedFrame yet
|
||||
startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
|
||||
else // we've removed aDeletedFrame, now adjust the starting col index of all subsequent col groups
|
||||
startingColIndex += ((nsTableColGroupFrame *)childFrame)->SetStartColumnIndex(startingColIndex);
|
||||
}
|
||||
prevSib=childFrame;
|
||||
rv = childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
|
||||
InvalidateColumnCache();
|
||||
//XXX: what we want to do here is determine if the new COL information changes anything about layout
|
||||
// if not, skip invalidating the first passs
|
||||
// if so, and we can fix the first pass info
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::IR_StyleChanged(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
@ -3277,85 +3279,69 @@ NS_METHOD nsTableFrame::IR_StyleChanged(nsIPresContext& aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::IR_RowGroupInserted(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableRowGroupFrame * aInsertedFrame,
|
||||
PRBool aReplace)
|
||||
// Recovers the reflow state to what it should be if aKidFrame is about
|
||||
// to be reflowed. Restores the following:
|
||||
// - availSize
|
||||
// - y
|
||||
// - footerFrame
|
||||
// - firstBodySection
|
||||
//
|
||||
// In the case of the footer frame the y-offset is set to its current
|
||||
// y-offset. Note that this is different from resize reflow when the
|
||||
// footer is positioned higher up and then moves down as each row
|
||||
// group frame is relowed
|
||||
//
|
||||
// XXX This is kind of klunky because the InnerTableReflowState::y
|
||||
// data member does not include the table's border/padding...
|
||||
nsresult
|
||||
nsTableFrame::RecoverState(InnerTableReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame)
|
||||
{
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: IR_RowGroupInserted for frame %p\n", aInsertedFrame);
|
||||
nsresult rv = AddFrame(aReflowState.reflowState, aInsertedFrame);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// do a pass-1 layout of all the cells in all the rows of the rowgroup
|
||||
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState.reflowState, aStatus,
|
||||
aInsertedFrame, eReflowReason_Initial, PR_FALSE);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
// Walk the list of children looking for aKidFrame
|
||||
for (nsIFrame* frame = mFrames.FirstChild(); frame; frame->GetNextSibling(&frame)) {
|
||||
// If this is a footer row group, remember it
|
||||
const nsStyleDisplay *display;
|
||||
frame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
|
||||
|
||||
InvalidateCellMap();
|
||||
InvalidateColumnCache();
|
||||
// We only allow a single footer frame, and the footer frame must occur before
|
||||
// any body section row groups
|
||||
if ((NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == display->mDisplay) &&
|
||||
!aReflowState.footerFrame && !aReflowState.firstBodySection) {
|
||||
aReflowState.footerFrame = frame;
|
||||
|
||||
} else if ((NS_STYLE_DISPLAY_TABLE_ROW_GROUP == display->mDisplay) &&
|
||||
!aReflowState.firstBodySection) {
|
||||
aReflowState.firstBodySection = frame;
|
||||
}
|
||||
|
||||
// See if this is the frame we're looking for
|
||||
if (frame == aKidFrame) {
|
||||
// If it's the footer, then keep going because the footer is at the
|
||||
// very bottom
|
||||
if (frame != aReflowState.footerFrame) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
// Get the frame's height
|
||||
nsSize kidSize;
|
||||
frame->GetSize(kidSize);
|
||||
|
||||
// If our height is constrained then update the available height. Do
|
||||
// this for all frames including the footer frame
|
||||
if (PR_FALSE == aReflowState.unconstrainedHeight) {
|
||||
aReflowState.availSize.height -= kidSize.height;
|
||||
}
|
||||
|
||||
// Update the running y-offset. Don't do this for the footer frame
|
||||
if (frame != aReflowState.footerFrame) {
|
||||
aReflowState.y += kidSize.height;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// since we know we're doing an append here, we can optimize
|
||||
NS_METHOD nsTableFrame::IR_RowGroupAppended(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableRowGroupFrame * aAppendedFrame)
|
||||
{
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: IR_RowGroupAppended for frame %p\n", aAppendedFrame);
|
||||
// hook aAppendedFrame into the child list
|
||||
nsresult rv = AddFrame(aReflowState.reflowState, aAppendedFrame);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// account for the cells in the rows that are children of aAppendedFrame
|
||||
// this will add the content of the rowgroup to the cell map
|
||||
rv = DidAppendRowGroup(aAppendedFrame);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// do a pass-1 layout of all the cells in all the rows of the rowgroup
|
||||
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState.reflowState, aStatus,
|
||||
aAppendedFrame, eReflowReason_Initial, PR_TRUE);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// if we've added any columns, we need to rebuild the column cache
|
||||
// XXX: it would be nice to have a mechanism to just extend the column cache, rather than rebuild it completely
|
||||
InvalidateColumnCache();
|
||||
|
||||
// if any column widths have to change due to this, rebalance column widths
|
||||
//XXX need to calculate this, but for now just do it
|
||||
InvalidateColumnWidths();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::IR_RowGroupRemoved(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableRowGroupFrame * aDeletedFrame)
|
||||
{
|
||||
if (PR_TRUE==gsDebugIR) printf("TIF IR: IR_RowGroupRemoved for frame %p\n", aDeletedFrame);
|
||||
nsresult rv = mFrames.DestroyFrame(aPresContext, aDeletedFrame);
|
||||
InvalidateCellMap();
|
||||
InvalidateColumnCache();
|
||||
|
||||
// if any column widths have to change due to this, rebalance column widths
|
||||
//XXX need to calculate this, but for now just do it
|
||||
InvalidateColumnWidths();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_METHOD nsTableFrame::IR_TargetIsChild(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
@ -3365,6 +3351,8 @@ NS_METHOD nsTableFrame::IR_TargetIsChild(nsIPresContext& aPresContext,
|
||||
{
|
||||
nsresult rv;
|
||||
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: IR_TargetIsChild\n");
|
||||
// Recover the state as if aNextFrame is about to be reflowed
|
||||
RecoverState(aReflowState, aNextFrame);
|
||||
|
||||
// Remember the old rect
|
||||
nsRect oldKidRect;
|
||||
@ -3372,24 +3360,31 @@ NS_METHOD nsTableFrame::IR_TargetIsChild(nsIPresContext& aPresContext,
|
||||
|
||||
// Pass along the reflow command
|
||||
nsHTMLReflowMetrics desiredSize(nsnull);
|
||||
// XXX Correctly compute the available space...
|
||||
nsSize availSpace(aReflowState.reflowState.availableWidth, aReflowState.reflowState.availableHeight);
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState,
|
||||
aNextFrame, availSpace);
|
||||
aNextFrame, aReflowState.availSize);
|
||||
|
||||
rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
|
||||
|
||||
// Resize the row group frame
|
||||
nsRect kidRect;
|
||||
aNextFrame->GetRect(kidRect);
|
||||
aNextFrame->SizeTo(desiredSize.width, desiredSize.height);
|
||||
// Place the row group frame. Don't use PlaceChild(), because it moves
|
||||
// the footer frame as well. We'll adjust the footer frame later on in
|
||||
// AdjustSiblingsAfterReflow()
|
||||
nscoord x = aReflowState.mBorderPadding.left;
|
||||
nscoord y = aReflowState.mBorderPadding.top + aReflowState.y;
|
||||
nsRect kidRect(x, y, desiredSize.width, desiredSize.height);
|
||||
aNextFrame->SetRect(kidRect);
|
||||
|
||||
// Adjust the running y-offset
|
||||
aReflowState.y += kidRect.height;
|
||||
|
||||
// If our height is constrained, then update the available height
|
||||
if (PR_FALSE == aReflowState.unconstrainedHeight) {
|
||||
aReflowState.availSize.height -= kidRect.height;
|
||||
}
|
||||
|
||||
// If the column width info is valid, then adjust the row group frames
|
||||
// that follow. Otherwise, return and we'll recompute the column widths
|
||||
// and reflow all the row group frames
|
||||
if (!NeedsReflow(aReflowState.reflowState,
|
||||
nsSize(aReflowState.reflowState.availableWidth,
|
||||
aReflowState.reflowState.availableHeight))) {
|
||||
if (!NeedsReflow(aReflowState.reflowState)) {
|
||||
// Adjust the row groups that follow
|
||||
AdjustSiblingsAfterReflow(aPresContext, aReflowState, aNextFrame, desiredSize.height -
|
||||
oldKidRect.height);
|
||||
|
@ -95,6 +95,20 @@ public:
|
||||
/** @see nsIFrame::Destroy */
|
||||
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
|
||||
|
||||
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList);
|
||||
NS_IMETHOD InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList);
|
||||
NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame);
|
||||
|
||||
/** helper method to find the table parent of any table frame object */
|
||||
// TODO: today, this depends on display types. This should be changed to rely
|
||||
// on stronger criteria, like an inner table frame atom
|
||||
@ -439,6 +453,14 @@ protected:
|
||||
* @return PR_TRUE if this table is nested inside another table.
|
||||
*/
|
||||
PRBool IsNested(const nsHTMLReflowState& aReflowState, const nsStylePosition *& aPosition) const;
|
||||
|
||||
// Sets the starting column index for aColGroupFrame and the siblings frames that
|
||||
// follow
|
||||
void SetStartingColumnIndexFor(nsTableColGroupFrame* aColGroupFrame,
|
||||
PRInt32 aIndex);
|
||||
|
||||
// Calculate the starting column index to use for the specified col group frame
|
||||
PRInt32 CalculateStartingColumnIndexFor(nsTableColGroupFrame* aColGroupFrame);
|
||||
|
||||
public:
|
||||
/** first pass of ResizeReflow.
|
||||
@ -463,6 +485,9 @@ public:
|
||||
NS_IMETHOD GetTableSpecifiedHeight(nscoord& aHeight, const nsHTMLReflowState& aReflowState);
|
||||
virtual PRBool RowGroupsShouldBeConstrained() { return PR_FALSE; }
|
||||
|
||||
/** do I need to do a reflow? */
|
||||
virtual PRBool NeedsReflow(const nsHTMLReflowState& aReflowState);
|
||||
|
||||
protected:
|
||||
/** second pass of ResizeReflow.
|
||||
* lays out all table content with aMaxSize(computed_table_width, given_table_height)
|
||||
@ -509,72 +534,6 @@ protected:
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
/** process a colgroup inserted notification
|
||||
* @param aInsertedFrame the new colgroup frame
|
||||
* @param aReplace PR_TRUE if aInsertedFrame is replacing an existing frame
|
||||
* Not Yet Implemented.
|
||||
* @see nsIFrameReflow::Reflow
|
||||
*/
|
||||
NS_IMETHOD IR_ColGroupInserted(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableColGroupFrame * aInsertedFrame,
|
||||
PRBool aReplace);
|
||||
|
||||
/** process a colgroup appended notification. This method is optimized for append.
|
||||
* @param aAppendedFrame the new colgroup frame
|
||||
* @see nsIFrameReflow::Reflow
|
||||
*/
|
||||
NS_IMETHOD IR_ColGroupAppended(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableColGroupFrame * aAppendedFrame);
|
||||
|
||||
/** process a colgroup removed notification.
|
||||
* @param aDeletedFrame the colgroup frame to remove
|
||||
* @see nsIFrameReflow::Reflow
|
||||
*/
|
||||
NS_IMETHOD IR_ColGroupRemoved(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableColGroupFrame * aDeletedFrame);
|
||||
|
||||
/** process a rowgroup inserted notification
|
||||
* @param aInsertedFrame the new rowgroup frame
|
||||
* @param aReplace PR_TRUE if aInsertedFrame is replacing an existing frame
|
||||
* Not Yet Implemented.
|
||||
* @see nsIFrameReflow::Reflow
|
||||
*/
|
||||
NS_IMETHOD IR_RowGroupInserted(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableRowGroupFrame * aInsertedFrame,
|
||||
PRBool aReplace);
|
||||
|
||||
/** process a rowgroup appended notification. This method is optimized for append.
|
||||
* @param aAppendedFrame the new rowgroup frame
|
||||
* @see nsIFrameReflow::Reflow
|
||||
*/
|
||||
NS_IMETHOD IR_RowGroupAppended(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableRowGroupFrame * aAppendedFrame);
|
||||
|
||||
/** process a rowgroup removed notification.
|
||||
* @param aDeletedFrame the rowgroup frame to remove
|
||||
* @see nsIFrameReflow::Reflow
|
||||
*/
|
||||
NS_IMETHOD IR_RowGroupRemoved(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsTableRowGroupFrame * aDeletedFrame);
|
||||
|
||||
/** process a style chnaged notification.
|
||||
* @see nsIFrameReflow::Reflow
|
||||
* TODO: needs to be optimized for which attribute was actually changed.
|
||||
@ -588,6 +547,9 @@ protected:
|
||||
InnerTableReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nscoord aDeltaY);
|
||||
|
||||
nsresult RecoverState(InnerTableReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame);
|
||||
|
||||
NS_METHOD AdjustForCollapsingRowGroup(nsIFrame* aRowGroupFrame,
|
||||
PRInt32& aRowX);
|
||||
@ -676,10 +638,6 @@ protected:
|
||||
/** sets the width of the table according to the computed widths of each column. */
|
||||
virtual void SetTableWidth(nsIPresContext& aPresContext);
|
||||
|
||||
/** given the new parent size, do I really need to do a reflow? */
|
||||
virtual PRBool NeedsReflow(const nsHTMLReflowState& aReflowState,
|
||||
const nsSize& aMaxSize);
|
||||
|
||||
/** returns PR_TRUE if the cached pass 1 data is still valid */
|
||||
virtual PRBool IsFirstPassValid() const;
|
||||
|
||||
|
@ -337,11 +337,11 @@ NS_IMETHODIMP nsTableOuterFrame::SetSelected(nsIDOMRange *aRange,PRBool aSelecte
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool nsTableOuterFrame::NeedsReflow(const nsHTMLReflowState& aReflowState, const nsSize& aMaxSize)
|
||||
PRBool nsTableOuterFrame::NeedsReflow(const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
PRBool result=PR_TRUE;
|
||||
if (nsnull != mInnerTableFrame) {
|
||||
result = ((nsTableFrame *)mInnerTableFrame)->NeedsReflow(aReflowState, aMaxSize);
|
||||
result = ((nsTableFrame *)mInnerTableFrame)->NeedsReflow(aReflowState);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ protected:
|
||||
* or if the table style attributes or parent max height/width have
|
||||
* changed.
|
||||
*/
|
||||
PRBool NeedsReflow(const nsHTMLReflowState& aReflowState, const nsSize& aMaxSize);
|
||||
PRBool NeedsReflow(const nsHTMLReflowState& aReflowState);
|
||||
|
||||
/** position the child frame
|
||||
* @param aReflowState the state of the reflow process
|
||||
|
@ -1373,26 +1373,29 @@ NS_METHOD nsTableRowFrame::IR_TargetIsChild(nsIPresContext& aPresContext,
|
||||
// size.
|
||||
// XXX It would be nice if we could skip this step and the next step if the
|
||||
// column width isn't dependent on the max cell width...
|
||||
kidReflowState.reason = eReflowReason_Initial;
|
||||
kidReflowState.reflowCommand = nsnull;
|
||||
kidReflowState.availableWidth = NS_UNCONSTRAINEDSIZE;
|
||||
rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
|
||||
if (gsDebug)
|
||||
printf ("TR %p for cell %p Incremental Reflow: desired=%d, MES=%d\n",
|
||||
this, aNextFrame, desiredSize.width, kidMaxElementSize.width);
|
||||
// Update the cell layout data.
|
||||
//XXX: this is a hack, shouldn't it be the case that a min size is
|
||||
// never larger than a desired size?
|
||||
if (kidMaxElementSize.width>desiredSize.width)
|
||||
desiredSize.width = kidMaxElementSize.width;
|
||||
if (kidMaxElementSize.height>desiredSize.height)
|
||||
desiredSize.height = kidMaxElementSize.height;
|
||||
((nsTableCellFrame *)aNextFrame)->SetPass1DesiredSize(desiredSize);
|
||||
((nsTableCellFrame *)aNextFrame)->SetPass1MaxElementSize(kidMaxElementSize);
|
||||
// Now reflow the cell again this time constraining the width
|
||||
// XXX Ignore for now the possibility that the column width has changed...
|
||||
kidReflowState.availableWidth = availWidth;
|
||||
rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
|
||||
if (aReflowState.tableFrame->RequiresPass1Layout()) {
|
||||
kidReflowState.reason = eReflowReason_Initial;
|
||||
kidReflowState.reflowCommand = nsnull;
|
||||
kidReflowState.availableWidth = NS_UNCONSTRAINEDSIZE;
|
||||
rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
|
||||
if (gsDebug)
|
||||
printf ("TR %p for cell %p Incremental Reflow: desired=%d, MES=%d\n",
|
||||
this, aNextFrame, desiredSize.width, kidMaxElementSize.width);
|
||||
// Update the cell layout data.
|
||||
//XXX: this is a hack, shouldn't it be the case that a min size is
|
||||
// never larger than a desired size?
|
||||
if (kidMaxElementSize.width>desiredSize.width)
|
||||
desiredSize.width = kidMaxElementSize.width;
|
||||
if (kidMaxElementSize.height>desiredSize.height)
|
||||
desiredSize.height = kidMaxElementSize.height;
|
||||
((nsTableCellFrame *)aNextFrame)->SetPass1DesiredSize(desiredSize);
|
||||
((nsTableCellFrame *)aNextFrame)->SetPass1MaxElementSize(kidMaxElementSize);
|
||||
|
||||
// Now reflow the cell again this time constraining the width
|
||||
// XXX Ignore for now the possibility that the column width has changed...
|
||||
kidReflowState.availableWidth = availWidth;
|
||||
rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
|
||||
}
|
||||
|
||||
// Place the child after taking into account it's margin and attributes
|
||||
// XXX We need to ask the table (or the table layout strategy) if the column
|
||||
@ -1434,6 +1437,12 @@ NS_METHOD nsTableRowFrame::IR_TargetIsChild(nsIPresContext& aPresContext,
|
||||
|
||||
SetMaxChildHeight(aReflowState.maxCellHeight, maxCellTopMargin, maxCellBottomMargin);
|
||||
|
||||
// If the column widths have changed, then tell the table to rebalance
|
||||
// the column widths
|
||||
if (aReflowState.tableFrame->RequiresPass1Layout()) {
|
||||
aReflowState.tableFrame->InvalidateColumnWidths();
|
||||
}
|
||||
|
||||
// Return our desired size. Note that our desired width is just whatever width
|
||||
// we were given by the row group frame
|
||||
aDesiredSize.width = aReflowState.availSize.width;
|
||||
|
@ -361,7 +361,6 @@ void nsTableRowGroupFrame::PlaceChild(nsIPresContext& aPresContext,
|
||||
if (PR_TRUE==aReflowState.firstRow)
|
||||
{
|
||||
aReflowState.firstRow = PR_FALSE;
|
||||
aReflowState.firstRowHeight = aKidRect.height;
|
||||
if (nsnull != aMaxElementSize) {
|
||||
aMaxElementSize->width = aKidMaxElementSize.width;
|
||||
aMaxElementSize->height = aKidMaxElementSize.height;
|
||||
@ -597,14 +596,15 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
|
||||
// all table cells have the same top and bottom margins, namely cellSpacingY
|
||||
nscoord cellSpacingY = tableFrame->GetCellSpacingY();
|
||||
|
||||
// iterate children and for each row get its height
|
||||
// iterate children and for each row get the height of the tallest cell
|
||||
PRInt32 numRows;
|
||||
GetRowCount(numRows, PR_FALSE);
|
||||
PRInt32 *rowHeights = new PRInt32[numRows];
|
||||
nsCRT::memset (rowHeights, 0, numRows*sizeof(PRInt32));
|
||||
nscoord *rowHeights = new nscoord[numRows];
|
||||
nsCRT::memset (rowHeights, 0, numRows*sizeof(nscoord));
|
||||
|
||||
/* Step 1: get the height of the tallest cell in the row and save it for
|
||||
* pass 2
|
||||
* pass 2. This height is for table cells that originate in this
|
||||
* row and that don't span into the rows that follow
|
||||
*/
|
||||
nsIFrame* rowFrame = GetFirstFrame();
|
||||
PRInt32 rowIndex = 0;
|
||||
@ -649,7 +649,7 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
|
||||
* If the cell's desired height is the larger value, resize the rows and contained
|
||||
* cells by an equal percentage of the additional space.
|
||||
* We go through this loop twice. The first time, we are adjusting cell heights
|
||||
* and row y-offsets on the fly.
|
||||
* on the fly.
|
||||
* The second time through the loop, we're ensuring that subsequent row-spanning cells
|
||||
* didn't change prior calculations.
|
||||
* Since we are guaranteed to have found the max height spanners the first time through,
|
||||
@ -661,6 +661,7 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
|
||||
*/
|
||||
|
||||
PRInt32 rowGroupHeight;
|
||||
nscoord deltaY = 0;
|
||||
for (PRInt32 counter=0; counter<2; counter++)
|
||||
{
|
||||
rowGroupHeight = 0;
|
||||
@ -686,90 +687,96 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
|
||||
PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(rowIndex + startRowIndex,
|
||||
(nsTableCellFrame*)cellFrame);
|
||||
if (rowSpan > 1)
|
||||
{ // found a cell with rowspan > 1, determine its height
|
||||
{ // found a cell with rowspan > 1, determine the height of the rows it
|
||||
// spans
|
||||
if (gsDebug) printf("TRGF CalcRowH: cell %p has rowspan=%d\n", cellFrame, rowSpan);
|
||||
nscoord heightOfRowsSpanned = 0;
|
||||
PRInt32 i;
|
||||
for (i = 0; i < rowSpan; i++) {
|
||||
heightOfRowsSpanned += rowHeights[rowIndex + i];
|
||||
}
|
||||
// the avail height needs to reduce by top and bottom margins
|
||||
// reduce the height by top and bottom margins
|
||||
nscoord availHeightOfRowsSpanned = heightOfRowsSpanned - cellSpacingY - cellSpacingY;
|
||||
if (gsDebug) printf("TRGF CalcRowH: availHeightOfRowsSpanned=%d\n", availHeightOfRowsSpanned);
|
||||
/* if the cell height fits in the rows, expand the spanning cell's height and slap it in */
|
||||
|
||||
// see if the cell's height fits within the rows it spans. If this is
|
||||
// pass 1 then use the cell's desired height and not the current height
|
||||
// of its frame. That way this works for incremental reflow, too
|
||||
nsSize cellFrameSize;
|
||||
cellFrame->GetSize(cellFrameSize);
|
||||
if (availHeightOfRowsSpanned > cellFrameSize.height)
|
||||
if (0 == counter) {
|
||||
nsSize cellDesiredSize = ((nsTableCellFrame*)cellFrame)->GetDesiredSize();
|
||||
cellFrameSize.height = cellDesiredSize.height;
|
||||
}
|
||||
|
||||
if (availHeightOfRowsSpanned >= cellFrameSize.height)
|
||||
{
|
||||
// yes the cell's height fits with the available space of the rows it
|
||||
// spans. Set the cell frame's height
|
||||
if (gsDebug) printf("TRGF CalcRowH: spanning cell fits in rows spanned, had h=%d, expanded to %d\n",
|
||||
cellFrameSize.height, availHeightOfRowsSpanned);
|
||||
cellFrame->SizeTo(cellFrameSize.width, availHeightOfRowsSpanned);
|
||||
// Realign cell content based on new height
|
||||
((nsTableCellFrame*)cellFrame)->VerticallyAlignChild();
|
||||
}
|
||||
/* otherwise, distribute the excess height to the rows effected.
|
||||
* push all subsequent rows down by the total change in height of all the rows above it
|
||||
*/
|
||||
else
|
||||
{
|
||||
// the cell's height is larger than the available space of the rows it
|
||||
// spans so distribute the excess height to the rows affected
|
||||
PRInt32 excessHeight = cellFrameSize.height - availHeightOfRowsSpanned;
|
||||
if (gsDebug) printf("TRGF CalcRowH: excessHeight=%d\n", excessHeight);
|
||||
// for every row starting at the row with the spanning cell...
|
||||
|
||||
// for every row starting at the row with the spanning cell and down
|
||||
// to the last row spanned by the cell
|
||||
nsTableRowFrame *rowFrameToBeResized = (nsTableRowFrame *)rowFrame;
|
||||
PRInt32 *excessForRow = new PRInt32[numRows];
|
||||
nsCRT::memset (excessForRow, 0, numRows*sizeof(PRInt32));
|
||||
nscoord excessAllocated = 0;
|
||||
for (i = rowIndex; i < numRows; i++) {
|
||||
for (i = rowIndex; i < (rowIndex + rowSpan); i++) {
|
||||
if (gsDebug) printf("TRGF CalcRowH: for row index=%d\n", i);
|
||||
// if the row is within the spanned range, resize the row
|
||||
if (i < (rowIndex + rowSpan)) {
|
||||
//float percent = ((float)rowHeights[i]) / ((float)availHeightOfRowsSpanned);
|
||||
//excessForRow[i] = NSToCoordRound(((float)(excessHeight)) * percent);
|
||||
float percent = ((float)rowHeights[i]) / ((float)heightOfRowsSpanned);
|
||||
// give rows their percentage, except the last row gets the remainder
|
||||
excessForRow[i] = ((i - 1) == (rowIndex + rowSpan))
|
||||
? excessHeight - excessAllocated
|
||||
: NSToCoordRound(((float)(excessHeight)) * percent);
|
||||
excessAllocated += excessForRow[i];
|
||||
if (gsDebug) printf("TRGF CalcRowH: for row %d, excessHeight=%d from percent %f\n",
|
||||
i, excessForRow[i], percent);
|
||||
// update the row height
|
||||
rowHeights[i] += excessForRow[i];
|
||||
// The amount of additional space each row gets is based on the
|
||||
// percentage of space it occupies, i.e. they don't all get the
|
||||
// same amount of available space
|
||||
float percent = ((float)rowHeights[i]) / ((float)heightOfRowsSpanned);
|
||||
|
||||
// give rows their percentage, except for the last row which gets
|
||||
// the remainder
|
||||
nscoord excessForRow = ((i + 1) == (rowIndex + rowSpan)) ?
|
||||
excessHeight - excessAllocated :
|
||||
NSToCoordRound(((float)(excessHeight)) * percent);
|
||||
excessAllocated += excessForRow;
|
||||
if (gsDebug) printf("TRGF CalcRowH: for row %d, excessHeight=%d from percent %f\n",
|
||||
i, excessForRow, percent);
|
||||
|
||||
// adjust the height of the row
|
||||
nsSize rowFrameSize;
|
||||
rowFrameToBeResized->GetSize(rowFrameSize);
|
||||
rowFrameToBeResized->SizeTo(rowFrameSize.width, rowHeights[i]);
|
||||
if (gsDebug) printf("TRGF CalcRowH: row %d (%p) sized to %d\n",
|
||||
i, rowFrameToBeResized, rowHeights[i]);
|
||||
}
|
||||
// update the row height
|
||||
rowHeights[i] += excessForRow;
|
||||
|
||||
// if we're dealing with a row below the row containing the spanning cell,
|
||||
// push that row down by the amount we've expanded the cell heights by
|
||||
if ((i >= rowIndex) && (i != 0))
|
||||
{
|
||||
nsRect rowRect;
|
||||
|
||||
rowFrameToBeResized->GetRect(rowRect);
|
||||
nscoord delta=0;
|
||||
for (PRInt32 j=0; j<i; j++)
|
||||
delta += excessForRow[j];
|
||||
if (delta > excessHeight)
|
||||
delta = excessHeight;
|
||||
rowFrameToBeResized->MoveTo(rowRect.x, rowRect.y + delta);
|
||||
if (gsDebug) printf("TRGF CalcRowH: row %d (%p) moved to %d after delta %d\n",
|
||||
i, rowFrameToBeResized, rowRect.y + delta, delta);
|
||||
}
|
||||
// Get the next row frame
|
||||
GetNextRowSibling((nsIFrame**)&rowFrameToBeResized);
|
||||
}
|
||||
delete []excessForRow;
|
||||
NS_ASSERTION(excessAllocated == excessHeight, "excess distribution failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Get the next row child (cell frame)
|
||||
cellFrame->GetNextSibling(&cellFrame);
|
||||
}
|
||||
|
||||
// If this is pass 2 then resize the row to its final size and move the
|
||||
// row's position if the previous rows have caused a shift
|
||||
if (1 == counter) {
|
||||
nsRect rowBounds;
|
||||
rowFrame->GetRect(rowBounds);
|
||||
|
||||
// Move the row to the correct position
|
||||
rowBounds.y += deltaY;
|
||||
|
||||
// Adjust our running delta
|
||||
deltaY += rowHeights[rowIndex] - rowBounds.height;
|
||||
|
||||
// Resize the row to its final size and position
|
||||
rowBounds.height = rowHeights[rowIndex];
|
||||
rowFrame->SetRect(rowBounds);
|
||||
}
|
||||
|
||||
// Update the running row group height
|
||||
rowGroupHeight += rowHeights[rowIndex];
|
||||
rowIndex++;
|
||||
@ -780,23 +787,26 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
|
||||
rowFrame->GetSize(frameSize);
|
||||
rowGroupHeight += frameSize.height;
|
||||
}
|
||||
|
||||
|
||||
// Get the next rowgroup child (row frame)
|
||||
GetNextFrame(rowFrame, &rowFrame);
|
||||
}
|
||||
}
|
||||
|
||||
/* step 3: finally, notify the rows of their new heights */
|
||||
// step 3: notify the rows of their new heights
|
||||
rowFrame = GetFirstFrame();
|
||||
rowIndex = 0;
|
||||
while (nsnull != rowFrame)
|
||||
{
|
||||
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
|
||||
{
|
||||
// Notify the row of the new size
|
||||
((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState);
|
||||
}
|
||||
// Get the next row
|
||||
GetNextFrame(rowFrame, &rowFrame);
|
||||
rowIndex++;
|
||||
}
|
||||
|
||||
// Adjust our desired size
|
||||
@ -806,11 +816,20 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
|
||||
delete []rowHeights;
|
||||
}
|
||||
|
||||
nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext& aPresContext,
|
||||
RowGroupReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nscoord aDeltaY)
|
||||
// Called by IR_TargetIsChild() to adjust the sibling frames that follow
|
||||
// after an incremental reflow of aKidFrame.
|
||||
// This function is not used for paginated mode so we don't need to deal
|
||||
// with continuing frames, and it's only called if aKidFrame has no
|
||||
// cells that span into it and no cells that span across it. That way
|
||||
// we don't have to deal with rowspans
|
||||
nsresult
|
||||
nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext& aPresContext,
|
||||
RowGroupReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nscoord aDeltaY)
|
||||
{
|
||||
NS_PRECONDITION(NS_UNCONSTRAINEDSIZE == aReflowState.reflowState.availableHeight,
|
||||
"we're not in galley mode");
|
||||
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: AdjustSiblingsAfterReflow\n");
|
||||
nsIFrame* lastKidFrame = aKidFrame;
|
||||
|
||||
@ -823,11 +842,12 @@ nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext& aP
|
||||
while (nsnull != kidFrame) {
|
||||
nsPoint origin;
|
||||
|
||||
// XXX We can't just slide the child if it has a next-in-flow
|
||||
// Adjust the y-origin
|
||||
kidFrame->GetOrigin(origin);
|
||||
origin.y += aDeltaY;
|
||||
|
||||
// XXX We need to send move notifications to the frame...
|
||||
// XXX We need to send move notifications to the frame. At least see if
|
||||
// views need to be repositioned
|
||||
nsIHTMLReflow* htmlReflow;
|
||||
if (NS_OK == kidFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) {
|
||||
htmlReflow->WillReflow(aPresContext);
|
||||
@ -844,8 +864,6 @@ nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext& aP
|
||||
lastKidFrame = GetLastFrame();
|
||||
}
|
||||
|
||||
// XXX Deal with cells that have rowspans.
|
||||
|
||||
// Update our running y-offset to reflect the bottommost child
|
||||
nsRect rect;
|
||||
lastKidFrame->GetRect(rect);
|
||||
@ -1125,8 +1143,6 @@ NS_METHOD nsTableRowGroupFrame::IncrementalReflow(nsIPresContext& aPresContext,
|
||||
nsIFrame* nextFrame;
|
||||
aReflowState.reflowState.reflowCommand->GetNext(nextFrame);
|
||||
|
||||
// Recover our reflow state
|
||||
//RecoverState(state, nextFrame);
|
||||
rv = IR_TargetIsChild(aPresContext, aDesiredSize, aReflowState, aStatus, nextFrame);
|
||||
}
|
||||
}
|
||||
@ -1429,6 +1445,51 @@ NS_METHOD nsTableRowGroupFrame::GetHeightOfRows(nscoord& aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Recovers the reflow state to what it should be if aKidFrame is about
|
||||
// to be reflowed. Restores the following:
|
||||
// - availSize
|
||||
// - y
|
||||
// - firstRow
|
||||
nsresult
|
||||
nsTableRowGroupFrame::RecoverState(RowGroupReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame)
|
||||
{
|
||||
// Walk the list of children looking for aKidFrame
|
||||
for (nsIFrame* frame = mFrames.FirstChild(); frame; frame->GetNextSibling(&frame)) {
|
||||
if (frame == aKidFrame) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Update the running y-offset
|
||||
nsSize kidSize;
|
||||
frame->GetSize(kidSize);
|
||||
aReflowState.y += kidSize.height;
|
||||
|
||||
// If our height is constrained then update the available height
|
||||
if (PR_FALSE == aReflowState.unconstrainedHeight) {
|
||||
aReflowState.availSize.height -= kidSize.height;
|
||||
}
|
||||
|
||||
// Update the maximum element size
|
||||
if (aReflowState.firstRow) {
|
||||
aReflowState.firstRow = PR_FALSE;
|
||||
// XXX Today you can't ask for max-element-size when doing an
|
||||
// incremental reflow
|
||||
#if 0
|
||||
if (aMaxElementSize) {
|
||||
aMaxElementSize->width = aKidMaxElementSize.width;
|
||||
aMaxElementSize->height = aKidMaxElementSize.height;
|
||||
}
|
||||
|
||||
} else if (aMaxElementSize) {
|
||||
aMaxElementSize->width = PR_MAX(aMaxElementSize->width, aKidMaxElementSize.width);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableRowGroupFrame::IR_TargetIsChild(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
RowGroupReflowState& aReflowState,
|
||||
@ -1438,35 +1499,53 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsChild(nsIPresContext& aPresConte
|
||||
{
|
||||
nsresult rv;
|
||||
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IR_TargetIsChild\n");
|
||||
// XXX Recover state
|
||||
// Recover the state as if aNextFrame is about to be reflowed
|
||||
RecoverState(aReflowState, aNextFrame);
|
||||
|
||||
// Remember the old rect
|
||||
nsRect oldKidRect;
|
||||
aNextFrame->GetRect(oldKidRect);
|
||||
|
||||
// Pass along the reflow command
|
||||
// XXX Correctly compute the available space...
|
||||
nsSize availSpace(aReflowState.reflowState.availableWidth, aReflowState.reflowState.availableHeight);
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState, aNextFrame, availSpace);
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState,
|
||||
aNextFrame, aReflowState.availSize);
|
||||
nsHTMLReflowMetrics desiredSize(nsnull);
|
||||
|
||||
rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
|
||||
// XXX Check aStatus to see if the frame is complete...
|
||||
|
||||
// Resize the row frame
|
||||
nsRect kidRect;
|
||||
aNextFrame->GetRect(kidRect);
|
||||
aNextFrame->SizeTo(desiredSize.width, desiredSize.height);
|
||||
// Place the row frame
|
||||
nsSize kidMaxElementSize;
|
||||
nsRect kidRect(0, aReflowState.y, desiredSize.width, desiredSize.height);
|
||||
PlaceChild(aPresContext, aReflowState, aNextFrame, kidRect, nsnull,
|
||||
kidMaxElementSize);
|
||||
|
||||
// Adjust the frames that follow...
|
||||
AdjustSiblingsAfterReflow(aPresContext, aReflowState, aNextFrame, desiredSize.height -
|
||||
oldKidRect.height);
|
||||
|
||||
// Return of desired size
|
||||
// See if the table needs a reflow (e.g., if the column widths have
|
||||
// changed). If so, just return and don't bother adjusting the rows
|
||||
// that follow
|
||||
if (!aReflowState.tableFrame->NeedsReflow(aReflowState.reflowState)) {
|
||||
// Inform the row of its new height.
|
||||
PRBool isJustSingleRow = PR_FALSE; /* how to determine this now? */
|
||||
if (isJustSingleRow) {
|
||||
((nsTableRowFrame*)aNextFrame)->DidResize(aPresContext, aReflowState.reflowState);
|
||||
|
||||
// Adjust the frames that follow...
|
||||
AdjustSiblingsAfterReflow(aPresContext, aReflowState, aNextFrame, desiredSize.height -
|
||||
oldKidRect.height);
|
||||
aDesiredSize.height = aReflowState.y;
|
||||
|
||||
} else {
|
||||
// Adjust the frames that follow...
|
||||
AdjustSiblingsAfterReflow(aPresContext, aReflowState, aNextFrame, desiredSize.height -
|
||||
oldKidRect.height);
|
||||
|
||||
// Now recalculate the row heights
|
||||
CalculateRowHeights(aPresContext, aDesiredSize, aReflowState.reflowState);
|
||||
}
|
||||
}
|
||||
|
||||
// Return our desired width
|
||||
aDesiredSize.width = aReflowState.reflowState.availableWidth;
|
||||
aDesiredSize.height = aReflowState.y;
|
||||
|
||||
// XXX If we have a next-in-flow, then we're not complete
|
||||
if (mNextInFlow) {
|
||||
aStatus = NS_FRAME_NOT_COMPLETE;
|
||||
}
|
||||
|
@ -44,9 +44,6 @@ struct RowGroupReflowState {
|
||||
// Flag used to set maxElementSize to my first row
|
||||
PRBool firstRow;
|
||||
|
||||
// Remember the height of the first row, because it's our maxElementHeight (plus header/footers)
|
||||
nscoord firstRowHeight;
|
||||
|
||||
nsTableFrame *tableFrame;
|
||||
|
||||
RowGroupReflowState(nsIPresContext& aPresContext,
|
||||
@ -61,7 +58,6 @@ struct RowGroupReflowState {
|
||||
unconstrainedWidth = PRBool(reflowState.availableWidth == NS_UNCONSTRAINEDSIZE);
|
||||
unconstrainedHeight = PRBool(reflowState.availableHeight == NS_UNCONSTRAINEDSIZE);
|
||||
firstRow = PR_TRUE;
|
||||
firstRowHeight=0;
|
||||
tableFrame = aTableFrame;
|
||||
}
|
||||
|
||||
@ -245,6 +241,9 @@ protected:
|
||||
RowGroupReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nscoord aDeltaY);
|
||||
|
||||
nsresult RecoverState(RowGroupReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame);
|
||||
|
||||
/**
|
||||
* Reflow the frames we've already created
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "nsSpaceManager.h"
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIPresShell.h"
|
||||
|
||||
#define CONSTANT float(0.0)
|
||||
#define DEBUG_REFLOW 0
|
||||
@ -1137,6 +1138,25 @@ nsBoxFrame::LayoutChildrenInRect(nsRect& size)
|
||||
}
|
||||
}
|
||||
|
||||
// Marks the frame as dirty and generates an incremental reflow
|
||||
// command targeted at this frame
|
||||
nsresult
|
||||
nsBoxFrame::GenerateDirtyReflowCommand(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell)
|
||||
{
|
||||
nsCOMPtr<nsIReflowCommand> reflowCmd;
|
||||
nsresult rv;
|
||||
|
||||
mState |= NS_FRAME_IS_DIRTY;
|
||||
rv = NS_NewHTMLReflowCommand(getter_AddRefs(reflowCmd), this,
|
||||
nsIReflowCommand::ReflowDirty);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Add the reflow command
|
||||
rv = aPresShell.AppendReflowCommand(reflowCmd);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBoxFrame::RemoveFrame(nsIPresContext& aPresContext,
|
||||
@ -1149,9 +1169,10 @@ nsBoxFrame::RemoveFrame(nsIPresContext& aPresContext,
|
||||
mSprings[i].clear();
|
||||
|
||||
// remove the child frame
|
||||
nsresult rv = nsHTMLContainerFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame);
|
||||
mFrames.DestroyFrame(aPresContext, aOldFrame);
|
||||
return rv;
|
||||
|
||||
// mark us dirty and generate a reflow command
|
||||
return GenerateDirtyReflowCommand(aPresContext, aPresShell);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1166,7 +1187,9 @@ nsBoxFrame::InsertFrames(nsIPresContext& aPresContext,
|
||||
mSprings[i].clear();
|
||||
|
||||
mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
|
||||
return nsHTMLContainerFrame::InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList);
|
||||
|
||||
// mark us dirty and generate a reflow command
|
||||
return GenerateDirtyReflowCommand(aPresContext, aPresShell);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1181,7 +1204,9 @@ nsBoxFrame::AppendFrames(nsIPresContext& aPresContext,
|
||||
mSprings[i].clear();
|
||||
|
||||
mFrames.AppendFrames(nsnull, aFrameList);
|
||||
return nsHTMLContainerFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList);
|
||||
|
||||
// mark us dirty and generate a reflow command
|
||||
return GenerateDirtyReflowCommand(aPresContext, aPresShell);
|
||||
}
|
||||
|
||||
|
||||
|
@ -144,6 +144,9 @@ protected:
|
||||
|
||||
virtual void GetInset(nsMargin& margin);
|
||||
|
||||
nsresult GenerateDirtyReflowCommand(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell);
|
||||
|
||||
PRBool mHorizontal;
|
||||
nsCalculatedBoxInfo mSprings[100];
|
||||
nscoord mSpringCount;
|
||||
|
@ -979,14 +979,17 @@ nsMenuFrame::RemoveFrame(nsIPresContext& aPresContext,
|
||||
for (int i=0; i < mSpringCount; i++)
|
||||
mSprings[i].clear();
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (mPopupFrames.ContainsFrame(aOldFrame)) {
|
||||
// Go ahead and remove this frame.
|
||||
nsHTMLContainerFrame::RemoveFrame(aPresContext, aPresShell, nsLayoutAtoms::popupList, aOldFrame);
|
||||
mPopupFrames.DestroyFrame(aPresContext, aOldFrame);
|
||||
return NS_OK;
|
||||
rv = GenerateDirtyReflowCommand(aPresContext, aPresShell);
|
||||
} else {
|
||||
rv = nsBoxFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame);
|
||||
}
|
||||
|
||||
return nsBoxFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1004,11 +1007,17 @@ nsMenuFrame::InsertFrames(nsIPresContext& aPresContext,
|
||||
aFrameList->GetContent(getter_AddRefs(frameChild));
|
||||
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
nsresult rv;
|
||||
|
||||
frameChild->GetTag(*getter_AddRefs(tag));
|
||||
if (tag && tag.get() == nsXULAtoms::menupopup) {
|
||||
mPopupFrames.InsertFrames(nsnull, nsnull, aFrameList);
|
||||
rv = GenerateDirtyReflowCommand(aPresContext, aPresShell);
|
||||
} else {
|
||||
rv = nsBoxFrame::InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList);
|
||||
}
|
||||
return nsHTMLContainerFrame::InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1028,10 +1037,15 @@ nsMenuFrame::AppendFrames(nsIPresContext& aPresContext,
|
||||
aFrameList->GetContent(getter_AddRefs(frameChild));
|
||||
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
nsresult rv;
|
||||
|
||||
frameChild->GetTag(*getter_AddRefs(tag));
|
||||
if (tag && tag.get() == nsXULAtoms::menupopup) {
|
||||
mPopupFrames.AppendFrames(nsnull, aFrameList);
|
||||
rv = GenerateDirtyReflowCommand(aPresContext, aPresShell);
|
||||
} else {
|
||||
rv = nsBoxFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList);
|
||||
}
|
||||
|
||||
return nsHTMLContainerFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -286,14 +286,17 @@ nsPopupSetFrame::RemoveFrame(nsIPresContext& aPresContext,
|
||||
for (int i=0; i < mSpringCount; i++)
|
||||
mSprings[i].clear();
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (mPopupFrames.ContainsFrame(aOldFrame)) {
|
||||
// Go ahead and remove this frame.
|
||||
nsHTMLContainerFrame::RemoveFrame(aPresContext, aPresShell, nsLayoutAtoms::popupList, aOldFrame);
|
||||
mPopupFrames.DestroyFrame(aPresContext, aOldFrame);
|
||||
return NS_OK;
|
||||
rv = GenerateDirtyReflowCommand(aPresContext, aPresShell);
|
||||
} else {
|
||||
rv = nsBoxFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame);
|
||||
}
|
||||
|
||||
return nsBoxFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -310,11 +313,16 @@ nsPopupSetFrame::InsertFrames(nsIPresContext& aPresContext,
|
||||
nsCOMPtr<nsIContent> frameChild;
|
||||
aFrameList->GetContent(getter_AddRefs(frameChild));
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
nsresult rv;
|
||||
frameChild->GetTag(*getter_AddRefs(tag));
|
||||
if (tag && tag.get() == nsXULAtoms::menupopup) {
|
||||
mPopupFrames.InsertFrames(nsnull, nsnull, aFrameList);
|
||||
rv = GenerateDirtyReflowCommand(aPresContext, aPresShell);
|
||||
} else {
|
||||
rv = nsBoxFrame::InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList);
|
||||
}
|
||||
return nsHTMLContainerFrame::InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -334,10 +342,15 @@ nsPopupSetFrame::AppendFrames(nsIPresContext& aPresContext,
|
||||
aFrameList->GetContent(getter_AddRefs(frameChild));
|
||||
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
nsresult rv;
|
||||
|
||||
frameChild->GetTag(*getter_AddRefs(tag));
|
||||
if (tag && tag.get() == nsXULAtoms::menupopup) {
|
||||
mPopupFrames.AppendFrames(nsnull, aFrameList);
|
||||
rv = GenerateDirtyReflowCommand(aPresContext, aPresShell);
|
||||
} else {
|
||||
rv = nsBoxFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList);
|
||||
}
|
||||
|
||||
return nsHTMLContainerFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -971,11 +971,21 @@ void nsTreeRowGroupFrame::OnContentAdded(nsIPresContext& aPresContext)
|
||||
if (IsLazy() && !treeFrame->IsSlatedForReflow()) {
|
||||
treeFrame->SlateForReflow();
|
||||
|
||||
// Schedule a reflow for us.
|
||||
nsCOMPtr<nsIReflowCommand> reflowCmd;
|
||||
// Mark the table frame as dirty
|
||||
nsFrameState frameState;
|
||||
|
||||
nsresult rv = NS_NewHTMLReflowCommand(getter_AddRefs(reflowCmd), treeFrame,
|
||||
nsIReflowCommand::FrameAppended, nsnull);
|
||||
treeFrame->GetFrameState(&frameState);
|
||||
frameState |= NS_FRAME_IS_DIRTY;
|
||||
treeFrame->SetFrameState(frameState);
|
||||
|
||||
// Schedule a reflow for us
|
||||
nsCOMPtr<nsIReflowCommand> reflowCmd;
|
||||
nsIFrame* outerTableFrame;
|
||||
nsresult rv;
|
||||
|
||||
treeFrame->GetParent(&outerTableFrame);
|
||||
rv = NS_NewHTMLReflowCommand(getter_AddRefs(reflowCmd), outerTableFrame,
|
||||
nsIReflowCommand::ReflowDirty);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
aPresContext.GetShell(getter_AddRefs(presShell));
|
||||
@ -1007,11 +1017,21 @@ void nsTreeRowGroupFrame::OnContentRemoved(nsIPresContext& aPresContext,
|
||||
if (IsLazy() && !treeFrame->IsSlatedForReflow()) {
|
||||
treeFrame->SlateForReflow();
|
||||
|
||||
// Mark the table frame as dirty
|
||||
nsFrameState frameState;
|
||||
|
||||
treeFrame->GetFrameState(&frameState);
|
||||
frameState |= NS_FRAME_IS_DIRTY;
|
||||
treeFrame->SetFrameState(frameState);
|
||||
|
||||
// Schedule a reflow for us.
|
||||
nsCOMPtr<nsIReflowCommand> reflowCmd;
|
||||
|
||||
nsresult rv = NS_NewHTMLReflowCommand(getter_AddRefs(reflowCmd), treeFrame,
|
||||
nsIReflowCommand::FrameRemoved, nsnull);
|
||||
nsIFrame* outerTableFrame;
|
||||
nsresult rv;
|
||||
|
||||
treeFrame->GetParent(&outerTableFrame);
|
||||
rv = NS_NewHTMLReflowCommand(getter_AddRefs(reflowCmd), treeFrame,
|
||||
nsIReflowCommand::ReflowDirty);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
aPresContext.GetShell(getter_AddRefs(presShell));
|
||||
|
Loading…
x
Reference in New Issue
Block a user