Fix for 73506. r=danm, sr=mscott

This commit is contained in:
hyatt%netscape.com 2001-03-28 22:45:43 +00:00
Родитель c2f73cbddd
Коммит 43fbb26cff
9 изменённых файлов: 377 добавлений и 76 удалений

Просмотреть файл

@ -78,8 +78,10 @@ interface nsIOutlinerBoxObject : nsISupports
void invalidateRange(in long startIndex, in long endIndex);
void invalidateScrollbar();
// A hit test that can tell you what cell the mouse is over.
void getCellAt(in long x, in long y, out long row, out wstring colID);
// A hit test that can tell you what cell the mouse is over. Row is the row index
// hit. ColID is the column hit. ChildElt is the pseudoelement hit: this can have
// values of "cell", "twisty", "image", and "text".
void getCellAt(in long x, in long y, out long row, out wstring colID, out wstring childElt);
// The view is responsible for calling these notification methods when
// rows are added or removed. Index is the position at which the new

Просмотреть файл

@ -329,6 +329,16 @@ NS_IMETHODIMP nsOutlinerBodyFrame::Reflow(nsIPresContext* aPresContext,
return NS_OK;
}
static void
AdjustForBorderPadding(nsIStyleContext* aContext, nsRect& aRect)
{
nsMargin m(0,0,0,0);
nsStyleBorderPadding bPad;
aContext->GetStyle(eStyleStruct_BorderPaddingShortcut, (nsStyleStruct&)bPad);
bPad.GetBorderPadding(m);
aRect.Deflate(m);
}
NS_IMETHODIMP nsOutlinerBodyFrame::GetView(nsIOutlinerView * *aView)
{
*aView = mView;
@ -547,7 +557,8 @@ NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateScrollbar()
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBodyFrame::GetCellAt(PRInt32 aX, PRInt32 aY, PRInt32* aRow, PRUnichar** aColID)
NS_IMETHODIMP nsOutlinerBodyFrame::GetCellAt(PRInt32 aX, PRInt32 aY, PRInt32* aRow, PRUnichar** aColID,
PRUnichar** aChildElt)
{
// Ensure we have a row height.
if (mRowHeight == 0)
@ -591,19 +602,156 @@ NS_IMETHODIMP nsOutlinerBodyFrame::GetCellAt(PRInt32 aX, PRInt32 aY, PRInt32* aR
nscoord currX = mInnerBox.x;
for (nsOutlinerColumn* currCol = mColumns; currCol && currX < mInnerBox.x+mInnerBox.width;
currCol = currCol->GetNext()) {
nsRect colRect(currX, mInnerBox.y, currCol->GetWidth(), mInnerBox.height);
PRInt32 overflow = colRect.x+colRect.width-(mInnerBox.x+mInnerBox.width);
nsRect cellRect(currX, mInnerBox.y+mRowHeight*(*aRow-mTopRowIndex), currCol->GetWidth(), mRowHeight);
PRInt32 overflow = cellRect.x+cellRect.width-(mInnerBox.x+mInnerBox.width);
if (overflow > 0)
colRect.width -= overflow;
cellRect.width -= overflow;
if (x >= colRect.x && x < colRect.x + colRect.width)
if (x >= cellRect.x && x < cellRect.x + cellRect.width) {
// We know the column hit now.
*aColID = nsXPIDLString::Copy(currCol->GetID());
currX += colRect.width;
if (currCol->IsCycler()) {
// Cyclers contain only images. Fill this in immediately and return.
nsAutoString image; image.AssignWithConversion("image");
*aChildElt = nsXPIDLString::Copy(image.GetUnicode());
}
else
GetItemWithinCellAt(x, cellRect, *aRow, currCol, aChildElt);
break;
}
currX += cellRect.width;
}
return NS_OK;
}
nsresult
nsOutlinerBodyFrame::GetItemWithinCellAt(PRInt32 aX, const nsRect& aCellRect,
PRInt32 aRowIndex,
nsOutlinerColumn* aColumn, PRUnichar** aChildElt)
{
// Obtain the properties for our cell.
PrefillPropertyArray(aRowIndex, aColumn);
mView->GetCellProperties(aRowIndex, aColumn->GetID(), mScratchArray);
// Resolve style for the cell.
nsCOMPtr<nsIStyleContext> cellContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinercell, getter_AddRefs(cellContext));
// Obtain the margins for the cell and then deflate our rect by that
// amount. The cell is assumed to be contained within the deflated rect.
nsRect cellRect(aCellRect);
const nsStyleMargin* cellMarginData = (const nsStyleMargin*)cellContext->GetStyleData(eStyleStruct_Margin);
nsMargin cellMargin;
cellMarginData->GetMargin(cellMargin);
cellRect.Deflate(cellMargin);
// Adjust the rect for its border and padding.
AdjustForBorderPadding(cellContext, cellRect);
if (aX < cellRect.x || aX >= cellRect.x + cellRect.width) {
// The user clicked within the cell's margins/borders/padding. This constitutes a click on the cell.
nsAutoString cell; cell.AssignWithConversion("cell");
*aChildElt = nsXPIDLString::Copy(cell.GetUnicode());
return NS_OK;
}
nscoord currX = cellRect.x;
nscoord remainingWidth = cellRect.width;
// XXX Handle right alignment hit testing.
if (aColumn->IsPrimary()) {
// If we're the primary column, we have indentation and a twisty.
PRInt32 level;
mView->GetLevel(aRowIndex, &level);
currX += mIndentation*level;
remainingWidth -= mIndentation*level;
if (aX < currX) {
// The user clicked within the indentation.
nsAutoString cell; cell.AssignWithConversion("cell");
*aChildElt = nsXPIDLString::Copy(cell.GetUnicode());
return NS_OK;
}
// Always leave space for the twisty.
nsRect twistyRect(currX, cellRect.y, remainingWidth, cellRect.height);
PRBool hasTwisty = PR_FALSE;
PRBool isContainer = PR_FALSE;
mView->IsContainer(aRowIndex, &isContainer);
if (isContainer) {
PRBool isContainerEmpty = PR_FALSE;
mView->IsContainerEmpty(aRowIndex, &isContainerEmpty);
if (!isContainerEmpty)
hasTwisty = PR_TRUE;
}
// Resolve style for the twisty.
nsCOMPtr<nsIStyleContext> twistyContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinertwisty, getter_AddRefs(twistyContext));
// We will treat a click as hitting the twisty if it happens on the margins, borders, padding,
// or content of the twisty object. By allowing a "slop" into the margin, we make it a little
// bit easier for a user to hit the twisty. (We don't want to be too picky here.)
nsRect imageSize = GetImageSize(twistyContext);
const nsStyleMargin* twistyMarginData = (const nsStyleMargin*)twistyContext->GetStyleData(eStyleStruct_Margin);
nsMargin twistyMargin;
twistyMarginData->GetMargin(twistyMargin);
imageSize.Inflate(twistyMargin);
twistyRect.width = imageSize.width;
// Now we test to see if aX is actually within the twistyRect. If it is, and if the item should
// have a twisty, then we return "twisty". If it is within the rect but we shouldn't have a twisty,
// then we return "cell".
if (aX >= twistyRect.x && aX < twistyRect.x + twistyRect.width) {
if (hasTwisty) {
nsAutoString twisty; twisty.AssignWithConversion("twisty");
*aChildElt = nsXPIDLString::Copy(twisty.GetUnicode());
}
else {
nsAutoString cell; cell.AssignWithConversion("cell");
*aChildElt = nsXPIDLString::Copy(cell.GetUnicode());
}
return NS_OK;
}
currX += twistyRect.width;
remainingWidth -= twistyRect.width;
}
// Now test to see if the user hit the icon for the cell.
nsRect iconRect(currX, cellRect.y, remainingWidth, cellRect.height);
// Resolve style for the image.
nsCOMPtr<nsIStyleContext> imageContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
nsRect iconSize = GetImageSize(imageContext);
const nsStyleMargin* imageMarginData = (const nsStyleMargin*)imageContext->GetStyleData(eStyleStruct_Margin);
nsMargin imageMargin;
imageMarginData->GetMargin(imageMargin);
iconSize.Inflate(imageMargin);
iconRect.width = iconSize.width;
if (aX >= iconRect.x && aX < iconRect.x + iconRect.width) {
// The user clicked on the image.
nsAutoString image; image.AssignWithConversion("image");
*aChildElt = nsXPIDLString::Copy(image.GetUnicode());
return NS_OK;
}
// Just assume "text".
// XXX For marquee selection, we'll have to make this more precise and do text measurement.
nsAutoString text; text.AssignWithConversion("text");
*aChildElt = nsXPIDLString::Copy(text.GetUnicode());
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBodyFrame::RowCountChanged(PRInt32 aIndex, PRInt32 aCount)
{
if (aCount == 0)
@ -854,7 +1002,7 @@ PRInt32 nsOutlinerBodyFrame::GetRowHeight()
// + the specified margins.
nsCOMPtr<nsIStyleContext> rowContext;
mScratchArray->Clear();
GetPseudoStyleContext(mPresContext, nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
if (rowContext) {
const nsStylePosition* myPosition = (const nsStylePosition*)
rowContext->GetStyleData(eStyleStruct_Position);
@ -881,7 +1029,7 @@ PRInt32 nsOutlinerBodyFrame::GetIndentation()
// Look up the correct indentation. It is equal to the specified indentation width.
nsCOMPtr<nsIStyleContext> indentContext;
mScratchArray->Clear();
GetPseudoStyleContext(mPresContext, nsXULAtoms::mozoutlinerindentation, getter_AddRefs(indentContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinerindentation, getter_AddRefs(indentContext));
if (indentContext) {
const nsStylePosition* myPosition = (const nsStylePosition*)
indentContext->GetStyleData(eStyleStruct_Position);
@ -904,16 +1052,6 @@ nsRect nsOutlinerBodyFrame::GetInnerBox()
return r;
}
static void
AdjustForBorderPadding(nsIStyleContext* aContext, nsRect& aRect)
{
nsMargin m(0,0,0,0);
nsStyleBorderPadding bPad;
aContext->GetStyle(eStyleStruct_BorderPaddingShortcut, (nsStyleStruct&)bPad);
bPad.GetBorderPadding(m);
aRect.Deflate(m);
}
// Painting routines
NS_IMETHODIMP nsOutlinerBodyFrame::Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -1019,7 +1157,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintColumn(nsOutlinerColumn* aColumn,
// Resolve style for the column. It contains all the info we need to lay ourselves
// out and to paint.
nsCOMPtr<nsIStyleContext> colContext;
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinercolumn, getter_AddRefs(colContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinercolumn, getter_AddRefs(colContext));
// Obtain the margins for the cell and then deflate our rect by that
// amount. The cell is assumed to be contained within the deflated rect.
@ -1055,7 +1193,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintRow(int aRowIndex, const nsRect& aRowRec
// Resolve style for the row. It contains all the info we need to lay ourselves
// out and to paint.
nsCOMPtr<nsIStyleContext> rowContext;
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
// Obtain the margins for the row and then deflate our rect by that
// amount. The row is assumed to be contained within the deflated rect.
@ -1110,7 +1248,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintCell(int aRowIndex,
// Resolve style for the cell. It contains all the info we need to lay ourselves
// out and to paint.
nsCOMPtr<nsIStyleContext> cellContext;
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinercell, getter_AddRefs(cellContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinercell, getter_AddRefs(cellContext));
// Obtain the margins for the cell and then deflate our rect by that
// amount. The cell is assumed to be contained within the deflated rect.
@ -1148,7 +1286,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintCell(int aRowIndex,
// Resolve the style to use for the connecting lines.
nsCOMPtr<nsIStyleContext> lineContext;
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinerline, getter_AddRefs(lineContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinerline, getter_AddRefs(lineContext));
const nsStyleDisplay* displayStyle = (const nsStyleDisplay*)lineContext->GetStyleData(eStyleStruct_Display);
if (displayStyle->IsVisibleOrCollapsed() && level && NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
@ -1244,7 +1382,7 @@ nsOutlinerBodyFrame::PaintTwisty(int aRowIndex,
// Resolve style for the twisty.
nsCOMPtr<nsIStyleContext> twistyContext;
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinertwisty, getter_AddRefs(twistyContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinertwisty, getter_AddRefs(twistyContext));
// Obtain the margins for the twisty and then deflate our rect by that
// amount. The twisty is assumed to be contained within the deflated rect.
@ -1316,7 +1454,7 @@ nsOutlinerBodyFrame::PaintImage(int aRowIndex,
{
// Resolve style for the image.
nsCOMPtr<nsIStyleContext> imageContext;
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
// Obtain the margins for the twisty and then deflate our rect by that
// amount. The twisty is assumed to be contained within the deflated rect.
@ -1401,7 +1539,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintText(int aRowIndex,
// Resolve style for the text. It contains all the info we need to lay ourselves
// out and to paint.
nsCOMPtr<nsIStyleContext> textContext;
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinercelltext, getter_AddRefs(textContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinercelltext, getter_AddRefs(textContext));
// Obtain the margins for the text and then deflate our rect by that
// amount. The text is assumed to be contained within the deflated rect.
@ -1697,10 +1835,10 @@ nsOutlinerBodyFrame::PositionChanged(PRInt32 aOldIndex, PRInt32& aNewIndex)
// The style cache.
nsresult
nsOutlinerBodyFrame::GetPseudoStyleContext(nsIPresContext* aPresContext, nsIAtom* aPseudoElement,
nsOutlinerBodyFrame::GetPseudoStyleContext(nsIAtom* aPseudoElement,
nsIStyleContext** aResult)
{
return mStyleCache.GetStyleContext(this, aPresContext, mContent, mStyleContext, aPseudoElement,
return mStyleCache.GetStyleContext(this, mPresContext, mContent, mStyleContext, aPseudoElement,
mScratchArray, aResult);
}

Просмотреть файл

@ -303,6 +303,10 @@ protected:
// Caches our box object.
void SetBoxObject(nsIOutlinerBoxObject* aBoxObject) { mOutlinerBoxObject = aBoxObject; };
// A helper used when hit testing.
nsresult GetItemWithinCellAt(PRInt32 aX, const nsRect& aCellRect, PRInt32 aRowIndex,
nsOutlinerColumn* aColumn, PRUnichar** aChildElt);
#ifdef USE_IMG2
// Fetch an image from the image cache.
nsresult GetImage(PRInt32 aRowIndex, const PRUnichar* aColID,
@ -324,7 +328,7 @@ protected:
// Looks up a style context in the style cache. On a cache miss we resolve
// the pseudo-styles passed in and place them into the cache.
nsresult GetPseudoStyleContext(nsIPresContext* aPresContext, nsIAtom* aPseudoElement, nsIStyleContext** aResult);
nsresult GetPseudoStyleContext(nsIAtom* aPseudoElement, nsIStyleContext** aResult);
// Builds our cache of column info.
void EnsureColumns();

Просмотреть файл

@ -280,11 +280,12 @@ NS_IMETHODIMP nsOutlinerBoxObject::InvalidateScrollbar()
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBoxObject::GetCellAt(PRInt32 x, PRInt32 y, PRInt32 *row, PRUnichar **colID)
NS_IMETHODIMP nsOutlinerBoxObject::GetCellAt(PRInt32 x, PRInt32 y, PRInt32 *row, PRUnichar **colID,
PRUnichar** childElt)
{
nsIOutlinerBoxObject* body = GetOutlinerBody();
if (body)
return body->GetCellAt(x, y, row, colID);
return body->GetCellAt(x, y, row, colID, childElt);
return NS_OK;
}

Просмотреть файл

@ -78,8 +78,10 @@ interface nsIOutlinerBoxObject : nsISupports
void invalidateRange(in long startIndex, in long endIndex);
void invalidateScrollbar();
// A hit test that can tell you what cell the mouse is over.
void getCellAt(in long x, in long y, out long row, out wstring colID);
// A hit test that can tell you what cell the mouse is over. Row is the row index
// hit. ColID is the column hit. ChildElt is the pseudoelement hit: this can have
// values of "cell", "twisty", "image", and "text".
void getCellAt(in long x, in long y, out long row, out wstring colID, out wstring childElt);
// The view is responsible for calling these notification methods when
// rows are added or removed. Index is the position at which the new

Просмотреть файл

@ -329,6 +329,16 @@ NS_IMETHODIMP nsOutlinerBodyFrame::Reflow(nsIPresContext* aPresContext,
return NS_OK;
}
static void
AdjustForBorderPadding(nsIStyleContext* aContext, nsRect& aRect)
{
nsMargin m(0,0,0,0);
nsStyleBorderPadding bPad;
aContext->GetStyle(eStyleStruct_BorderPaddingShortcut, (nsStyleStruct&)bPad);
bPad.GetBorderPadding(m);
aRect.Deflate(m);
}
NS_IMETHODIMP nsOutlinerBodyFrame::GetView(nsIOutlinerView * *aView)
{
*aView = mView;
@ -547,7 +557,8 @@ NS_IMETHODIMP nsOutlinerBodyFrame::InvalidateScrollbar()
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBodyFrame::GetCellAt(PRInt32 aX, PRInt32 aY, PRInt32* aRow, PRUnichar** aColID)
NS_IMETHODIMP nsOutlinerBodyFrame::GetCellAt(PRInt32 aX, PRInt32 aY, PRInt32* aRow, PRUnichar** aColID,
PRUnichar** aChildElt)
{
// Ensure we have a row height.
if (mRowHeight == 0)
@ -591,19 +602,156 @@ NS_IMETHODIMP nsOutlinerBodyFrame::GetCellAt(PRInt32 aX, PRInt32 aY, PRInt32* aR
nscoord currX = mInnerBox.x;
for (nsOutlinerColumn* currCol = mColumns; currCol && currX < mInnerBox.x+mInnerBox.width;
currCol = currCol->GetNext()) {
nsRect colRect(currX, mInnerBox.y, currCol->GetWidth(), mInnerBox.height);
PRInt32 overflow = colRect.x+colRect.width-(mInnerBox.x+mInnerBox.width);
nsRect cellRect(currX, mInnerBox.y+mRowHeight*(*aRow-mTopRowIndex), currCol->GetWidth(), mRowHeight);
PRInt32 overflow = cellRect.x+cellRect.width-(mInnerBox.x+mInnerBox.width);
if (overflow > 0)
colRect.width -= overflow;
cellRect.width -= overflow;
if (x >= colRect.x && x < colRect.x + colRect.width)
if (x >= cellRect.x && x < cellRect.x + cellRect.width) {
// We know the column hit now.
*aColID = nsXPIDLString::Copy(currCol->GetID());
currX += colRect.width;
if (currCol->IsCycler()) {
// Cyclers contain only images. Fill this in immediately and return.
nsAutoString image; image.AssignWithConversion("image");
*aChildElt = nsXPIDLString::Copy(image.GetUnicode());
}
else
GetItemWithinCellAt(x, cellRect, *aRow, currCol, aChildElt);
break;
}
currX += cellRect.width;
}
return NS_OK;
}
nsresult
nsOutlinerBodyFrame::GetItemWithinCellAt(PRInt32 aX, const nsRect& aCellRect,
PRInt32 aRowIndex,
nsOutlinerColumn* aColumn, PRUnichar** aChildElt)
{
// Obtain the properties for our cell.
PrefillPropertyArray(aRowIndex, aColumn);
mView->GetCellProperties(aRowIndex, aColumn->GetID(), mScratchArray);
// Resolve style for the cell.
nsCOMPtr<nsIStyleContext> cellContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinercell, getter_AddRefs(cellContext));
// Obtain the margins for the cell and then deflate our rect by that
// amount. The cell is assumed to be contained within the deflated rect.
nsRect cellRect(aCellRect);
const nsStyleMargin* cellMarginData = (const nsStyleMargin*)cellContext->GetStyleData(eStyleStruct_Margin);
nsMargin cellMargin;
cellMarginData->GetMargin(cellMargin);
cellRect.Deflate(cellMargin);
// Adjust the rect for its border and padding.
AdjustForBorderPadding(cellContext, cellRect);
if (aX < cellRect.x || aX >= cellRect.x + cellRect.width) {
// The user clicked within the cell's margins/borders/padding. This constitutes a click on the cell.
nsAutoString cell; cell.AssignWithConversion("cell");
*aChildElt = nsXPIDLString::Copy(cell.GetUnicode());
return NS_OK;
}
nscoord currX = cellRect.x;
nscoord remainingWidth = cellRect.width;
// XXX Handle right alignment hit testing.
if (aColumn->IsPrimary()) {
// If we're the primary column, we have indentation and a twisty.
PRInt32 level;
mView->GetLevel(aRowIndex, &level);
currX += mIndentation*level;
remainingWidth -= mIndentation*level;
if (aX < currX) {
// The user clicked within the indentation.
nsAutoString cell; cell.AssignWithConversion("cell");
*aChildElt = nsXPIDLString::Copy(cell.GetUnicode());
return NS_OK;
}
// Always leave space for the twisty.
nsRect twistyRect(currX, cellRect.y, remainingWidth, cellRect.height);
PRBool hasTwisty = PR_FALSE;
PRBool isContainer = PR_FALSE;
mView->IsContainer(aRowIndex, &isContainer);
if (isContainer) {
PRBool isContainerEmpty = PR_FALSE;
mView->IsContainerEmpty(aRowIndex, &isContainerEmpty);
if (!isContainerEmpty)
hasTwisty = PR_TRUE;
}
// Resolve style for the twisty.
nsCOMPtr<nsIStyleContext> twistyContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinertwisty, getter_AddRefs(twistyContext));
// We will treat a click as hitting the twisty if it happens on the margins, borders, padding,
// or content of the twisty object. By allowing a "slop" into the margin, we make it a little
// bit easier for a user to hit the twisty. (We don't want to be too picky here.)
nsRect imageSize = GetImageSize(twistyContext);
const nsStyleMargin* twistyMarginData = (const nsStyleMargin*)twistyContext->GetStyleData(eStyleStruct_Margin);
nsMargin twistyMargin;
twistyMarginData->GetMargin(twistyMargin);
imageSize.Inflate(twistyMargin);
twistyRect.width = imageSize.width;
// Now we test to see if aX is actually within the twistyRect. If it is, and if the item should
// have a twisty, then we return "twisty". If it is within the rect but we shouldn't have a twisty,
// then we return "cell".
if (aX >= twistyRect.x && aX < twistyRect.x + twistyRect.width) {
if (hasTwisty) {
nsAutoString twisty; twisty.AssignWithConversion("twisty");
*aChildElt = nsXPIDLString::Copy(twisty.GetUnicode());
}
else {
nsAutoString cell; cell.AssignWithConversion("cell");
*aChildElt = nsXPIDLString::Copy(cell.GetUnicode());
}
return NS_OK;
}
currX += twistyRect.width;
remainingWidth -= twistyRect.width;
}
// Now test to see if the user hit the icon for the cell.
nsRect iconRect(currX, cellRect.y, remainingWidth, cellRect.height);
// Resolve style for the image.
nsCOMPtr<nsIStyleContext> imageContext;
GetPseudoStyleContext(nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
nsRect iconSize = GetImageSize(imageContext);
const nsStyleMargin* imageMarginData = (const nsStyleMargin*)imageContext->GetStyleData(eStyleStruct_Margin);
nsMargin imageMargin;
imageMarginData->GetMargin(imageMargin);
iconSize.Inflate(imageMargin);
iconRect.width = iconSize.width;
if (aX >= iconRect.x && aX < iconRect.x + iconRect.width) {
// The user clicked on the image.
nsAutoString image; image.AssignWithConversion("image");
*aChildElt = nsXPIDLString::Copy(image.GetUnicode());
return NS_OK;
}
// Just assume "text".
// XXX For marquee selection, we'll have to make this more precise and do text measurement.
nsAutoString text; text.AssignWithConversion("text");
*aChildElt = nsXPIDLString::Copy(text.GetUnicode());
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBodyFrame::RowCountChanged(PRInt32 aIndex, PRInt32 aCount)
{
if (aCount == 0)
@ -854,7 +1002,7 @@ PRInt32 nsOutlinerBodyFrame::GetRowHeight()
// + the specified margins.
nsCOMPtr<nsIStyleContext> rowContext;
mScratchArray->Clear();
GetPseudoStyleContext(mPresContext, nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
if (rowContext) {
const nsStylePosition* myPosition = (const nsStylePosition*)
rowContext->GetStyleData(eStyleStruct_Position);
@ -881,7 +1029,7 @@ PRInt32 nsOutlinerBodyFrame::GetIndentation()
// Look up the correct indentation. It is equal to the specified indentation width.
nsCOMPtr<nsIStyleContext> indentContext;
mScratchArray->Clear();
GetPseudoStyleContext(mPresContext, nsXULAtoms::mozoutlinerindentation, getter_AddRefs(indentContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinerindentation, getter_AddRefs(indentContext));
if (indentContext) {
const nsStylePosition* myPosition = (const nsStylePosition*)
indentContext->GetStyleData(eStyleStruct_Position);
@ -904,16 +1052,6 @@ nsRect nsOutlinerBodyFrame::GetInnerBox()
return r;
}
static void
AdjustForBorderPadding(nsIStyleContext* aContext, nsRect& aRect)
{
nsMargin m(0,0,0,0);
nsStyleBorderPadding bPad;
aContext->GetStyle(eStyleStruct_BorderPaddingShortcut, (nsStyleStruct&)bPad);
bPad.GetBorderPadding(m);
aRect.Deflate(m);
}
// Painting routines
NS_IMETHODIMP nsOutlinerBodyFrame::Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -1019,7 +1157,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintColumn(nsOutlinerColumn* aColumn,
// Resolve style for the column. It contains all the info we need to lay ourselves
// out and to paint.
nsCOMPtr<nsIStyleContext> colContext;
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinercolumn, getter_AddRefs(colContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinercolumn, getter_AddRefs(colContext));
// Obtain the margins for the cell and then deflate our rect by that
// amount. The cell is assumed to be contained within the deflated rect.
@ -1055,7 +1193,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintRow(int aRowIndex, const nsRect& aRowRec
// Resolve style for the row. It contains all the info we need to lay ourselves
// out and to paint.
nsCOMPtr<nsIStyleContext> rowContext;
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinerrow, getter_AddRefs(rowContext));
// Obtain the margins for the row and then deflate our rect by that
// amount. The row is assumed to be contained within the deflated rect.
@ -1110,7 +1248,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintCell(int aRowIndex,
// Resolve style for the cell. It contains all the info we need to lay ourselves
// out and to paint.
nsCOMPtr<nsIStyleContext> cellContext;
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinercell, getter_AddRefs(cellContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinercell, getter_AddRefs(cellContext));
// Obtain the margins for the cell and then deflate our rect by that
// amount. The cell is assumed to be contained within the deflated rect.
@ -1148,7 +1286,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintCell(int aRowIndex,
// Resolve the style to use for the connecting lines.
nsCOMPtr<nsIStyleContext> lineContext;
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinerline, getter_AddRefs(lineContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinerline, getter_AddRefs(lineContext));
const nsStyleDisplay* displayStyle = (const nsStyleDisplay*)lineContext->GetStyleData(eStyleStruct_Display);
if (displayStyle->IsVisibleOrCollapsed() && level && NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
@ -1244,7 +1382,7 @@ nsOutlinerBodyFrame::PaintTwisty(int aRowIndex,
// Resolve style for the twisty.
nsCOMPtr<nsIStyleContext> twistyContext;
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinertwisty, getter_AddRefs(twistyContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinertwisty, getter_AddRefs(twistyContext));
// Obtain the margins for the twisty and then deflate our rect by that
// amount. The twisty is assumed to be contained within the deflated rect.
@ -1316,7 +1454,7 @@ nsOutlinerBodyFrame::PaintImage(int aRowIndex,
{
// Resolve style for the image.
nsCOMPtr<nsIStyleContext> imageContext;
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinerimage, getter_AddRefs(imageContext));
// Obtain the margins for the twisty and then deflate our rect by that
// amount. The twisty is assumed to be contained within the deflated rect.
@ -1401,7 +1539,7 @@ NS_IMETHODIMP nsOutlinerBodyFrame::PaintText(int aRowIndex,
// Resolve style for the text. It contains all the info we need to lay ourselves
// out and to paint.
nsCOMPtr<nsIStyleContext> textContext;
GetPseudoStyleContext(aPresContext, nsXULAtoms::mozoutlinercelltext, getter_AddRefs(textContext));
GetPseudoStyleContext(nsXULAtoms::mozoutlinercelltext, getter_AddRefs(textContext));
// Obtain the margins for the text and then deflate our rect by that
// amount. The text is assumed to be contained within the deflated rect.
@ -1697,10 +1835,10 @@ nsOutlinerBodyFrame::PositionChanged(PRInt32 aOldIndex, PRInt32& aNewIndex)
// The style cache.
nsresult
nsOutlinerBodyFrame::GetPseudoStyleContext(nsIPresContext* aPresContext, nsIAtom* aPseudoElement,
nsOutlinerBodyFrame::GetPseudoStyleContext(nsIAtom* aPseudoElement,
nsIStyleContext** aResult)
{
return mStyleCache.GetStyleContext(this, aPresContext, mContent, mStyleContext, aPseudoElement,
return mStyleCache.GetStyleContext(this, mPresContext, mContent, mStyleContext, aPseudoElement,
mScratchArray, aResult);
}

Просмотреть файл

@ -303,6 +303,10 @@ protected:
// Caches our box object.
void SetBoxObject(nsIOutlinerBoxObject* aBoxObject) { mOutlinerBoxObject = aBoxObject; };
// A helper used when hit testing.
nsresult GetItemWithinCellAt(PRInt32 aX, const nsRect& aCellRect, PRInt32 aRowIndex,
nsOutlinerColumn* aColumn, PRUnichar** aChildElt);
#ifdef USE_IMG2
// Fetch an image from the image cache.
nsresult GetImage(PRInt32 aRowIndex, const PRUnichar* aColID,
@ -324,7 +328,7 @@ protected:
// Looks up a style context in the style cache. On a cache miss we resolve
// the pseudo-styles passed in and place them into the cache.
nsresult GetPseudoStyleContext(nsIPresContext* aPresContext, nsIAtom* aPseudoElement, nsIStyleContext** aResult);
nsresult GetPseudoStyleContext(nsIAtom* aPseudoElement, nsIStyleContext** aResult);
// Builds our cache of column info.
void EnsureColumns();

Просмотреть файл

@ -280,11 +280,12 @@ NS_IMETHODIMP nsOutlinerBoxObject::InvalidateScrollbar()
return NS_OK;
}
NS_IMETHODIMP nsOutlinerBoxObject::GetCellAt(PRInt32 x, PRInt32 y, PRInt32 *row, PRUnichar **colID)
NS_IMETHODIMP nsOutlinerBoxObject::GetCellAt(PRInt32 x, PRInt32 y, PRInt32 *row, PRUnichar **colID,
PRUnichar** childElt)
{
nsIOutlinerBoxObject* body = GetOutlinerBody();
if (body)
return body->GetCellAt(x, y, row, colID);
return body->GetCellAt(x, y, row, colID, childElt);
return NS_OK;
}

Просмотреть файл

@ -409,17 +409,20 @@
if (!event.ctrlKey && !event.shiftKey && !event.metaKey) {
var row = {};
var col = {};
var obj = {};
var b = this.parentNode.outlinerBoxObject;
b.getCellAt(event.clientX, event.clientY, row, col);
b.getCellAt(event.clientX, event.clientY, row, col, obj);
var column = document.getElementById(col.value);
var cycler = column.getAttribute('cycler') == 'true';
if (obj.value != "twisty") {
var column = document.getElementById(col.value);
var cycler = column.getAttribute('cycler') == 'true';
if (cycler)
b.view.cycleCell(row.value, col.value);
else
if (!b.selection.isSelected(row.value))
b.selection.select(row.value);
if (cycler)
b.view.cycleCell(row.value, col.value);
else
if (!b.selection.isSelected(row.value))
b.selection.select(row.value);
}
}
]]>
</handler>
@ -431,8 +434,13 @@
if (event.button != 0) return;
var row = {};
var col = {};
var obj = {};
var b = this.parentNode.outlinerBoxObject;
b.getCellAt(event.clientX, event.clientY, row, col);
b.getCellAt(event.clientX, event.clientY, row, col, obj);
if (obj.value == "twisty") {
b.view.toggleOpenState(row.value);
return;
}
var augment = event.ctrlKey || event.metaKey;
if (event.shiftKey) {
b.selection.rangedSelect(-1, row.value, augment);
@ -462,10 +470,13 @@
<![CDATA[
var row = {};
var col = {};
// XXX Again, we need to check the cycler.
var obj = {};
var b = this.parentNode.outlinerBoxObject;
b.getCellAt(event.clientX, event.clientY, row, col);
if (b.view.isContainer(row.value))
b.getCellAt(event.clientX, event.clientY, row, col, obj);
var column = document.getElementById(col.value);
var cycler = column.getAttribute('cycler') == 'true';
if (!cycler && obj.value != "twisty" && b.view.isContainer(row.value))
b.view.toggleOpenState(row.value);
]]>
</handler>