mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-28 11:28:38 +00:00
Implement ContentDeleted
This commit is contained in:
parent
1f9273223c
commit
dc09e8124d
@ -156,18 +156,6 @@ NS_METHOD nsHTMLContainerFrame::ContentAppended(nsIPresShell* aShell,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
HasSameMapping(nsIFrame* aFrame, nsIContent* aContent)
|
||||
{
|
||||
nsIContent* content;
|
||||
PRBool result;
|
||||
|
||||
aFrame->GetContent(content);
|
||||
result = content == aContent;
|
||||
NS_RELEASE(content);
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLContainerFrame::ContentInserted(nsIPresShell* aShell,
|
||||
nsIPresContext* aPresContext,
|
||||
@ -247,6 +235,128 @@ nsHTMLContainerFrame::ContentInserted(nsIPresShell* aShell,
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLContainerFrame::ContentDeleted(nsIPresShell* aShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInParent)
|
||||
{
|
||||
NS_ASSERTION(!IsPseudoFrame(), "pseudos not supported here");
|
||||
|
||||
// Find the frame that precedes the deletion point
|
||||
nsHTMLContainerFrame* flow;
|
||||
nsIFrame* deadFrame;
|
||||
nsIFrame* prevSibling;
|
||||
if (aIndexInParent > 0) {
|
||||
nsIContent* precedingContent = aContainer->ChildAt(aIndexInParent - 1);
|
||||
prevSibling = aShell->FindFrameWithContent(precedingContent);
|
||||
NS_RELEASE(precedingContent);
|
||||
|
||||
// The frame may have a next-in-flow. Get the last-in-flow
|
||||
nsIFrame* nextInFlow;
|
||||
do {
|
||||
prevSibling->GetNextInFlow(nextInFlow);
|
||||
if (nsnull != nextInFlow) {
|
||||
prevSibling = nextInFlow;
|
||||
}
|
||||
} while (nsnull != nextInFlow);
|
||||
|
||||
// Get the dead frame (maybe)
|
||||
prevSibling->GetGeometricParent((nsIFrame*&)flow);
|
||||
prevSibling->GetNextSibling(deadFrame);
|
||||
if (nsnull == deadFrame) {
|
||||
// The deadFrame must be prevSibling's parent's next-in-flows
|
||||
// first frame. Therefore it doesn't have a prevSibling.
|
||||
flow = (nsHTMLContainerFrame*) flow->mNextInFlow;
|
||||
if (nsnull != flow) {
|
||||
deadFrame = flow->mFirstChild;
|
||||
}
|
||||
prevSibling = nsnull;
|
||||
}
|
||||
}
|
||||
else {
|
||||
prevSibling = nsnull;
|
||||
flow = this;
|
||||
deadFrame = flow->mFirstChild;
|
||||
}
|
||||
NS_ASSERTION(nsnull != deadFrame, "yikes! couldn't find frame");
|
||||
if (nsnull == deadFrame) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Generate a reflow command
|
||||
nsIReflowCommand* cmd;
|
||||
nsresult rv = NS_NewHTMLReflowCommand(&cmd, flow,
|
||||
nsIReflowCommand::FrameDeleted);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
aShell->AppendReflowCommand(cmd);
|
||||
NS_RELEASE(cmd);
|
||||
|
||||
// Take the frame away; Note that we also have to take away any
|
||||
// continuations so we loop here until deadFrame is nsnull.
|
||||
while (nsnull != deadFrame) {
|
||||
// If the last frame for the flow is the frame we are deleting
|
||||
// then the flow will become complete.
|
||||
if (!flow->mLastContentIsComplete) {
|
||||
nsIFrame* lastFrame;
|
||||
flow->LastChild(lastFrame);
|
||||
if (lastFrame == deadFrame) {
|
||||
flow->mLastContentIsComplete = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove frame from sibling list
|
||||
nsIFrame* nextSib;
|
||||
deadFrame->GetNextSibling(nextSib);
|
||||
if (nsnull != prevSibling) {
|
||||
prevSibling->SetNextSibling(nextSib);
|
||||
}
|
||||
else {
|
||||
flow->mFirstChild = nextSib;
|
||||
}
|
||||
|
||||
// Update flows child count and last-content-offset. Note that
|
||||
// only the last content needs updating when a deadFrame is
|
||||
// removed from flow (because only the children that follow the
|
||||
// deletion need renumbering).
|
||||
flow->mChildCount--;
|
||||
flow->mLastContentOffset--;
|
||||
|
||||
// Break frame out of its flow and then destroy it
|
||||
nsIFrame* nextInFlow;
|
||||
deadFrame->GetNextInFlow(nextInFlow);
|
||||
deadFrame->BreakFromNextFlow();
|
||||
deadFrame->DeleteFrame();
|
||||
deadFrame = nextInFlow;
|
||||
|
||||
if (nsnull != deadFrame) {
|
||||
// Get the parent of deadFrame's continuation
|
||||
deadFrame->GetGeometricParent((nsIFrame*&) flow);
|
||||
|
||||
// When we move to a next-in-flow then the deadFrame will be the
|
||||
// first child of the new parent. Therefore we know that
|
||||
// prevSibling will be null.
|
||||
prevSibling = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// Repair any remaining next-in-flows content offsets; these are the
|
||||
// next-in-flows the follow the last flow container that contained
|
||||
// one of the deadFrame's. Therefore both content offsets need
|
||||
// updating (because all the children are following the deletion).
|
||||
flow = (nsHTMLContainerFrame*) flow->mNextInFlow;
|
||||
while (nsnull != flow) {
|
||||
flow->mFirstContentOffset--;
|
||||
flow->mLastContentOffset--;
|
||||
flow = (nsHTMLContainerFrame*) flow->mNextInFlow;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLContainerFrame::ProcessInitialReflow(nsIPresContext* aPresContext)
|
||||
{
|
||||
|
@ -31,25 +31,26 @@ public:
|
||||
NS_IMETHOD Paint(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect);
|
||||
|
||||
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus& aEventStatus);
|
||||
|
||||
NS_IMETHOD GetCursorAt(nsIPresContext& aPresContext,
|
||||
const nsPoint& aPoint,
|
||||
nsIFrame** aFrame,
|
||||
PRInt32& aCursor);
|
||||
|
||||
NS_IMETHOD ContentAppended(nsIPresShell* aShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIContent* aContainer);
|
||||
|
||||
NS_IMETHOD ContentInserted(nsIPresShell* aShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInParent);
|
||||
NS_IMETHOD ContentDeleted(nsIPresShell* aShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInParent);
|
||||
|
||||
protected:
|
||||
virtual ~nsHTMLContainerFrame();
|
||||
|
@ -156,18 +156,6 @@ NS_METHOD nsHTMLContainerFrame::ContentAppended(nsIPresShell* aShell,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
HasSameMapping(nsIFrame* aFrame, nsIContent* aContent)
|
||||
{
|
||||
nsIContent* content;
|
||||
PRBool result;
|
||||
|
||||
aFrame->GetContent(content);
|
||||
result = content == aContent;
|
||||
NS_RELEASE(content);
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLContainerFrame::ContentInserted(nsIPresShell* aShell,
|
||||
nsIPresContext* aPresContext,
|
||||
@ -247,6 +235,128 @@ nsHTMLContainerFrame::ContentInserted(nsIPresShell* aShell,
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLContainerFrame::ContentDeleted(nsIPresShell* aShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInParent)
|
||||
{
|
||||
NS_ASSERTION(!IsPseudoFrame(), "pseudos not supported here");
|
||||
|
||||
// Find the frame that precedes the deletion point
|
||||
nsHTMLContainerFrame* flow;
|
||||
nsIFrame* deadFrame;
|
||||
nsIFrame* prevSibling;
|
||||
if (aIndexInParent > 0) {
|
||||
nsIContent* precedingContent = aContainer->ChildAt(aIndexInParent - 1);
|
||||
prevSibling = aShell->FindFrameWithContent(precedingContent);
|
||||
NS_RELEASE(precedingContent);
|
||||
|
||||
// The frame may have a next-in-flow. Get the last-in-flow
|
||||
nsIFrame* nextInFlow;
|
||||
do {
|
||||
prevSibling->GetNextInFlow(nextInFlow);
|
||||
if (nsnull != nextInFlow) {
|
||||
prevSibling = nextInFlow;
|
||||
}
|
||||
} while (nsnull != nextInFlow);
|
||||
|
||||
// Get the dead frame (maybe)
|
||||
prevSibling->GetGeometricParent((nsIFrame*&)flow);
|
||||
prevSibling->GetNextSibling(deadFrame);
|
||||
if (nsnull == deadFrame) {
|
||||
// The deadFrame must be prevSibling's parent's next-in-flows
|
||||
// first frame. Therefore it doesn't have a prevSibling.
|
||||
flow = (nsHTMLContainerFrame*) flow->mNextInFlow;
|
||||
if (nsnull != flow) {
|
||||
deadFrame = flow->mFirstChild;
|
||||
}
|
||||
prevSibling = nsnull;
|
||||
}
|
||||
}
|
||||
else {
|
||||
prevSibling = nsnull;
|
||||
flow = this;
|
||||
deadFrame = flow->mFirstChild;
|
||||
}
|
||||
NS_ASSERTION(nsnull != deadFrame, "yikes! couldn't find frame");
|
||||
if (nsnull == deadFrame) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Generate a reflow command
|
||||
nsIReflowCommand* cmd;
|
||||
nsresult rv = NS_NewHTMLReflowCommand(&cmd, flow,
|
||||
nsIReflowCommand::FrameDeleted);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
aShell->AppendReflowCommand(cmd);
|
||||
NS_RELEASE(cmd);
|
||||
|
||||
// Take the frame away; Note that we also have to take away any
|
||||
// continuations so we loop here until deadFrame is nsnull.
|
||||
while (nsnull != deadFrame) {
|
||||
// If the last frame for the flow is the frame we are deleting
|
||||
// then the flow will become complete.
|
||||
if (!flow->mLastContentIsComplete) {
|
||||
nsIFrame* lastFrame;
|
||||
flow->LastChild(lastFrame);
|
||||
if (lastFrame == deadFrame) {
|
||||
flow->mLastContentIsComplete = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove frame from sibling list
|
||||
nsIFrame* nextSib;
|
||||
deadFrame->GetNextSibling(nextSib);
|
||||
if (nsnull != prevSibling) {
|
||||
prevSibling->SetNextSibling(nextSib);
|
||||
}
|
||||
else {
|
||||
flow->mFirstChild = nextSib;
|
||||
}
|
||||
|
||||
// Update flows child count and last-content-offset. Note that
|
||||
// only the last content needs updating when a deadFrame is
|
||||
// removed from flow (because only the children that follow the
|
||||
// deletion need renumbering).
|
||||
flow->mChildCount--;
|
||||
flow->mLastContentOffset--;
|
||||
|
||||
// Break frame out of its flow and then destroy it
|
||||
nsIFrame* nextInFlow;
|
||||
deadFrame->GetNextInFlow(nextInFlow);
|
||||
deadFrame->BreakFromNextFlow();
|
||||
deadFrame->DeleteFrame();
|
||||
deadFrame = nextInFlow;
|
||||
|
||||
if (nsnull != deadFrame) {
|
||||
// Get the parent of deadFrame's continuation
|
||||
deadFrame->GetGeometricParent((nsIFrame*&) flow);
|
||||
|
||||
// When we move to a next-in-flow then the deadFrame will be the
|
||||
// first child of the new parent. Therefore we know that
|
||||
// prevSibling will be null.
|
||||
prevSibling = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// Repair any remaining next-in-flows content offsets; these are the
|
||||
// next-in-flows the follow the last flow container that contained
|
||||
// one of the deadFrame's. Therefore both content offsets need
|
||||
// updating (because all the children are following the deletion).
|
||||
flow = (nsHTMLContainerFrame*) flow->mNextInFlow;
|
||||
while (nsnull != flow) {
|
||||
flow->mFirstContentOffset--;
|
||||
flow->mLastContentOffset--;
|
||||
flow = (nsHTMLContainerFrame*) flow->mNextInFlow;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLContainerFrame::ProcessInitialReflow(nsIPresContext* aPresContext)
|
||||
{
|
||||
|
@ -31,25 +31,26 @@ public:
|
||||
NS_IMETHOD Paint(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect);
|
||||
|
||||
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus& aEventStatus);
|
||||
|
||||
NS_IMETHOD GetCursorAt(nsIPresContext& aPresContext,
|
||||
const nsPoint& aPoint,
|
||||
nsIFrame** aFrame,
|
||||
PRInt32& aCursor);
|
||||
|
||||
NS_IMETHOD ContentAppended(nsIPresShell* aShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIContent* aContainer);
|
||||
|
||||
NS_IMETHOD ContentInserted(nsIPresShell* aShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInParent);
|
||||
NS_IMETHOD ContentDeleted(nsIPresShell* aShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInParent);
|
||||
|
||||
protected:
|
||||
virtual ~nsHTMLContainerFrame();
|
||||
|
Loading…
Reference in New Issue
Block a user