Bug 1389029 - Create custom change hint and post restyle event for rowspan, colspan attribute changes. r=dbaron

MozReview-Commit-ID: IwUlgDa3DAj
This commit is contained in:
Neerja Pancholi
2017-09-05 13:30:40 -07:00
parent 0d32baa271
commit bb48ee0cd8
7 changed files with 61 additions and 33 deletions

View File

@@ -432,12 +432,12 @@ RestyleManager::ChangeHintToString(nsChangeHint aHint)
"ReflowChangesSizeOrPosition", "UpdateComputedBSize", "ReflowChangesSizeOrPosition", "UpdateComputedBSize",
"UpdateUsesOpacity", "UpdateBackgroundPosition", "UpdateUsesOpacity", "UpdateBackgroundPosition",
"AddOrRemoveTransform", "CSSOverflowChange", "AddOrRemoveTransform", "CSSOverflowChange",
"UpdateWidgetProperties" "UpdateWidgetProperties", "UpdateTableCellSpans"
}; };
static_assert(nsChangeHint_AllHints == (1 << ArrayLength(names)) - 1, static_assert(nsChangeHint_AllHints == (1u << ArrayLength(names)) - 1,
"Name list doesn't match change hints."); "Name list doesn't match change hints.");
uint32_t hint = aHint & ((1 << ArrayLength(names)) - 1); uint32_t hint = aHint & ((1u << ArrayLength(names)) - 1);
uint32_t rest = aHint & ~((1 << ArrayLength(names)) - 1); uint32_t rest = aHint & ~((1u << ArrayLength(names)) - 1);
if ((hint & NS_STYLE_HINT_REFLOW) == NS_STYLE_HINT_REFLOW) { if ((hint & NS_STYLE_HINT_REFLOW) == NS_STYLE_HINT_REFLOW) {
result.AppendLiteral("NS_STYLE_HINT_REFLOW"); result.AppendLiteral("NS_STYLE_HINT_REFLOW");
hint = hint & ~NS_STYLE_HINT_REFLOW; hint = hint & ~NS_STYLE_HINT_REFLOW;
@@ -1697,6 +1697,9 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
if (hint & nsChangeHint_UpdateWidgetProperties) { if (hint & nsChangeHint_UpdateWidgetProperties) {
frame->UpdateWidgetProperties(); frame->UpdateWidgetProperties();
} }
if (hint & nsChangeHint_UpdateTableCellSpans) {
frameConstructor->UpdateTableCellSpans(content);
}
} }
} }

View File

@@ -9958,6 +9958,21 @@ nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(
return true; return true;
} }
void
nsCSSFrameConstructor::UpdateTableCellSpans(nsIContent* aContent)
{
nsTableCellFrame* cellFrame = do_QueryFrame(aContent->GetPrimaryFrame());
// It's possible that this warning could fire if some other style change
// simultaneously changes the 'display' of the element and makes it no
// longer be a table cell.
NS_WARNING_ASSERTION(cellFrame, "Hint should only be posted on table cells!");
if (cellFrame) {
cellFrame->GetTableFrame()->RowOrColSpanChanged(cellFrame);
}
}
void void
nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent, nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent,
InsertionKind aInsertionKind, InsertionKind aInsertionKind,

View File

@@ -1803,6 +1803,11 @@ private:
InsertionKind aInsertionKind, InsertionKind aInsertionKind,
RemoveFlags aFlags); RemoveFlags aFlags);
/**
* Handles change of rowspan and colspan attributes on table cells.
*/
void UpdateTableCellSpans(nsIContent* aContent);
// If removal of aFrame from the frame tree requires reconstruction of some // If removal of aFrame from the frame tree requires reconstruction of some
// containing block (either of aFrame or of its parent) due to {ib} splits or // containing block (either of aFrame or of its parent) due to {ib} splits or
// table pseudo-frames, recreate the relevant frame subtree. The return value // table pseudo-frames, recreate the relevant frame subtree. The return value

View File

@@ -238,6 +238,12 @@ enum nsChangeHint : uint32_t {
*/ */
nsChangeHint_UpdateWidgetProperties = 1 << 29, nsChangeHint_UpdateWidgetProperties = 1 << 29,
/**
* Indicates that there has been a colspan or rowspan attribute change
* on the cells of a table.
*/
nsChangeHint_UpdateTableCellSpans = 1 << 30,
// IMPORTANT NOTE: When adding a new hint, you will need to add it to // IMPORTANT NOTE: When adding a new hint, you will need to add it to
// one of: // one of:
// //
@@ -253,7 +259,7 @@ enum nsChangeHint : uint32_t {
/** /**
* Dummy hint value for all hints. It exists for compile time check. * Dummy hint value for all hints. It exists for compile time check.
*/ */
nsChangeHint_AllHints = (1 << 30) - 1, nsChangeHint_AllHints = (1u << 31) - 1,
}; };
// Redefine these operators to return nothing. This will catch any use // Redefine these operators to return nothing. This will catch any use
@@ -353,6 +359,7 @@ inline nsChangeHint operator^=(nsChangeHint& aLeft, nsChangeHint aRight)
nsChangeHint_UpdateOverflow | \ nsChangeHint_UpdateOverflow | \
nsChangeHint_UpdateParentOverflow | \ nsChangeHint_UpdateParentOverflow | \
nsChangeHint_UpdatePostTransformOverflow | \ nsChangeHint_UpdatePostTransformOverflow | \
nsChangeHint_UpdateTableCellSpans | \
nsChangeHint_UpdateTransformLayer | \ nsChangeHint_UpdateTransformLayer | \
nsChangeHint_UpdateUsesOpacity | \ nsChangeHint_UpdateUsesOpacity | \
nsChangeHint_AddOrRemoveTransform | \ nsChangeHint_AddOrRemoveTransform | \

View File

@@ -230,8 +230,12 @@ nsTableCellFrame::AttributeChanged(int32_t aNameSpaceID,
PresContext()->PresShell()-> PresContext()->PresShell()->
FrameNeedsReflow(this, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY); FrameNeedsReflow(this, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY);
} }
// let the table frame decide what to do
GetTableFrame()->AttributeChangedFor(this, mContent, aAttribute); if (aAttribute == nsGkAtoms::rowspan || aAttribute == nsGkAtoms::colspan) {
nsLayoutUtils::PostRestyleEvent(mContent->AsElement(),
nsRestyleHint(0),
nsChangeHint_UpdateTableCellSpans);
}
return NS_OK; return NS_OK;
} }

View File

@@ -355,30 +355,24 @@ nsTableFrame::SetInitialChildList(ChildListID aListID,
} }
void void
nsTableFrame::AttributeChangedFor(nsIFrame* aFrame, nsTableFrame::RowOrColSpanChanged(nsTableCellFrame* aCellFrame)
nsIContent* aContent,
nsIAtom* aAttribute)
{ {
nsTableCellFrame *cellFrame = do_QueryFrame(aFrame); if (aCellFrame) {
if (cellFrame) { nsTableCellMap* cellMap = GetCellMap();
if ((nsGkAtoms::rowspan == aAttribute) || if (cellMap) {
(nsGkAtoms::colspan == aAttribute)) { // for now just remove the cell from the map and reinsert it
nsTableCellMap* cellMap = GetCellMap(); int32_t rowIndex, colIndex;
if (cellMap) { aCellFrame->GetRowIndex(rowIndex);
// for now just remove the cell from the map and reinsert it aCellFrame->GetColIndex(colIndex);
int32_t rowIndex, colIndex; RemoveCell(aCellFrame, rowIndex);
cellFrame->GetRowIndex(rowIndex); AutoTArray<nsTableCellFrame*, 1> cells;
cellFrame->GetColIndex(colIndex); cells.AppendElement(aCellFrame);
RemoveCell(cellFrame, rowIndex); InsertCells(cells, rowIndex, colIndex - 1);
AutoTArray<nsTableCellFrame*, 1> cells;
cells.AppendElement(cellFrame);
InsertCells(cells, rowIndex, colIndex - 1);
// XXX Should this use eStyleChange? It currently doesn't need // XXX Should this use eStyleChange? It currently doesn't need
// to, but it might given more optimization. // to, but it might given more optimization.
PresContext()->PresShell()-> PresContext()->PresShell()->
FrameNeedsReflow(this, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY); FrameNeedsReflow(this, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY);
}
} }
} }
} }

View File

@@ -180,12 +180,12 @@ public:
nsIFrame* aDestructRoot); nsIFrame* aDestructRoot);
nsPoint GetFirstSectionOrigin(const ReflowInput& aReflowInput) const; nsPoint GetFirstSectionOrigin(const ReflowInput& aReflowInput) const;
/* /*
* Notification that aAttribute has changed for content inside a table (cell, row, etc) * Notification that rowspan or colspan has changed for content inside a
* table cell
*/ */
void AttributeChangedFor(nsIFrame* aFrame, void RowOrColSpanChanged(nsTableCellFrame* aCellFrame);
nsIContent* aContent,
nsIAtom* aAttribute);
/** @see nsIFrame::DestroyFrom */ /** @see nsIFrame::DestroyFrom */
virtual void DestroyFrom(nsIFrame* aDestructRoot) override; virtual void DestroyFrom(nsIFrame* aDestructRoot) override;