зеркало из https://github.com/mozilla/pjs.git
bug 22246 - row/col span changes on cell alter cell map and reflow table. r=kmcclusk
This commit is contained in:
Родитель
527c7e0748
Коммит
5397ffd020
|
@ -364,7 +364,7 @@ PRBool nsCellMap::CellsSpanInOrOut(PRInt32 aStartRowIndex,
|
|||
}
|
||||
|
||||
void nsCellMap::InsertCells(nsVoidArray& aCellFrames,
|
||||
PRInt32 aRowIndex,
|
||||
PRInt32 aRowIndex,
|
||||
PRInt32 aColIndexBefore)
|
||||
{
|
||||
if (aCellFrames.Count() == 0) return;
|
||||
|
@ -419,7 +419,6 @@ void nsCellMap::InsertCells(nsVoidArray& aCellFrames,
|
|||
else {
|
||||
ExpandWithCells(aCellFrames, aRowIndex, startColIndex, rowSpan);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -537,9 +536,11 @@ void nsCellMap::ExpandWithCells(nsVoidArray& aCellFrames,
|
|||
for (PRInt32 rowX = aRowIndex; rowX <= endRowIndex; rowX++) {
|
||||
nsVoidArray* row = (nsVoidArray *)mRows.ElementAt(rowX);
|
||||
PRInt32 numCols = row->Count();
|
||||
for (PRInt32 colX = aColIndex + totalColSpan; colX < numCols; colX++) {
|
||||
PRInt32 colX;
|
||||
for (colX = aColIndex + totalColSpan; colX < numCols; colX++) {
|
||||
CellData* data = (CellData*) row->ElementAt(colX);
|
||||
if (data) {
|
||||
// increase the origin and span counts beyond the spanned cols
|
||||
if (data->mOrigCell) {
|
||||
// a cell that gets moved needs adjustment as well as it new orignating col
|
||||
data->mOrigCell->SetColIndex(colX);
|
||||
|
@ -550,21 +551,24 @@ void nsCellMap::ExpandWithCells(nsVoidArray& aCellFrames,
|
|||
nsColInfo* colInfo = (nsColInfo *)mCols.ElementAt(colX);
|
||||
colInfo->mNumCellsSpan++;
|
||||
}
|
||||
}
|
||||
data = (CellData*) row->ElementAt(colX - totalColSpan);
|
||||
if (data) {
|
||||
if (data->mOrigCell) {
|
||||
// the old originating col of a moved cell needs adjustment
|
||||
nsColInfo* colInfo = (nsColInfo *)mCols.ElementAt(colX - totalColSpan);
|
||||
colInfo->mNumCellsOrig--;
|
||||
}
|
||||
else if (data->mColSpanData) {
|
||||
nsColInfo* colInfo = (nsColInfo *)mCols.ElementAt(colX);
|
||||
colInfo->mNumCellsSpan--;
|
||||
}
|
||||
|
||||
// decrease the origin and span counts within the spanned cols
|
||||
PRInt32 colX2 = colX - totalColSpan;
|
||||
//if (colX2 < aColIndex + totalColSpan) {
|
||||
nsColInfo* colInfo2 = (nsColInfo *)mCols.ElementAt(colX2);
|
||||
if (data->mOrigCell) {
|
||||
// the old originating col of a moved cell needs adjustment
|
||||
colInfo2->mNumCellsOrig--;
|
||||
}
|
||||
else if (data->mColSpanData) {
|
||||
colInfo2->mNumCellsSpan--;
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
// remove any unused cols
|
||||
RemoveUnusedCols(mCols.Count());
|
||||
}
|
||||
|
||||
void nsCellMap::ShrinkWithoutRows(PRInt32 aStartRowIndex,
|
||||
|
@ -611,16 +615,50 @@ void nsCellMap::ShrinkWithoutRows(PRInt32 aStartRowIndex,
|
|||
}
|
||||
}
|
||||
|
||||
PRInt32 nsCellMap::GetColSpan(PRInt32 aRowIndex,
|
||||
PRInt32 aColIndex)
|
||||
{
|
||||
PRInt32 colSpan = 1;
|
||||
nsVoidArray* row = (nsVoidArray *)(mRows.ElementAt(aRowIndex));
|
||||
PRInt32 colCount = mCols.Count();
|
||||
for (PRInt32 colX = aColIndex + 1; colX < colCount; colX++) {
|
||||
CellData* data = (CellData *)(row->ElementAt(colX));
|
||||
if (data && data->mColSpanData) {
|
||||
colSpan++;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
return colSpan;
|
||||
}
|
||||
|
||||
PRInt32 nsCellMap::GetRowSpan(PRInt32 aRowIndex,
|
||||
PRInt32 aColIndex)
|
||||
{
|
||||
PRInt32 rowSpan = 1;
|
||||
PRInt32 rowCount = mRows.Count();
|
||||
for (PRInt32 rowX = aRowIndex + 1; rowX < rowCount; rowX++) {
|
||||
nsVoidArray* row = (nsVoidArray *)(mRows.ElementAt(rowX));
|
||||
CellData* data = (CellData *)(row->ElementAt(aColIndex));
|
||||
if (data && data->mRowSpanData) {
|
||||
rowSpan++;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
return rowSpan;
|
||||
}
|
||||
|
||||
void nsCellMap::ShrinkWithoutCell(nsTableCellFrame& aCellFrame,
|
||||
PRInt32 aRowIndex,
|
||||
PRInt32 aColIndex)
|
||||
{
|
||||
PRInt32 rowSpan = aCellFrame.GetRowSpan();
|
||||
PRInt32 colSpan = aCellFrame.GetColSpan();
|
||||
PRInt32 colX, rowX;
|
||||
|
||||
// get the rowspan and colspan from the cell map since the content may have changed
|
||||
PRInt32 rowSpan = GetRowSpan(aRowIndex, aColIndex);
|
||||
PRInt32 colSpan = GetColSpan(aRowIndex, aColIndex);
|
||||
PRInt32 endRowIndex = aRowIndex + rowSpan - 1;
|
||||
PRInt32 endColIndex = aColIndex + colSpan - 1;
|
||||
|
||||
PRInt32 colX;
|
||||
// adjust the col counts due to the deleted cell before removing it
|
||||
for (colX = aColIndex; colX <= endColIndex; colX++) {
|
||||
nsColInfo* colInfo = (nsColInfo *)mCols.ElementAt(colX);
|
||||
|
@ -633,10 +671,9 @@ void nsCellMap::ShrinkWithoutCell(nsTableCellFrame& aCellFrame,
|
|||
}
|
||||
|
||||
// remove the deleted cell and cellData entries for it
|
||||
PRInt32 rowX;
|
||||
for (rowX = aRowIndex; rowX <= endRowIndex; rowX++) {
|
||||
nsVoidArray* row = (nsVoidArray *)mRows.ElementAt(rowX);
|
||||
for (colX = aColIndex; colX <= endColIndex; colX++) {
|
||||
for (colX = endColIndex; colX >= aColIndex; colX--) {
|
||||
row->RemoveElementAt(colX);
|
||||
}
|
||||
// put back null entries in the row to make it the right size
|
||||
|
@ -871,7 +908,7 @@ void nsCellMap::RebuildConsideringCells(nsVoidArray* aCellFrames,
|
|||
}
|
||||
|
||||
void nsCellMap::RemoveCell(nsTableCellFrame* aCellFrame,
|
||||
PRInt32 aRowIndex)
|
||||
PRInt32 aRowIndex)
|
||||
{
|
||||
PRInt32 numRows = mRows.Count();
|
||||
if ((aRowIndex < 0) || (aRowIndex >= numRows)) {
|
||||
|
@ -889,9 +926,9 @@ void nsCellMap::RemoveCell(nsTableCellFrame* aCellFrame,
|
|||
}
|
||||
}
|
||||
|
||||
PRInt32 rowSpan = aCellFrame->GetRowSpan();
|
||||
PRInt32 rowSpan = GetRowSpan(aRowIndex, startColIndex);
|
||||
PRInt32 endRowIndex = aRowIndex + rowSpan - 1;
|
||||
PRInt32 endColIndex = startColIndex + aCellFrame->GetColSpan() - 1;
|
||||
PRInt32 endColIndex = startColIndex + GetColSpan(aRowIndex, startColIndex) - 1;
|
||||
// record whether removing the cells is going to cause complications due
|
||||
// to existing row spans, col spans or table sizing.
|
||||
PRBool spansCauseRebuild = PR_FALSE;
|
||||
|
@ -962,7 +999,8 @@ void nsCellMap::Dump() const
|
|||
// check the validity of the cell map
|
||||
nsVoidArray* rowAbove = (nsVoidArray *)mRows.ElementAt(rowIndex - 1);
|
||||
CellData* cdAbove = (CellData *)rowAbove->ElementAt(colIndex);
|
||||
if ((cdAbove->mOrigCell != cell) && (cdAbove->mRowSpanData->mOrigCell != cell)) {
|
||||
if ((cdAbove->mOrigCell != cell) && (cdAbove->mRowSpanData) &&
|
||||
(cdAbove->mRowSpanData->mOrigCell != cell)) {
|
||||
NS_ASSERTION(PR_FALSE, "bad row span data");
|
||||
}
|
||||
printf("R ");
|
||||
|
@ -971,7 +1009,8 @@ void nsCellMap::Dump() const
|
|||
cell = cd->mColSpanData->mOrigCell;
|
||||
// check the validity of the cell map
|
||||
CellData* cdBefore = (CellData *)row->ElementAt(colIndex - 1);
|
||||
if ((cdBefore->mOrigCell != cell) && (cdBefore->mColSpanData->mOrigCell != cell)) {
|
||||
if ((cdBefore->mOrigCell != cell) && (cdBefore->mColSpanData) &&
|
||||
(cdBefore->mColSpanData->mOrigCell != cell)) {
|
||||
NS_ASSERTION(PR_FALSE, "bad col span data");
|
||||
}
|
||||
printf("C ");
|
||||
|
|
|
@ -183,6 +183,13 @@ protected:
|
|||
|
||||
PRBool CreateEmptyRow(PRInt32 aRowIndex,
|
||||
PRInt32 aNumCols);
|
||||
|
||||
PRInt32 GetColSpan(PRInt32 aRowIndex,
|
||||
PRInt32 aColIndex);
|
||||
|
||||
PRInt32 GetRowSpan(PRInt32 aRowIndex,
|
||||
PRInt32 aColIndex);
|
||||
|
||||
/** an array containing col array. It can be larger than mRowCount due to
|
||||
* row spans extending beyond the table */
|
||||
nsVoidArray mRows;
|
||||
|
|
|
@ -51,6 +51,13 @@ NS_DEF_PTR(nsIStyleContext);
|
|||
static NS_DEFINE_IID(kIHTMLTableCellElementIID, NS_IHTMLTABLECELLELEMENT_IID);
|
||||
static NS_DEFINE_IID(kIDOMHTMLTableCellElementIID, NS_IDOMHTMLTABLECELLELEMENT_IID);
|
||||
|
||||
nsTableCellFrame::nsTableCellFrame()
|
||||
{
|
||||
mColIndex = 0;
|
||||
mPriorAvailWidth = 0;
|
||||
mBorderEdges = nsnull;
|
||||
}
|
||||
|
||||
nsTableCellFrame::~nsTableCellFrame()
|
||||
{
|
||||
delete mBorderEdges;
|
||||
|
@ -80,6 +87,22 @@ nsTableCellFrame::Init(nsIPresContext* aPresContext,
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTableCellFrame::AttributeChanged(nsIPresContext* aPresContext,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aHint)
|
||||
{
|
||||
// let the table frame decide what to do
|
||||
nsTableFrame* tableFrame = nsnull;
|
||||
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if ((NS_SUCCEEDED(rv)) && (tableFrame)) {
|
||||
tableFrame->AttributeChangedFor(aPresContext, this, aChild, aAttribute);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsTableCellFrame::SetPass1MaxElementSize(const nsSize& aMaxElementSize)
|
||||
{
|
||||
mPass1MaxElementSize.height = aMaxElementSize.height;
|
||||
|
@ -144,6 +167,7 @@ void nsTableCellFrame::InitCellFrame(PRInt32 aColIndex)
|
|||
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame)) {
|
||||
SetColIndex(aColIndex);
|
||||
if (NS_STYLE_BORDER_COLLAPSE == tableFrame->GetBorderCollapseStyle()) {
|
||||
if (mBorderEdges) delete mBorderEdges; // this could be non null during a reinitialization
|
||||
mBorderEdges = new nsBorderEdges;
|
||||
mBorderEdges->mOutsideEdge=PR_FALSE;
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ public:
|
|||
|
||||
// default constructor supplied by the compiler
|
||||
|
||||
nsTableCellFrame();
|
||||
~nsTableCellFrame();
|
||||
|
||||
NS_IMETHOD Init(nsIPresContext* aPresContext,
|
||||
|
@ -65,6 +66,12 @@ public:
|
|||
nsIStyleContext* aContext,
|
||||
nsIFrame* aPrevInFlow);
|
||||
|
||||
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aHint);
|
||||
|
||||
// table cells contain an area frame which does most of the work, and
|
||||
// so these functions should never be called. They assert and return
|
||||
// NS_ERROR_NOT_IMPLEMENTED
|
||||
|
|
|
@ -247,6 +247,39 @@ nsTableFrame::Destroy(nsIPresContext* aPresContext)
|
|||
return nsHTMLContainerFrame::Destroy(aPresContext);
|
||||
}
|
||||
|
||||
// Helper function. It marks the table frame as dirty and generates
|
||||
// a reflow command
|
||||
nsresult
|
||||
nsTableFrame::AddTableDirtyReflowCommand(nsIPresContext* aPresContext,
|
||||
nsIFrame* aTableFrame)
|
||||
{
|
||||
nsFrameState frameState;
|
||||
nsIFrame* tableParentFrame;
|
||||
nsIReflowCommand* reflowCmd;
|
||||
nsresult rv;
|
||||
nsIPresShell* presShell;
|
||||
|
||||
aPresContext->GetShell(&presShell);
|
||||
|
||||
// Mark the table frame as dirty
|
||||
aTableFrame->GetFrameState(&frameState);
|
||||
frameState |= NS_FRAME_IS_DIRTY;
|
||||
aTableFrame->SetFrameState(frameState);
|
||||
|
||||
// Target the reflow comamnd at its parent frame
|
||||
aTableFrame->GetParent(&tableParentFrame);
|
||||
rv = NS_NewHTMLReflowCommand(&reflowCmd, tableParentFrame,
|
||||
nsIReflowCommand::ReflowDirty);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Add the reflow command
|
||||
rv = presShell->AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
|
||||
NS_RELEASE(presShell);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// XXX this needs to be cleaned up so that the frame constructor breaks out col group
|
||||
// frames into a separate child list.
|
||||
NS_IMETHODIMP
|
||||
|
@ -315,6 +348,37 @@ nsTableFrame::SetInitialChildList(nsIPresContext* aPresContext,
|
|||
}
|
||||
|
||||
|
||||
void nsTableFrame::AttributeChangedFor(nsIPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
nsIContent* aContent,
|
||||
nsIAtom* aAttribute)
|
||||
{
|
||||
nsIAtom* frameType;
|
||||
aFrame->GetFrameType(&frameType);
|
||||
if (nsLayoutAtoms::tableCellFrame == frameType) {
|
||||
if ((nsHTMLAtoms::rowspan == aAttribute) ||
|
||||
(nsHTMLAtoms::colspan == aAttribute)) {
|
||||
nsCellMap* cellMap = GetCellMap();
|
||||
if (cellMap) {
|
||||
// for now just remove the cell from the map and reinsert it
|
||||
nsTableCellFrame* cellFrame = (nsTableCellFrame*)aFrame;
|
||||
PRInt32 rowIndex, colIndex;
|
||||
cellFrame->GetRowIndex(rowIndex);
|
||||
cellFrame->GetColIndex(colIndex);
|
||||
RemoveCell(*aPresContext, cellFrame, rowIndex);
|
||||
nsVoidArray cells;
|
||||
cells.AppendElement(cellFrame);
|
||||
InsertCells(*aPresContext, cells, rowIndex, colIndex - 1);
|
||||
// invalidate the column widths and generate a reflow command
|
||||
InvalidateColumnWidths();
|
||||
AddTableDirtyReflowCommand(aPresContext, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_IF_RELEASE(frameType);
|
||||
}
|
||||
|
||||
|
||||
/* ****** CellMap methods ******* */
|
||||
|
||||
/* counts columns in column groups */
|
||||
|
|
|
@ -106,6 +106,16 @@ public:
|
|||
nsIFrame* aPrevInFlow);
|
||||
|
||||
|
||||
static nsresult AddTableDirtyReflowCommand(nsIPresContext* aPresContext,
|
||||
nsIFrame* aTableFrame);
|
||||
/*
|
||||
* Notification that aAttribute has changed for content inside a table (cell, row, etc)
|
||||
*/
|
||||
void AttributeChangedFor(nsIPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
nsIContent* aContent,
|
||||
nsIAtom* aAttribute);
|
||||
|
||||
/** @see nsIFrame::Destroy */
|
||||
NS_IMETHOD Destroy(nsIPresContext* aPresContext);
|
||||
|
||||
|
|
|
@ -364,7 +364,7 @@ PRBool nsCellMap::CellsSpanInOrOut(PRInt32 aStartRowIndex,
|
|||
}
|
||||
|
||||
void nsCellMap::InsertCells(nsVoidArray& aCellFrames,
|
||||
PRInt32 aRowIndex,
|
||||
PRInt32 aRowIndex,
|
||||
PRInt32 aColIndexBefore)
|
||||
{
|
||||
if (aCellFrames.Count() == 0) return;
|
||||
|
@ -419,7 +419,6 @@ void nsCellMap::InsertCells(nsVoidArray& aCellFrames,
|
|||
else {
|
||||
ExpandWithCells(aCellFrames, aRowIndex, startColIndex, rowSpan);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -537,9 +536,11 @@ void nsCellMap::ExpandWithCells(nsVoidArray& aCellFrames,
|
|||
for (PRInt32 rowX = aRowIndex; rowX <= endRowIndex; rowX++) {
|
||||
nsVoidArray* row = (nsVoidArray *)mRows.ElementAt(rowX);
|
||||
PRInt32 numCols = row->Count();
|
||||
for (PRInt32 colX = aColIndex + totalColSpan; colX < numCols; colX++) {
|
||||
PRInt32 colX;
|
||||
for (colX = aColIndex + totalColSpan; colX < numCols; colX++) {
|
||||
CellData* data = (CellData*) row->ElementAt(colX);
|
||||
if (data) {
|
||||
// increase the origin and span counts beyond the spanned cols
|
||||
if (data->mOrigCell) {
|
||||
// a cell that gets moved needs adjustment as well as it new orignating col
|
||||
data->mOrigCell->SetColIndex(colX);
|
||||
|
@ -550,21 +551,24 @@ void nsCellMap::ExpandWithCells(nsVoidArray& aCellFrames,
|
|||
nsColInfo* colInfo = (nsColInfo *)mCols.ElementAt(colX);
|
||||
colInfo->mNumCellsSpan++;
|
||||
}
|
||||
}
|
||||
data = (CellData*) row->ElementAt(colX - totalColSpan);
|
||||
if (data) {
|
||||
if (data->mOrigCell) {
|
||||
// the old originating col of a moved cell needs adjustment
|
||||
nsColInfo* colInfo = (nsColInfo *)mCols.ElementAt(colX - totalColSpan);
|
||||
colInfo->mNumCellsOrig--;
|
||||
}
|
||||
else if (data->mColSpanData) {
|
||||
nsColInfo* colInfo = (nsColInfo *)mCols.ElementAt(colX);
|
||||
colInfo->mNumCellsSpan--;
|
||||
}
|
||||
|
||||
// decrease the origin and span counts within the spanned cols
|
||||
PRInt32 colX2 = colX - totalColSpan;
|
||||
//if (colX2 < aColIndex + totalColSpan) {
|
||||
nsColInfo* colInfo2 = (nsColInfo *)mCols.ElementAt(colX2);
|
||||
if (data->mOrigCell) {
|
||||
// the old originating col of a moved cell needs adjustment
|
||||
colInfo2->mNumCellsOrig--;
|
||||
}
|
||||
else if (data->mColSpanData) {
|
||||
colInfo2->mNumCellsSpan--;
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
// remove any unused cols
|
||||
RemoveUnusedCols(mCols.Count());
|
||||
}
|
||||
|
||||
void nsCellMap::ShrinkWithoutRows(PRInt32 aStartRowIndex,
|
||||
|
@ -611,16 +615,50 @@ void nsCellMap::ShrinkWithoutRows(PRInt32 aStartRowIndex,
|
|||
}
|
||||
}
|
||||
|
||||
PRInt32 nsCellMap::GetColSpan(PRInt32 aRowIndex,
|
||||
PRInt32 aColIndex)
|
||||
{
|
||||
PRInt32 colSpan = 1;
|
||||
nsVoidArray* row = (nsVoidArray *)(mRows.ElementAt(aRowIndex));
|
||||
PRInt32 colCount = mCols.Count();
|
||||
for (PRInt32 colX = aColIndex + 1; colX < colCount; colX++) {
|
||||
CellData* data = (CellData *)(row->ElementAt(colX));
|
||||
if (data && data->mColSpanData) {
|
||||
colSpan++;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
return colSpan;
|
||||
}
|
||||
|
||||
PRInt32 nsCellMap::GetRowSpan(PRInt32 aRowIndex,
|
||||
PRInt32 aColIndex)
|
||||
{
|
||||
PRInt32 rowSpan = 1;
|
||||
PRInt32 rowCount = mRows.Count();
|
||||
for (PRInt32 rowX = aRowIndex + 1; rowX < rowCount; rowX++) {
|
||||
nsVoidArray* row = (nsVoidArray *)(mRows.ElementAt(rowX));
|
||||
CellData* data = (CellData *)(row->ElementAt(aColIndex));
|
||||
if (data && data->mRowSpanData) {
|
||||
rowSpan++;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
return rowSpan;
|
||||
}
|
||||
|
||||
void nsCellMap::ShrinkWithoutCell(nsTableCellFrame& aCellFrame,
|
||||
PRInt32 aRowIndex,
|
||||
PRInt32 aColIndex)
|
||||
{
|
||||
PRInt32 rowSpan = aCellFrame.GetRowSpan();
|
||||
PRInt32 colSpan = aCellFrame.GetColSpan();
|
||||
PRInt32 colX, rowX;
|
||||
|
||||
// get the rowspan and colspan from the cell map since the content may have changed
|
||||
PRInt32 rowSpan = GetRowSpan(aRowIndex, aColIndex);
|
||||
PRInt32 colSpan = GetColSpan(aRowIndex, aColIndex);
|
||||
PRInt32 endRowIndex = aRowIndex + rowSpan - 1;
|
||||
PRInt32 endColIndex = aColIndex + colSpan - 1;
|
||||
|
||||
PRInt32 colX;
|
||||
// adjust the col counts due to the deleted cell before removing it
|
||||
for (colX = aColIndex; colX <= endColIndex; colX++) {
|
||||
nsColInfo* colInfo = (nsColInfo *)mCols.ElementAt(colX);
|
||||
|
@ -633,10 +671,9 @@ void nsCellMap::ShrinkWithoutCell(nsTableCellFrame& aCellFrame,
|
|||
}
|
||||
|
||||
// remove the deleted cell and cellData entries for it
|
||||
PRInt32 rowX;
|
||||
for (rowX = aRowIndex; rowX <= endRowIndex; rowX++) {
|
||||
nsVoidArray* row = (nsVoidArray *)mRows.ElementAt(rowX);
|
||||
for (colX = aColIndex; colX <= endColIndex; colX++) {
|
||||
for (colX = endColIndex; colX >= aColIndex; colX--) {
|
||||
row->RemoveElementAt(colX);
|
||||
}
|
||||
// put back null entries in the row to make it the right size
|
||||
|
@ -871,7 +908,7 @@ void nsCellMap::RebuildConsideringCells(nsVoidArray* aCellFrames,
|
|||
}
|
||||
|
||||
void nsCellMap::RemoveCell(nsTableCellFrame* aCellFrame,
|
||||
PRInt32 aRowIndex)
|
||||
PRInt32 aRowIndex)
|
||||
{
|
||||
PRInt32 numRows = mRows.Count();
|
||||
if ((aRowIndex < 0) || (aRowIndex >= numRows)) {
|
||||
|
@ -889,9 +926,9 @@ void nsCellMap::RemoveCell(nsTableCellFrame* aCellFrame,
|
|||
}
|
||||
}
|
||||
|
||||
PRInt32 rowSpan = aCellFrame->GetRowSpan();
|
||||
PRInt32 rowSpan = GetRowSpan(aRowIndex, startColIndex);
|
||||
PRInt32 endRowIndex = aRowIndex + rowSpan - 1;
|
||||
PRInt32 endColIndex = startColIndex + aCellFrame->GetColSpan() - 1;
|
||||
PRInt32 endColIndex = startColIndex + GetColSpan(aRowIndex, startColIndex) - 1;
|
||||
// record whether removing the cells is going to cause complications due
|
||||
// to existing row spans, col spans or table sizing.
|
||||
PRBool spansCauseRebuild = PR_FALSE;
|
||||
|
@ -962,7 +999,8 @@ void nsCellMap::Dump() const
|
|||
// check the validity of the cell map
|
||||
nsVoidArray* rowAbove = (nsVoidArray *)mRows.ElementAt(rowIndex - 1);
|
||||
CellData* cdAbove = (CellData *)rowAbove->ElementAt(colIndex);
|
||||
if ((cdAbove->mOrigCell != cell) && (cdAbove->mRowSpanData->mOrigCell != cell)) {
|
||||
if ((cdAbove->mOrigCell != cell) && (cdAbove->mRowSpanData) &&
|
||||
(cdAbove->mRowSpanData->mOrigCell != cell)) {
|
||||
NS_ASSERTION(PR_FALSE, "bad row span data");
|
||||
}
|
||||
printf("R ");
|
||||
|
@ -971,7 +1009,8 @@ void nsCellMap::Dump() const
|
|||
cell = cd->mColSpanData->mOrigCell;
|
||||
// check the validity of the cell map
|
||||
CellData* cdBefore = (CellData *)row->ElementAt(colIndex - 1);
|
||||
if ((cdBefore->mOrigCell != cell) && (cdBefore->mColSpanData->mOrigCell != cell)) {
|
||||
if ((cdBefore->mOrigCell != cell) && (cdBefore->mColSpanData) &&
|
||||
(cdBefore->mColSpanData->mOrigCell != cell)) {
|
||||
NS_ASSERTION(PR_FALSE, "bad col span data");
|
||||
}
|
||||
printf("C ");
|
||||
|
|
|
@ -183,6 +183,13 @@ protected:
|
|||
|
||||
PRBool CreateEmptyRow(PRInt32 aRowIndex,
|
||||
PRInt32 aNumCols);
|
||||
|
||||
PRInt32 GetColSpan(PRInt32 aRowIndex,
|
||||
PRInt32 aColIndex);
|
||||
|
||||
PRInt32 GetRowSpan(PRInt32 aRowIndex,
|
||||
PRInt32 aColIndex);
|
||||
|
||||
/** an array containing col array. It can be larger than mRowCount due to
|
||||
* row spans extending beyond the table */
|
||||
nsVoidArray mRows;
|
||||
|
|
|
@ -51,6 +51,13 @@ NS_DEF_PTR(nsIStyleContext);
|
|||
static NS_DEFINE_IID(kIHTMLTableCellElementIID, NS_IHTMLTABLECELLELEMENT_IID);
|
||||
static NS_DEFINE_IID(kIDOMHTMLTableCellElementIID, NS_IDOMHTMLTABLECELLELEMENT_IID);
|
||||
|
||||
nsTableCellFrame::nsTableCellFrame()
|
||||
{
|
||||
mColIndex = 0;
|
||||
mPriorAvailWidth = 0;
|
||||
mBorderEdges = nsnull;
|
||||
}
|
||||
|
||||
nsTableCellFrame::~nsTableCellFrame()
|
||||
{
|
||||
delete mBorderEdges;
|
||||
|
@ -80,6 +87,22 @@ nsTableCellFrame::Init(nsIPresContext* aPresContext,
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTableCellFrame::AttributeChanged(nsIPresContext* aPresContext,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aHint)
|
||||
{
|
||||
// let the table frame decide what to do
|
||||
nsTableFrame* tableFrame = nsnull;
|
||||
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if ((NS_SUCCEEDED(rv)) && (tableFrame)) {
|
||||
tableFrame->AttributeChangedFor(aPresContext, this, aChild, aAttribute);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsTableCellFrame::SetPass1MaxElementSize(const nsSize& aMaxElementSize)
|
||||
{
|
||||
mPass1MaxElementSize.height = aMaxElementSize.height;
|
||||
|
@ -144,6 +167,7 @@ void nsTableCellFrame::InitCellFrame(PRInt32 aColIndex)
|
|||
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame)) {
|
||||
SetColIndex(aColIndex);
|
||||
if (NS_STYLE_BORDER_COLLAPSE == tableFrame->GetBorderCollapseStyle()) {
|
||||
if (mBorderEdges) delete mBorderEdges; // this could be non null during a reinitialization
|
||||
mBorderEdges = new nsBorderEdges;
|
||||
mBorderEdges->mOutsideEdge=PR_FALSE;
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ public:
|
|||
|
||||
// default constructor supplied by the compiler
|
||||
|
||||
nsTableCellFrame();
|
||||
~nsTableCellFrame();
|
||||
|
||||
NS_IMETHOD Init(nsIPresContext* aPresContext,
|
||||
|
@ -65,6 +66,12 @@ public:
|
|||
nsIStyleContext* aContext,
|
||||
nsIFrame* aPrevInFlow);
|
||||
|
||||
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aHint);
|
||||
|
||||
// table cells contain an area frame which does most of the work, and
|
||||
// so these functions should never be called. They assert and return
|
||||
// NS_ERROR_NOT_IMPLEMENTED
|
||||
|
|
|
@ -247,6 +247,39 @@ nsTableFrame::Destroy(nsIPresContext* aPresContext)
|
|||
return nsHTMLContainerFrame::Destroy(aPresContext);
|
||||
}
|
||||
|
||||
// Helper function. It marks the table frame as dirty and generates
|
||||
// a reflow command
|
||||
nsresult
|
||||
nsTableFrame::AddTableDirtyReflowCommand(nsIPresContext* aPresContext,
|
||||
nsIFrame* aTableFrame)
|
||||
{
|
||||
nsFrameState frameState;
|
||||
nsIFrame* tableParentFrame;
|
||||
nsIReflowCommand* reflowCmd;
|
||||
nsresult rv;
|
||||
nsIPresShell* presShell;
|
||||
|
||||
aPresContext->GetShell(&presShell);
|
||||
|
||||
// Mark the table frame as dirty
|
||||
aTableFrame->GetFrameState(&frameState);
|
||||
frameState |= NS_FRAME_IS_DIRTY;
|
||||
aTableFrame->SetFrameState(frameState);
|
||||
|
||||
// Target the reflow comamnd at its parent frame
|
||||
aTableFrame->GetParent(&tableParentFrame);
|
||||
rv = NS_NewHTMLReflowCommand(&reflowCmd, tableParentFrame,
|
||||
nsIReflowCommand::ReflowDirty);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Add the reflow command
|
||||
rv = presShell->AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
|
||||
NS_RELEASE(presShell);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// XXX this needs to be cleaned up so that the frame constructor breaks out col group
|
||||
// frames into a separate child list.
|
||||
NS_IMETHODIMP
|
||||
|
@ -315,6 +348,37 @@ nsTableFrame::SetInitialChildList(nsIPresContext* aPresContext,
|
|||
}
|
||||
|
||||
|
||||
void nsTableFrame::AttributeChangedFor(nsIPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
nsIContent* aContent,
|
||||
nsIAtom* aAttribute)
|
||||
{
|
||||
nsIAtom* frameType;
|
||||
aFrame->GetFrameType(&frameType);
|
||||
if (nsLayoutAtoms::tableCellFrame == frameType) {
|
||||
if ((nsHTMLAtoms::rowspan == aAttribute) ||
|
||||
(nsHTMLAtoms::colspan == aAttribute)) {
|
||||
nsCellMap* cellMap = GetCellMap();
|
||||
if (cellMap) {
|
||||
// for now just remove the cell from the map and reinsert it
|
||||
nsTableCellFrame* cellFrame = (nsTableCellFrame*)aFrame;
|
||||
PRInt32 rowIndex, colIndex;
|
||||
cellFrame->GetRowIndex(rowIndex);
|
||||
cellFrame->GetColIndex(colIndex);
|
||||
RemoveCell(*aPresContext, cellFrame, rowIndex);
|
||||
nsVoidArray cells;
|
||||
cells.AppendElement(cellFrame);
|
||||
InsertCells(*aPresContext, cells, rowIndex, colIndex - 1);
|
||||
// invalidate the column widths and generate a reflow command
|
||||
InvalidateColumnWidths();
|
||||
AddTableDirtyReflowCommand(aPresContext, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_IF_RELEASE(frameType);
|
||||
}
|
||||
|
||||
|
||||
/* ****** CellMap methods ******* */
|
||||
|
||||
/* counts columns in column groups */
|
||||
|
|
|
@ -106,6 +106,16 @@ public:
|
|||
nsIFrame* aPrevInFlow);
|
||||
|
||||
|
||||
static nsresult AddTableDirtyReflowCommand(nsIPresContext* aPresContext,
|
||||
nsIFrame* aTableFrame);
|
||||
/*
|
||||
* Notification that aAttribute has changed for content inside a table (cell, row, etc)
|
||||
*/
|
||||
void AttributeChangedFor(nsIPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
nsIContent* aContent,
|
||||
nsIAtom* aAttribute);
|
||||
|
||||
/** @see nsIFrame::Destroy */
|
||||
NS_IMETHOD Destroy(nsIPresContext* aPresContext);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче