зеркало из https://github.com/mozilla/gecko-dev.git
Column resizing works, and boy is it slow.
This commit is contained in:
Родитель
f67b510aa5
Коммит
963ee4f0de
|
@ -216,13 +216,7 @@ nsTreeCellFrame::HandleMouseDownEvent(nsIPresContext& aPresContext,
|
|||
treeRow->SetFlexingColumn(leftFlex);
|
||||
nsRect rect;
|
||||
GetRect(rect);
|
||||
treeRow->SetHeaderPosition(point.x + rect.x);
|
||||
|
||||
// Ensure accurate annotation
|
||||
nsTableFrame* tableFrame = nsnull;
|
||||
nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
nsTreeFrame* treeFrame = (nsTreeFrame*)tableFrame;
|
||||
treeFrame->AnnotateColumns();
|
||||
treeRow->SetHeaderPosition(point.x);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -305,22 +305,30 @@ nsTreeFrame::Reflow(nsIPresContext& aPresContext,
|
|||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
mSlatedForReflow = PR_FALSE;
|
||||
|
||||
nsRect rect;
|
||||
GetRect(rect);
|
||||
if (rect.width != aReflowState.mComputedWidth && aReflowState.reason == eReflowReason_Resize) {
|
||||
// We're doing a resize and changing the width of the table. All rows must
|
||||
// reflow. Reset our generation.
|
||||
SetUseGeneration(PR_FALSE);
|
||||
}
|
||||
if (!mSuppressReflow) {
|
||||
nsRect rect;
|
||||
GetRect(rect);
|
||||
if (rect.width != aReflowState.mComputedWidth && aReflowState.reason == eReflowReason_Resize) {
|
||||
// We're doing a resize and changing the width of the table. All rows must
|
||||
// reflow. Reset our generation.
|
||||
SetUseGeneration(PR_FALSE);
|
||||
}
|
||||
|
||||
if (UseGeneration()) {
|
||||
++mGeneration;
|
||||
if (UseGeneration()) {
|
||||
++mGeneration;
|
||||
}
|
||||
|
||||
rv = nsTableFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
}
|
||||
|
||||
nsresult rv = nsTableFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
|
||||
if (aReflowState.mComputedWidth != NS_UNCONSTRAINEDSIZE)
|
||||
aDesiredSize.width = aReflowState.mComputedWidth +
|
||||
aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right;
|
||||
|
@ -342,31 +350,35 @@ nsTreeFrame::DidReflow(nsIPresContext& aPresContext,
|
|||
nsDidReflowStatus aStatus)
|
||||
{
|
||||
nsresult rv = nsTableFrame::DidReflow(aPresContext, aStatus);
|
||||
if (mNeedsDirtyReflow) {
|
||||
mNeedsDirtyReflow = PR_FALSE;
|
||||
InvalidateCellMap();
|
||||
InvalidateColumnCache();
|
||||
InvalidateFirstPassCache();
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
aPresContext.GetShell(getter_AddRefs(shell));
|
||||
nsFrameState frameState;
|
||||
nsIFrame* tableParentFrame;
|
||||
nsIReflowCommand* reflowCmd;
|
||||
|
||||
// Mark the table frame as dirty
|
||||
GetFrameState(&frameState);
|
||||
frameState |= NS_FRAME_IS_DIRTY;
|
||||
SetFrameState(frameState);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Target the reflow comamnd at its parent frame
|
||||
GetParent(&tableParentFrame);
|
||||
rv = NS_NewHTMLReflowCommand(&reflowCmd, tableParentFrame,
|
||||
nsIReflowCommand::ReflowDirty);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Add the reflow command
|
||||
rv = shell->AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsTreeFrame::MarkForDirtyReflow(nsIPresContext& aPresContext)
|
||||
{
|
||||
mSuppressReflow = PR_FALSE;
|
||||
InvalidateCellMap();
|
||||
InvalidateColumnCache();
|
||||
InvalidateFirstPassCache();
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
aPresContext.GetShell(getter_AddRefs(shell));
|
||||
nsFrameState frameState;
|
||||
nsIFrame* tableParentFrame;
|
||||
nsIReflowCommand* reflowCmd;
|
||||
|
||||
// Mark the table frame as dirty
|
||||
GetFrameState(&frameState);
|
||||
frameState |= NS_FRAME_IS_DIRTY;
|
||||
SetFrameState(frameState);
|
||||
|
||||
// Target the reflow comamnd at its parent frame
|
||||
GetParent(&tableParentFrame);
|
||||
nsresult rv = NS_NewHTMLReflowCommand(&reflowCmd, tableParentFrame,
|
||||
nsIReflowCommand::ReflowDirty);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Add the reflow command
|
||||
rv = shell->AppendReflowCommand(reflowCmd);
|
||||
NS_RELEASE(reflowCmd);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -390,35 +402,6 @@ nsTreeFrame::Init(nsIPresContext& aPresContext,
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTreeFrame::AnnotateColumns()
|
||||
{
|
||||
// Iterate over the column frames and set proportional width attributes on all flexible
|
||||
// columns.
|
||||
PRInt32 columnCount = GetColCount();
|
||||
for (PRInt32 i = 0; i < columnCount; i++) {
|
||||
nsTableColFrame* result = GetColFrame(i);
|
||||
nsCOMPtr<nsIContent> colContent;
|
||||
result->GetContent(getter_AddRefs(colContent));
|
||||
nsCOMPtr<nsIAtom> fixedAtom = dont_AddRef(NS_NewAtom("fixed"));
|
||||
if (colContent) {
|
||||
nsAutoString fixedValue;
|
||||
colContent->GetAttribute(kNameSpaceID_None, fixedAtom, fixedValue);
|
||||
if (fixedValue != "true") {
|
||||
// We are a proportional column and should be annotated with our current
|
||||
// width.
|
||||
PRInt32 colWidth = GetColumnWidth(i);
|
||||
char ch[100];
|
||||
sprintf(ch,"%d*", colWidth);
|
||||
nsAutoString propColWidth(ch);
|
||||
colContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, propColWidth,
|
||||
PR_FALSE); // Suppress a notification.
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsTreeFrame::ContainsFlexibleColumn(PRInt32 aStartIndex, PRInt32 aEndIndex,
|
||||
nsTableColFrame** aResult)
|
||||
|
|
|
@ -65,17 +65,19 @@ public:
|
|||
NS_IMETHOD DidReflow(nsIPresContext& aPresContext,
|
||||
nsDidReflowStatus aStatus);
|
||||
|
||||
void WillNeedDirtyReflow() { mNeedsDirtyReflow = PR_TRUE; };
|
||||
PRInt32 GetCurrentGeneration() { return mGeneration; };
|
||||
void SetCurrentGeneration(PRInt32 aGeneration) { mGeneration = aGeneration; };
|
||||
|
||||
PRBool UseGeneration() { return mUseGeneration; };
|
||||
void SetUseGeneration(PRBool aUse) { mUseGeneration = aUse; };
|
||||
|
||||
NS_IMETHOD AnnotateColumns();
|
||||
|
||||
PRBool ContainsFlexibleColumn(PRInt32 aStartIndex, PRInt32 aEndIndex, nsTableColFrame** aResult);
|
||||
|
||||
NS_IMETHOD MarkForDirtyReflow(nsIPresContext& aPresContext);
|
||||
|
||||
void SuppressReflow() { mSuppressReflow = PR_TRUE; };
|
||||
void UnsuppressReflow() { mSuppressReflow = PR_FALSE; };
|
||||
|
||||
protected:
|
||||
nsTreeFrame();
|
||||
virtual ~nsTreeFrame();
|
||||
|
@ -83,7 +85,7 @@ protected:
|
|||
protected: // Data Members
|
||||
PRBool mSlatedForReflow; // If set, don't waste time scheduling excess reflows.
|
||||
nsTreeTwistyListener* mTwistyListener;
|
||||
PRBool mNeedsDirtyReflow;
|
||||
PRInt32 mGeneration;
|
||||
PRBool mUseGeneration;
|
||||
PRBool mSuppressReflow;
|
||||
}; // class nsTreeFrame
|
||||
|
|
|
@ -208,20 +208,6 @@ nsTreeRowFrame::HandleMouseUpEvent(nsIPresContext& aPresContext,
|
|||
{
|
||||
if (DraggingHeader()) {
|
||||
HeaderDrag(PR_FALSE);
|
||||
|
||||
nsTableFrame* tableFrame = nsnull;
|
||||
nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
nsTreeFrame* treeFrame = (nsTreeFrame*)tableFrame;
|
||||
treeFrame->SetUseGeneration(PR_FALSE); // Cached rows have to reflow.
|
||||
|
||||
nsCellMap* cellMap = tableFrame->GetCellMap();
|
||||
PRInt32 numCols = cellMap->GetColCount();
|
||||
nsTableColFrame* colFrame = tableFrame->GetColFrame(0);
|
||||
nsCOMPtr<nsIContent> colElement;
|
||||
colFrame->GetContent(getter_AddRefs(colElement));
|
||||
if (colElement) {
|
||||
colElement->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, "40", PR_TRUE);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -249,7 +235,7 @@ nsTreeRowFrame::GetFrameForPoint(const nsPoint& aPoint, // Overridden to capture
|
|||
*aFrame = this;
|
||||
nsRect rect;
|
||||
GetRect(rect);
|
||||
if (rect.Contains(aPoint)) {
|
||||
if (!rect.Contains(aPoint)) {
|
||||
mHitFrame = nsnull;
|
||||
}
|
||||
}
|
||||
|
@ -284,7 +270,51 @@ nsTreeRowFrame::HandleHeaderDragEvent(nsIPresContext& aPresContext,
|
|||
// Grab our tree frame.
|
||||
nsTableFrame* tableFrame = nsnull;
|
||||
nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
nsTreeFrame* treeFrame = (nsTreeFrame*)tableFrame;
|
||||
|
||||
// Until we finish all of our batched operations, suppress all reflow.
|
||||
treeFrame->SuppressReflow();
|
||||
|
||||
PRInt32 columnCount = treeFrame->GetColCount();
|
||||
PRInt32* colWidths = new PRInt32[columnCount];
|
||||
nsCRT::memset(colWidths, 0, columnCount*sizeof(PRInt32));
|
||||
|
||||
// Retrieve our column widths.
|
||||
PRInt32 i;
|
||||
for (i = 0; i < columnCount; i++) {
|
||||
nsTableColFrame* result = treeFrame->GetColFrame(i);
|
||||
nsCOMPtr<nsIContent> colContent;
|
||||
result->GetContent(getter_AddRefs(colContent));
|
||||
nsCOMPtr<nsIAtom> fixedAtom = dont_AddRef(NS_NewAtom("fixed"));
|
||||
if (colContent) {
|
||||
nsAutoString fixedValue;
|
||||
colContent->GetAttribute(kNameSpaceID_None, fixedAtom, fixedValue);
|
||||
if (fixedValue != "true") {
|
||||
// We are a proportional column and should be annotated with our current
|
||||
// width.
|
||||
PRInt32 colWidth = treeFrame->GetColumnWidth(i);
|
||||
colWidths[i] = colWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Annotate with the current proportions
|
||||
for (i = 0; i < columnCount; i++) {
|
||||
if (colWidths[i] > 0) {
|
||||
nsTableColFrame* result = treeFrame->GetColFrame(i);
|
||||
nsCOMPtr<nsIContent> colContent;
|
||||
result->GetContent(getter_AddRefs(colContent));
|
||||
if (colContent) {
|
||||
PRInt32 colWidth = colWidths[i];
|
||||
char ch[100];
|
||||
sprintf(ch,"%d*", colWidth);
|
||||
nsAutoString propColWidth(ch);
|
||||
colContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, propColWidth,
|
||||
PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Figure out how much we shifted the mouse.
|
||||
char ch[100];
|
||||
nsPoint point = ((nsMouseEvent*)aEvent)->point;
|
||||
|
@ -293,82 +323,83 @@ nsTreeRowFrame::HandleHeaderDragEvent(nsIPresContext& aPresContext,
|
|||
|
||||
// The proportional columns to the right will gain or lose space
|
||||
// according to the percentages they currently consume.
|
||||
PRInt32 numCols = tableFrame->GetColCount();
|
||||
nscoord* propInfo = new PRInt32[numCols];
|
||||
nsCRT::memset(propInfo, 0, numCols*sizeof(nscoord));
|
||||
nscoord propTotal = 0;
|
||||
|
||||
// For every column, determine its proportional width
|
||||
// Find our flexing col and note its index and width.
|
||||
PRInt32 colX;
|
||||
for (colX = 0; colX < numCols; colX++) {
|
||||
PRInt32 flexWidth = 0;
|
||||
PRInt32 flexIndex;
|
||||
for (colX = 0; colX < columnCount; colX++) {
|
||||
// Get column information
|
||||
nsTableColFrame* colFrame = tableFrame->GetColFrame(colX);
|
||||
if (colFrame == mFlexingCol)
|
||||
if (colFrame == mFlexingCol) {
|
||||
flexWidth = colWidths[colX];
|
||||
flexIndex = colX;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
colX++;
|
||||
for ( ; colX < numCols; colX++) {
|
||||
|
||||
for (colX = flexIndex+1; colX < columnCount; colX++) {
|
||||
// Retrieve the current widths for these columns and compute
|
||||
// the total amount of space they occupy.
|
||||
nsTableColFrame* colFrame = tableFrame->GetColFrame(colX);
|
||||
|
||||
// Get the column's width from the corresponding child cell in the header.
|
||||
nsCOMPtr<nsIContent> colContent;
|
||||
colFrame->GetContent(getter_AddRefs(colContent));
|
||||
|
||||
nsCOMPtr<nsIAtom> fixedAtom = dont_AddRef(NS_NewAtom("fixed"));
|
||||
nsAutoString fixedVal;
|
||||
colContent->GetAttribute(kNameSpaceID_None, fixedAtom, fixedVal);
|
||||
if (fixedVal != "true") {
|
||||
PRInt32 colWidth = tableFrame->GetColumnWidth(colX);
|
||||
propInfo[colX] = colWidth;
|
||||
propTotal += propInfo[colX];
|
||||
}
|
||||
propTotal += colWidths[colX];
|
||||
}
|
||||
|
||||
// Iterate over the columns to the right of the flexing column,
|
||||
// and give them a percentage of the delta based off their proportions.
|
||||
nsCOMPtr<nsIContent> colContent;
|
||||
nsTableColFrame* colFrame;
|
||||
PRInt32 colWidth;
|
||||
PRInt32 remaining = delta;
|
||||
for (colX = 0; colX < numCols; colX++) {
|
||||
if (propInfo[colX] > 0) {
|
||||
nsTableColFrame* colFrame = tableFrame->GetColFrame(colX);
|
||||
float percentage = ((float)propInfo[colX])/((float)propTotal);
|
||||
for (colX = flexIndex+1; colX < columnCount; colX++) {
|
||||
if (colWidths[colX] > 0) {
|
||||
colFrame = tableFrame->GetColFrame(colX);
|
||||
float percentage = ((float)colWidths[colX])/((float)propTotal);
|
||||
PRInt32 mod = (PRInt32)(percentage * (float)delta);
|
||||
PRInt32 colWidth = propInfo[colX] + mod;
|
||||
colWidth = colWidths[colX] + mod;
|
||||
|
||||
sprintf(ch,"%d*", colWidth);
|
||||
nsAutoString propColWidth(ch);
|
||||
|
||||
colFrame->GetContent(getter_AddRefs(colContent));
|
||||
if (colContent)
|
||||
if (colContent) {
|
||||
colContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, propColWidth,
|
||||
PR_FALSE); // Suppress a notification.
|
||||
PR_TRUE);
|
||||
}
|
||||
|
||||
remaining -= mod;
|
||||
}
|
||||
}
|
||||
|
||||
// Fix the spillover. We'll probably be off by a little.
|
||||
if (remaining != 0 && colContent) {
|
||||
sprintf(ch,"%d*", remaining);
|
||||
colWidth += remaining;
|
||||
sprintf(ch,"%d*", colWidth);
|
||||
nsAutoString propColWidth(ch);
|
||||
colContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, propColWidth,
|
||||
PR_FALSE); // Suppress a notification.
|
||||
PR_TRUE);
|
||||
|
||||
}
|
||||
|
||||
// Delete the propInfo array.
|
||||
delete [] propInfo;
|
||||
|
||||
// Delete the colWidths array.
|
||||
delete []colWidths;
|
||||
|
||||
// Modify the flexing column by the delta.
|
||||
nsCOMPtr<nsIContent> flexContent;
|
||||
mFlexingCol->GetContent(getter_AddRefs(flexContent));
|
||||
if (flexContent) {
|
||||
sprintf(ch,"%d*", delta);
|
||||
treeFrame->SetUseGeneration(PR_FALSE); // Cached rows have to reflow.
|
||||
treeFrame->UnsuppressReflow();
|
||||
|
||||
PRInt32 colWidth = flexWidth - delta;
|
||||
sprintf(ch,"%d*", colWidth);
|
||||
nsAutoString propColWidth(ch);
|
||||
flexContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, propColWidth,
|
||||
PR_TRUE); // NOW we send the notification that causes the reflow.
|
||||
|
||||
// Do a dirty table reflow.
|
||||
//treeFrame->MarkForDirtyReflow(aPresContext);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
Загрузка…
Ссылка в новой задаче