зеркало из https://github.com/mozilla/gecko-dev.git
Beginnings of keyboard navigation in the tree widget. No, it doesn't work
yet.
This commit is contained in:
Родитель
b22a966f53
Коммит
87872fe749
|
@ -26,7 +26,10 @@
|
||||||
#include "nsCellMap.h"
|
#include "nsCellMap.h"
|
||||||
#include "nsIDOMXULTreeElement.h"
|
#include "nsIDOMXULTreeElement.h"
|
||||||
#include "nsINameSpaceManager.h"
|
#include "nsINameSpaceManager.h"
|
||||||
|
#include "nsTreeRowGroupFrame.h"
|
||||||
|
#include "nsXULAtoms.h"
|
||||||
|
#include "nsIDOMNodeList.h"
|
||||||
|
#include "nsIDOMXULTreeElement.h"
|
||||||
//
|
//
|
||||||
// NS_NewTreeFrame
|
// NS_NewTreeFrame
|
||||||
//
|
//
|
||||||
|
@ -107,6 +110,28 @@ void nsTreeFrame::RangedSelection(nsIPresContext& aPresContext, nsTreeCellFrame*
|
||||||
// XXX Re-implement!
|
// XXX Re-implement!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsTreeFrame::GetTreeBody(nsTreeRowGroupFrame** aResult)
|
||||||
|
{
|
||||||
|
nsIFrame* curr = mFrames.FirstChild();
|
||||||
|
while (curr) {
|
||||||
|
nsCOMPtr<nsIContent> content;
|
||||||
|
curr->GetContent(getter_AddRefs(content));
|
||||||
|
if (content) {
|
||||||
|
nsCOMPtr<nsIAtom> tag;
|
||||||
|
content->GetTag(*getter_AddRefs(tag));
|
||||||
|
if (tag && tag.get() == nsXULAtoms::treechildren) {
|
||||||
|
// This is our actual treechildren frame.
|
||||||
|
nsTreeRowGroupFrame* rowGroup = (nsTreeRowGroupFrame*)curr; // XXX I am evil.
|
||||||
|
*aResult = rowGroup;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curr->GetNextSibling(&curr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsTreeFrame::HandleEvent(nsIPresContext& aPresContext,
|
nsTreeFrame::HandleEvent(nsIPresContext& aPresContext,
|
||||||
nsGUIEvent* aEvent,
|
nsGUIEvent* aEvent,
|
||||||
|
@ -114,7 +139,74 @@ nsTreeFrame::HandleEvent(nsIPresContext& aPresContext,
|
||||||
{
|
{
|
||||||
aEventStatus = nsEventStatus_eConsumeDoDefault;
|
aEventStatus = nsEventStatus_eConsumeDoDefault;
|
||||||
if (aEvent->message == NS_KEY_DOWN) {
|
if (aEvent->message == NS_KEY_DOWN) {
|
||||||
printf("YES!\n");
|
nsKeyEvent* keyEvent = (nsKeyEvent*)aEvent;
|
||||||
|
PRUint32 keyCode = keyEvent->keyCode;
|
||||||
|
if (keyCode == NS_VK_UP ||
|
||||||
|
keyCode == NS_VK_DOWN) {
|
||||||
|
|
||||||
|
// Get our treechildren child frame.
|
||||||
|
nsTreeRowGroupFrame* treeRowGroup = nsnull;
|
||||||
|
GetTreeBody(&treeRowGroup);
|
||||||
|
|
||||||
|
if (!treeRowGroup)
|
||||||
|
return NS_OK; // No tree body. Just bail.
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMXULTreeElement> treeElement = do_QueryInterface(mContent);
|
||||||
|
nsCOMPtr<nsIDOMNodeList> itemNodeList;
|
||||||
|
nsCOMPtr<nsIDOMNodeList> cellNodeList;
|
||||||
|
treeElement->GetSelectedItems(getter_AddRefs(itemNodeList));
|
||||||
|
treeElement->GetSelectedCells(getter_AddRefs(cellNodeList));
|
||||||
|
PRUint32 itemLength;
|
||||||
|
PRUint32 cellLength;
|
||||||
|
itemNodeList->GetLength(&itemLength);
|
||||||
|
cellNodeList->GetLength(&cellLength);
|
||||||
|
|
||||||
|
PRInt32 rowIndex = -1;
|
||||||
|
PRInt32 cellIndex = 0;
|
||||||
|
|
||||||
|
if (cellLength != 0 && itemLength == 0) {
|
||||||
|
nsCOMPtr<nsIDOMNode> node;
|
||||||
|
cellNodeList->Item(0, getter_AddRefs(node));
|
||||||
|
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
|
||||||
|
treeRowGroup->IndexOfCell(content, rowIndex, cellIndex);
|
||||||
|
}
|
||||||
|
else if (cellLength == 0 && itemLength != 0) {
|
||||||
|
nsCOMPtr<nsIDOMNode> node;
|
||||||
|
itemNodeList->Item(0, getter_AddRefs(node));
|
||||||
|
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
|
||||||
|
treeRowGroup->IndexOfRow(content, rowIndex);
|
||||||
|
}
|
||||||
|
else if (cellLength != 0 && itemLength != 0) {
|
||||||
|
nsCOMPtr<nsIDOMNode> node;
|
||||||
|
cellNodeList->Item(0, getter_AddRefs(node));
|
||||||
|
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
|
||||||
|
treeRowGroup->IndexOfCell(content, rowIndex, cellIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We now have a valid row and cell index for the current selection. Based on the
|
||||||
|
// direction, let's adjust the row and column index.
|
||||||
|
if (rowIndex == -1)
|
||||||
|
rowIndex = 0;
|
||||||
|
else if (keyCode == NS_VK_DOWN)
|
||||||
|
rowIndex++;
|
||||||
|
else if (keyCode == NS_VK_UP)
|
||||||
|
rowIndex--;
|
||||||
|
|
||||||
|
if (!treeRowGroup->IsValidRow(rowIndex))
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
// Ensure that the required index is visible.
|
||||||
|
treeRowGroup->EnsureRowIsVisible(rowIndex);
|
||||||
|
|
||||||
|
// Now that the row is scrolled into view, we have a frame created. We can retrieve the cell.
|
||||||
|
nsTreeCellFrame* cellFrame;
|
||||||
|
treeRowGroup->GetCellFrameAtIndex(rowIndex, cellIndex, &cellFrame);
|
||||||
|
if (!cellFrame)
|
||||||
|
return NS_OK; // No cell. Whatever. Bail.
|
||||||
|
|
||||||
|
// We got it! Perform the selection.
|
||||||
|
SetSelection(aPresContext, cellFrame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +219,7 @@ void nsTreeFrame::MoveUp(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame)
|
||||||
pFrame->GetColIndex(colIndex);
|
pFrame->GetColIndex(colIndex);
|
||||||
if (rowIndex > 0)
|
if (rowIndex > 0)
|
||||||
{
|
{
|
||||||
MoveToRowCol(aPresContext, rowIndex-1, colIndex, pFrame);
|
MoveToRowCol(aPresContext, rowIndex-1, colIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +233,7 @@ void nsTreeFrame::MoveDown(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame
|
||||||
|
|
||||||
if (rowIndex < totalRows-1)
|
if (rowIndex < totalRows-1)
|
||||||
{
|
{
|
||||||
MoveToRowCol(aPresContext, rowIndex+1, colIndex, pFrame);
|
MoveToRowCol(aPresContext, rowIndex+1, colIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,31 +245,31 @@ void nsTreeFrame::MoveLeft(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame
|
||||||
pFrame->GetColIndex(colIndex);
|
pFrame->GetColIndex(colIndex);
|
||||||
if (colIndex > 0)
|
if (colIndex > 0)
|
||||||
{
|
{
|
||||||
MoveToRowCol(aPresContext, rowIndex, colIndex-1, pFrame);
|
MoveToRowCol(aPresContext, rowIndex, colIndex-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsTreeFrame::MoveRight(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame)
|
void nsTreeFrame::MoveRight(nsIPresContext& aPresContext, nsTreeCellFrame* aFrame)
|
||||||
{
|
{
|
||||||
PRInt32 rowIndex;
|
PRInt32 rowIndex;
|
||||||
pFrame->GetRowIndex(rowIndex);
|
aFrame->GetRowIndex(rowIndex);
|
||||||
PRInt32 colIndex;
|
PRInt32 colIndex;
|
||||||
pFrame->GetColIndex(colIndex);
|
aFrame->GetColIndex(colIndex);
|
||||||
PRInt32 totalCols = mCellMap->GetColCount();
|
PRInt32 totalCols = mCellMap->GetColCount();
|
||||||
|
|
||||||
if (colIndex < totalCols-1)
|
if (colIndex < totalCols-1)
|
||||||
{
|
{
|
||||||
MoveToRowCol(aPresContext, rowIndex, colIndex+1, pFrame);
|
MoveToRowCol(aPresContext, rowIndex, colIndex+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsTreeFrame::MoveToRowCol(nsIPresContext& aPresContext, PRInt32 row, PRInt32 col, nsTreeCellFrame* pFrame)
|
void nsTreeFrame::MoveToRowCol(nsIPresContext& aPresContext, PRInt32 aRow, PRInt32 aCol)
|
||||||
{
|
{
|
||||||
nsTableCellFrame *cellFrame = mCellMap->GetCellInfoAt(row, col);
|
nsTableCellFrame* cellFrame = mCellMap->GetCellInfoAt(aRow, aCol);
|
||||||
|
|
||||||
// We now have the cell that should be selected.
|
// We now have the cell that should be selected.
|
||||||
nsTreeCellFrame* pTreeCell = NS_STATIC_CAST(nsTreeCellFrame*, cellFrame);
|
nsTreeCellFrame* treeCell = NS_STATIC_CAST(nsTreeCellFrame*, cellFrame);
|
||||||
SetSelection(aPresContext, pTreeCell);
|
SetSelection(aPresContext, treeCell);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "nsVoidArray.h"
|
#include "nsVoidArray.h"
|
||||||
|
|
||||||
class nsTreeCellFrame;
|
class nsTreeCellFrame;
|
||||||
|
class nsTreeRowGroupFrame;
|
||||||
|
|
||||||
class nsTreeFrame : public nsTableFrame
|
class nsTreeFrame : public nsTableFrame
|
||||||
{
|
{
|
||||||
|
@ -35,11 +36,13 @@ public:
|
||||||
void MoveDown(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame);
|
void MoveDown(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame);
|
||||||
void MoveLeft(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame);
|
void MoveLeft(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame);
|
||||||
void MoveRight(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame);
|
void MoveRight(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame);
|
||||||
void MoveToRowCol(nsIPresContext& aPresContext, PRInt32 row, PRInt32 col, nsTreeCellFrame* pFrame);
|
void MoveToRowCol(nsIPresContext& aPresContext, PRInt32 row, PRInt32 col);
|
||||||
|
|
||||||
PRBool IsSlatedForReflow() { return mSlatedForReflow; };
|
PRBool IsSlatedForReflow() { return mSlatedForReflow; };
|
||||||
void SlateForReflow() { mSlatedForReflow = PR_TRUE; };
|
void SlateForReflow() { mSlatedForReflow = PR_TRUE; };
|
||||||
|
|
||||||
|
void GetTreeBody(nsTreeRowGroupFrame** aResult);
|
||||||
|
|
||||||
// Overridden methods
|
// Overridden methods
|
||||||
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
|
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
|
||||||
PRBool RowGroupsShouldBeConstrained() { return PR_TRUE; }
|
PRBool RowGroupsShouldBeConstrained() { return PR_TRUE; }
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "nsCellMap.h"
|
#include "nsCellMap.h"
|
||||||
#include "nsIDOMXULTreeElement.h"
|
#include "nsIDOMXULTreeElement.h"
|
||||||
#include "nsINameSpaceManager.h"
|
#include "nsINameSpaceManager.h"
|
||||||
|
#include "nsXULAtoms.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// NS_NewTreeOuterFrame
|
// NS_NewTreeOuterFrame
|
||||||
|
@ -65,7 +66,22 @@ nsTreeOuterFrame::HandleEvent(nsIPresContext& aPresContext,
|
||||||
{
|
{
|
||||||
aEventStatus = nsEventStatus_eConsumeDoDefault;
|
aEventStatus = nsEventStatus_eConsumeDoDefault;
|
||||||
if (aEvent->message == NS_KEY_DOWN) {
|
if (aEvent->message == NS_KEY_DOWN) {
|
||||||
printf("YES!\n");
|
// Retrieve the tree frame.
|
||||||
|
nsIFrame* curr = mFrames.FirstChild();
|
||||||
|
while (curr) {
|
||||||
|
nsCOMPtr<nsIContent> content;
|
||||||
|
curr->GetContent(getter_AddRefs(content));
|
||||||
|
if (content) {
|
||||||
|
nsCOMPtr<nsIAtom> tag;
|
||||||
|
content->GetTag(*getter_AddRefs(tag));
|
||||||
|
if (tag && tag.get() == nsXULAtoms::tree) {
|
||||||
|
// This is our actual tree frame.
|
||||||
|
return curr->HandleEvent(aPresContext, aEvent, aEventStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curr->GetNextSibling(&curr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -364,7 +364,7 @@ nsTreeRowGroupFrame::FindPreviousRowContent(PRInt32& aDelta, nsIContent* aUpward
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsTreeRowGroupFrame::GetVisibleRowCount(PRInt32& aCount, nsIContent* aParent)
|
nsTreeRowGroupFrame::ComputeVisibleRowCount(PRInt32& aCount, nsIContent* aParent)
|
||||||
{
|
{
|
||||||
PRInt32 childCount;
|
PRInt32 childCount;
|
||||||
aParent->ChildCount(childCount);
|
aParent->ChildCount(childCount);
|
||||||
|
@ -379,7 +379,7 @@ nsTreeRowGroupFrame::GetVisibleRowCount(PRInt32& aCount, nsIContent* aParent)
|
||||||
}
|
}
|
||||||
else if (tag.get() == nsXULAtoms::treeitem) {
|
else if (tag.get() == nsXULAtoms::treeitem) {
|
||||||
// Descend into this row group and try to find the next row.
|
// Descend into this row group and try to find the next row.
|
||||||
GetVisibleRowCount(aCount, childContent);
|
ComputeVisibleRowCount(aCount, childContent);
|
||||||
|
|
||||||
// If it's open, descend into its treechildren.
|
// If it's open, descend into its treechildren.
|
||||||
nsCOMPtr<nsIAtom> openAtom = dont_AddRef(NS_NewAtom("open"));
|
nsCOMPtr<nsIAtom> openAtom = dont_AddRef(NS_NewAtom("open"));
|
||||||
|
@ -401,7 +401,7 @@ nsTreeRowGroupFrame::GetVisibleRowCount(PRInt32& aCount, nsIContent* aParent)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (j >= 0 && grandChild)
|
if (j >= 0 && grandChild)
|
||||||
GetVisibleRowCount(aCount, grandChild);
|
ComputeVisibleRowCount(aCount, grandChild);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -656,7 +656,7 @@ nsTreeRowGroupFrame::ReflowAfterRowLayout(nsIPresContext& aPresContext,
|
||||||
CreateScrollbar(aPresContext);
|
CreateScrollbar(aPresContext);
|
||||||
|
|
||||||
PRInt32 rowCount = 0;
|
PRInt32 rowCount = 0;
|
||||||
GetVisibleRowCount(rowCount, mContent); // XXX This sucks! Needs to be cheap!
|
ComputeVisibleRowCount(rowCount, mContent); // XXX This sucks! Needs to be cheap!
|
||||||
|
|
||||||
// Set the maxpos of the scrollbar.
|
// Set the maxpos of the scrollbar.
|
||||||
nsCOMPtr<nsIContent> scrollbarContent;
|
nsCOMPtr<nsIContent> scrollbarContent;
|
||||||
|
@ -1091,3 +1091,34 @@ void nsTreeRowGroupFrame::CreateScrollbar(nsIPresContext& aPresContext)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsTreeRowGroupFrame::IndexOfCell(nsIContent* aCellContent, PRInt32& aRowIndex, PRInt32& aColIndex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsTreeRowGroupFrame::IndexOfRow(nsIContent* aRowContent, PRInt32& aRowIndex)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
nsTreeRowGroupFrame::IsValidRow(PRInt32 aRowIndex)
|
||||||
|
{
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsTreeRowGroupFrame::EnsureRowIsVisible(PRInt32 aRowIndex)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsTreeRowGroupFrame::GetCellFrameAtIndex(PRInt32 aRowIndex, PRInt32 aColIndex,
|
||||||
|
nsTreeCellFrame** aResult)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,8 @@ public:
|
||||||
const nsRect& aDirtyRect,
|
const nsRect& aDirtyRect,
|
||||||
nsFramePaintLayer aWhichLayer);
|
nsFramePaintLayer aWhichLayer);
|
||||||
|
|
||||||
|
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
|
||||||
|
|
||||||
PRBool ContinueReflow(nsIPresContext& aPresContext, nscoord y, nscoord height);
|
PRBool ContinueReflow(nsIPresContext& aPresContext, nscoord y, nscoord height);
|
||||||
|
|
||||||
PRBool IsFull() { return mIsFull; };
|
PRBool IsFull() { return mIsFull; };
|
||||||
|
@ -109,9 +111,32 @@ protected:
|
||||||
nsIContent** aResult);
|
nsIContent** aResult);
|
||||||
void GetFirstRowContent(nsIContent** aRowContent);
|
void GetFirstRowContent(nsIContent** aRowContent);
|
||||||
|
|
||||||
void GetVisibleRowCount(PRInt32& rowCount, nsIContent* aParent);
|
void ComputeVisibleRowCount(PRInt32& rowCount, nsIContent* aParent);
|
||||||
|
|
||||||
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
|
public:
|
||||||
|
// Helpers that allow access to info. The tree is the primary consumer of this
|
||||||
|
// info.
|
||||||
|
|
||||||
|
// Tells you the row and index of a cell (given only the content node).
|
||||||
|
// This method is expensive.
|
||||||
|
void IndexOfCell(nsIContent* aCellContent, PRInt32& aRowIndex, PRInt32& aColIndex);
|
||||||
|
|
||||||
|
// Tells you the row index of a row (given only the content node).
|
||||||
|
// This method is expensive.
|
||||||
|
void IndexOfRow(nsIContent* aRowContent, PRInt32& aRowIndex);
|
||||||
|
|
||||||
|
// Whether or not the row is valid. This is a cheap method, since the total row count
|
||||||
|
// is cached.
|
||||||
|
PRBool IsValidRow(PRInt32 aRowIndex);
|
||||||
|
|
||||||
|
// This method ensures that a row is onscreen. It will scroll the tree widget such
|
||||||
|
// that the row is at the top of the screen (if the row was offscreen to start with).
|
||||||
|
void EnsureRowIsVisible(PRInt32 aRowIndex);
|
||||||
|
|
||||||
|
// This method retrieves a cell at a given index. The intent of this method is that it be
|
||||||
|
// cheap. It should not cause frames to be built, so this should only be called when the
|
||||||
|
// cell is onscreen (use EnsureRowIsVisible to guarantee this).
|
||||||
|
void GetCellFrameAtIndex(PRInt32 aRowIndex, PRInt32 aColIndex, nsTreeCellFrame** aResult);
|
||||||
|
|
||||||
protected: // Data Members
|
protected: // Data Members
|
||||||
nsIFrame* mTopFrame; // The current topmost frame in the view.
|
nsIFrame* mTopFrame; // The current topmost frame in the view.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче