зеркало из https://github.com/mozilla/pjs.git
Keyboard navigation and ensurevisible support for new tree widget. Bug#30511, r=pav
This commit is contained in:
Родитель
07f7e211e8
Коммит
de97a71ea3
|
@ -33,6 +33,8 @@
|
|||
#include "nsIPresContext.h"
|
||||
#include "nsIFrame.h"
|
||||
|
||||
//#define XULTREE
|
||||
|
||||
// XXX Hack
|
||||
#include "nsTreeOuterFrame.h"
|
||||
|
||||
|
@ -84,6 +86,9 @@ nsTreeBoxObject::~nsTreeBoxObject()
|
|||
nsIFrame*
|
||||
nsTreeBoxObject::GetFrame()
|
||||
{
|
||||
#ifdef XULTREE
|
||||
return nsBoxObject::GetFrame();
|
||||
#else
|
||||
nsIFrame* frame = nsBoxObject::GetFrame();
|
||||
if (!frame)
|
||||
return nsnull;
|
||||
|
@ -97,6 +102,7 @@ nsTreeBoxObject::GetFrame()
|
|||
return nsnull;
|
||||
|
||||
return (nsIFrame*)treeFrame;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* void ensureIndexIsVisible (in long rowIndex); */
|
||||
|
@ -106,7 +112,7 @@ NS_IMETHODIMP nsTreeBoxObject::EnsureIndexIsVisible(PRInt32 aRowIndex)
|
|||
if (!frame)
|
||||
return NS_OK;
|
||||
|
||||
nsITreeFrame* treeFrame = (nsITreeFrame*)frame;
|
||||
nsCOMPtr<nsITreeFrame> treeFrame(do_QueryInterface(frame));
|
||||
return treeFrame->EnsureRowIsVisible(aRowIndex);
|
||||
}
|
||||
|
||||
|
@ -123,7 +129,7 @@ NS_IMETHODIMP nsTreeBoxObject::GetNextItem(nsIDOMElement *aStartItem, PRInt32 aD
|
|||
if (!frame)
|
||||
return NS_OK;
|
||||
|
||||
nsITreeFrame* treeFrame = (nsITreeFrame*)frame;
|
||||
nsCOMPtr<nsITreeFrame> treeFrame(do_QueryInterface(frame));
|
||||
|
||||
return treeFrame->GetNextItem(aStartItem, aDelta, aResult);
|
||||
}
|
||||
|
@ -135,7 +141,7 @@ NS_IMETHODIMP nsTreeBoxObject::GetPreviousItem(nsIDOMElement *aStartItem, PRInt3
|
|||
if (!frame)
|
||||
return NS_OK;
|
||||
|
||||
nsITreeFrame* treeFrame = (nsITreeFrame*)frame;
|
||||
nsCOMPtr<nsITreeFrame> treeFrame(do_QueryInterface(frame));
|
||||
return treeFrame->GetPreviousItem(aStartItem, aDelta, aResult);
|
||||
}
|
||||
|
||||
|
@ -154,8 +160,7 @@ NS_IMETHODIMP nsTreeBoxObject::GetIndexOfItem(nsIDOMElement* aElement, PRInt32 *
|
|||
if (!frame)
|
||||
return NS_OK;
|
||||
|
||||
nsITreeFrame* treeFrame = (nsITreeFrame*)frame;
|
||||
|
||||
nsCOMPtr<nsITreeFrame> treeFrame(do_QueryInterface(frame));
|
||||
nsCOMPtr<nsIPresContext> presContext;
|
||||
mPresShell->GetPresContext(getter_AddRefs(presContext));
|
||||
return treeFrame->GetIndexOfItem(presContext, aElement, aResult);
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsXULTreeFrame.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsXULTreeOuterGroupFrame.h"
|
||||
#include "nsXULAtoms.h"
|
||||
|
||||
//
|
||||
// NS_NewXULTreeFrame
|
||||
|
@ -51,9 +55,219 @@ NS_NewXULTreeFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoo
|
|||
// Constructor
|
||||
nsXULTreeFrame::nsXULTreeFrame(nsIPresShell* aPresShell, PRBool aIsRoot, nsIBoxLayout* aLayoutManager, PRBool aIsHorizontal)
|
||||
:nsBoxFrame(aPresShell, aIsRoot, aLayoutManager, aIsHorizontal)
|
||||
{}
|
||||
{
|
||||
mPresShell = aPresShell;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
nsXULTreeFrame::~nsXULTreeFrame()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt)
|
||||
nsXULTreeFrame::AddRef(void)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt)
|
||||
nsXULTreeFrame::Release(void)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// QueryInterface
|
||||
//
|
||||
NS_INTERFACE_MAP_BEGIN(nsXULTreeFrame)
|
||||
NS_INTERFACE_MAP_ENTRY(nsITreeFrame)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame)
|
||||
|
||||
static void
|
||||
GetImmediateChild(nsIContent* aParent, nsIAtom* aTag, nsIContent** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
PRInt32 childCount;
|
||||
aParent->ChildCount(childCount);
|
||||
for (PRInt32 i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
aParent->ChildAt(i, *getter_AddRefs(child));
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
child->GetTag(*getter_AddRefs(tag));
|
||||
if (aTag == tag.get()) {
|
||||
*aResult = child;
|
||||
NS_ADDREF(*aResult);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeFrame::EnsureRowIsVisible(PRInt32 aRowIndex)
|
||||
{
|
||||
// Get our treechildren child frame.
|
||||
nsXULTreeOuterGroupFrame* XULTreeOuterGroup = nsnull;
|
||||
GetTreeBody(&XULTreeOuterGroup);
|
||||
|
||||
if (!XULTreeOuterGroup) return NS_OK;
|
||||
|
||||
XULTreeOuterGroup->EnsureRowIsVisible(aRowIndex);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void scrollToIndex (in long rowIndex); */
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeFrame::ScrollToIndex(PRInt32 rowIndex)
|
||||
{
|
||||
// Get our treechildren child frame.
|
||||
nsXULTreeOuterGroupFrame* treeOuterGroup = nsnull;
|
||||
GetTreeBody(&treeOuterGroup);
|
||||
|
||||
if (!treeOuterGroup)
|
||||
return NS_OK; // No tree body. Just bail.
|
||||
|
||||
// XXX IMPLEMENT!
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* nsIDOMElement getNextItem (in nsIDOMElement startItem, in long delta); */
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeFrame::GetNextItem(nsIDOMElement *aStartItem, PRInt32 aDelta, nsIDOMElement **aResult)
|
||||
{
|
||||
// Get our treechildren child frame.
|
||||
nsXULTreeOuterGroupFrame* treeOuterGroup = nsnull;
|
||||
GetTreeBody(&treeOuterGroup);
|
||||
|
||||
if (!treeOuterGroup)
|
||||
return NS_OK; // No tree body. Just bail.
|
||||
|
||||
nsCOMPtr<nsIContent> start(do_QueryInterface(aStartItem));
|
||||
nsCOMPtr<nsIContent> row;
|
||||
GetImmediateChild(start, nsXULAtoms::treerow, getter_AddRefs(row));
|
||||
|
||||
nsCOMPtr<nsIContent> result;
|
||||
treeOuterGroup->FindNextRowContent(aDelta, row, nsnull, getter_AddRefs(result));
|
||||
if (!result)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
result->GetParent(*getter_AddRefs(parent));
|
||||
if (!parent)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> item(do_QueryInterface(parent));
|
||||
*aResult = item;
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* nsIDOMElement getPreviousItem (in nsIDOMElement startItem, in long delta); */
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeFrame::GetPreviousItem(nsIDOMElement* aStartItem, PRInt32 aDelta, nsIDOMElement** aResult)
|
||||
{
|
||||
// Get our treechildren child frame.
|
||||
nsXULTreeOuterGroupFrame* treeOuterGroup = nsnull;
|
||||
GetTreeBody(&treeOuterGroup);
|
||||
|
||||
if (!treeOuterGroup)
|
||||
return NS_OK; // No tree body. Just bail.
|
||||
|
||||
nsCOMPtr<nsIContent> start(do_QueryInterface(aStartItem));
|
||||
nsCOMPtr<nsIContent> row;
|
||||
GetImmediateChild(start, nsXULAtoms::treerow, getter_AddRefs(row));
|
||||
|
||||
nsCOMPtr<nsIContent> result;
|
||||
treeOuterGroup->FindPreviousRowContent(aDelta, row, nsnull, getter_AddRefs(result));
|
||||
if (!result)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
result->GetParent(*getter_AddRefs(parent));
|
||||
if (!parent)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> item(do_QueryInterface(parent));
|
||||
*aResult = item;
|
||||
NS_IF_ADDREF(*aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* nsIDOMElement getItemAtIndex (in long index); */
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeFrame::GetItemAtIndex(PRInt32 aIndex, nsIDOMElement **aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
|
||||
// Get our treechildren child frame.
|
||||
nsXULTreeOuterGroupFrame* treeOuterGroup = nsnull;
|
||||
GetTreeBody(&treeOuterGroup);
|
||||
|
||||
if (!treeOuterGroup)
|
||||
return NS_OK; // No tree body. Just bail.
|
||||
|
||||
nsCOMPtr<nsIContent> result;
|
||||
treeOuterGroup->FindRowContentAtIndex(aIndex, nsnull, getter_AddRefs(result));
|
||||
if (!result)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
result->GetParent(*getter_AddRefs(parent));
|
||||
if (!parent)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> item(do_QueryInterface(parent));
|
||||
*aResult = item;
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* long getIndexOfItem (in nsIDOMElement item); */
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeFrame::GetIndexOfItem(nsIPresContext* aPresContext, nsIDOMElement* aElement, PRInt32* aResult)
|
||||
{
|
||||
// Get our treechildren child frame.
|
||||
nsXULTreeOuterGroupFrame* treeOuterGroup = nsnull;
|
||||
GetTreeBody(&treeOuterGroup);
|
||||
|
||||
if (!treeOuterGroup)
|
||||
return NS_OK; // No tree body. Just bail.
|
||||
|
||||
*aResult = 0;
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
|
||||
nsCOMPtr<nsIContent> root;
|
||||
treeOuterGroup->GetContent(getter_AddRefs(root));
|
||||
return treeOuterGroup->IndexOfItem(root, content, PR_TRUE, PR_TRUE, aResult);
|
||||
}
|
||||
|
||||
void
|
||||
nsXULTreeFrame::GetTreeBody(nsXULTreeOuterGroupFrame** aResult)
|
||||
{
|
||||
nsCOMPtr<nsIContent> child;
|
||||
PRInt32 count;
|
||||
mContent->ChildCount(count);
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
mContent->ChildAt(i, *getter_AddRefs(child));
|
||||
if (child) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
child->GetTag(*getter_AddRefs(tag));
|
||||
if (tag && tag.get() == nsXULAtoms::treechildren) {
|
||||
// This is our actual treechildren frame.
|
||||
nsIFrame* frame;
|
||||
mPresShell->GetPrimaryFrameFor(child, &frame);
|
||||
if (frame) {
|
||||
nsCOMPtr<nsIScrollableFrame> scroll(do_QueryInterface(frame));
|
||||
if (scroll) {
|
||||
scroll->GetScrolledFrame(nsnull, frame);
|
||||
}
|
||||
*aResult = (nsXULTreeOuterGroupFrame*)frame;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*aResult = nsnull;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,8 +23,12 @@
|
|||
*/
|
||||
|
||||
#include "nsBoxFrame.h"
|
||||
#include "nsITreeFrame.h"
|
||||
|
||||
class nsXULTreeFrame : public nsBoxFrame
|
||||
class nsXULTreeOuterGroupFrame;
|
||||
class nsIPresShell;
|
||||
|
||||
class nsXULTreeFrame : public nsBoxFrame, public nsITreeFrame
|
||||
{
|
||||
public:
|
||||
friend nsresult NS_NewXULTreeFrame(nsIPresShell* aPresShell,
|
||||
|
@ -33,10 +37,22 @@ public:
|
|||
nsIBoxLayout* aLayoutManager = nsnull,
|
||||
PRBool aDefaultHorizontal = PR_TRUE);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsITreeFrame
|
||||
NS_IMETHOD EnsureRowIsVisible(PRInt32 aRowIndex);
|
||||
NS_IMETHOD GetNextItem(nsIDOMElement* aStartItem, PRInt32 aDelta, nsIDOMElement** aResult);
|
||||
NS_IMETHOD GetPreviousItem(nsIDOMElement* aStartItem, PRInt32 aDelta, nsIDOMElement** aResult);
|
||||
NS_IMETHOD ScrollToIndex(PRInt32 aRowIndex);
|
||||
NS_IMETHOD GetItemAtIndex(PRInt32 aIndex, nsIDOMElement** aResult);
|
||||
NS_IMETHOD GetIndexOfItem(nsIPresContext* aPresContext, nsIDOMElement* aElement, PRInt32* aResult);
|
||||
|
||||
protected:
|
||||
nsXULTreeFrame(nsIPresShell* aPresShell, PRBool aIsRoot = nsnull, nsIBoxLayout* aLayoutManager = nsnull, PRBool aDefaultHorizontal = PR_TRUE);
|
||||
virtual ~nsXULTreeFrame();
|
||||
|
||||
void GetTreeBody(nsXULTreeOuterGroupFrame** aResult);
|
||||
|
||||
protected: // Data Members
|
||||
|
||||
nsIPresShell* mPresShell;
|
||||
}; // class nsXULTreeFrame
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "nsIScrollbarFrame.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsCSSFrameConstructor.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
#define TICK_FACTOR 50
|
||||
|
||||
|
@ -698,3 +699,93 @@ nsXULTreeOuterGroupFrame::FindNextRowContent(PRInt32& aDelta, nsIContent* aUpwar
|
|||
|
||||
// Bail. There's nothing else we can do.
|
||||
}
|
||||
|
||||
void
|
||||
nsXULTreeOuterGroupFrame::EnsureRowIsVisible(PRInt32 aRowIndex)
|
||||
{
|
||||
PRInt32 rows = GetAvailableHeight()/mRowHeight;
|
||||
PRInt32 bottomIndex = mCurrentIndex + rows - 1;
|
||||
|
||||
// if row is visible, ignore
|
||||
if (mCurrentIndex <= aRowIndex && aRowIndex <= bottomIndex)
|
||||
return;
|
||||
|
||||
// Try to center the new index.
|
||||
PRInt32 newIndex = aRowIndex - rows/2;
|
||||
if (newIndex < 0)
|
||||
newIndex = 0;
|
||||
|
||||
PRInt32 delta = mCurrentIndex > newIndex ? mCurrentIndex - newIndex : newIndex - mCurrentIndex;
|
||||
PRInt32 up = newIndex < mCurrentIndex;
|
||||
mCurrentIndex = newIndex;
|
||||
InternalPositionChanged(up, delta);
|
||||
|
||||
// This change has to happen immediately.
|
||||
// Flush any pending reflow commands.
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
mContent->GetDocument(*getter_AddRefs(doc));
|
||||
doc->FlushPendingNotifications();
|
||||
}
|
||||
|
||||
// walks the DOM to get the zero-based row index of the current content
|
||||
// note that aContent can be any element, this will get the index of the
|
||||
// element's parent
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeOuterGroupFrame::IndexOfItem(nsIContent* aRoot, nsIContent* aContent,
|
||||
PRBool aDescendIntoRows, // Invariant
|
||||
PRBool aParentIsOpen,
|
||||
PRInt32 *aResult)
|
||||
{
|
||||
PRInt32 childCount=0;
|
||||
aRoot->ChildCount(childCount);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 childIndex;
|
||||
for (childIndex=0; childIndex<childCount; childIndex++) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
aRoot->ChildAt(childIndex, *getter_AddRefs(child));
|
||||
|
||||
nsCOMPtr<nsIAtom> childTag;
|
||||
child->GetTag(*getter_AddRefs(childTag));
|
||||
|
||||
// is this it?
|
||||
if (child.get() == aContent)
|
||||
return NS_OK;
|
||||
|
||||
// we hit a treerow, count it
|
||||
if (childTag.get() == nsXULAtoms::treeitem)
|
||||
(*aResult)++;
|
||||
|
||||
PRBool descend = PR_TRUE;
|
||||
PRBool parentIsOpen = aParentIsOpen;
|
||||
|
||||
// don't descend into closed children
|
||||
if (childTag.get() == nsXULAtoms::treechildren && !parentIsOpen)
|
||||
descend = PR_FALSE;
|
||||
|
||||
// speed optimization - descend into rows only when told
|
||||
else if (childTag.get() == nsXULAtoms::treerow && !aDescendIntoRows)
|
||||
descend = PR_FALSE;
|
||||
|
||||
// descend as normally, but remember that the parent is closed!
|
||||
else if (childTag.get() == nsXULAtoms::treeitem) {
|
||||
nsAutoString isOpen;
|
||||
rv = child->GetAttribute(kNameSpaceID_None, nsXULAtoms::open, isOpen);
|
||||
|
||||
if (!isOpen.EqualsWithConversion("true"))
|
||||
parentIsOpen=PR_FALSE;
|
||||
}
|
||||
|
||||
// now that we've analyzed the tags, recurse
|
||||
if (descend) {
|
||||
rv = IndexOfItem(child, aContent,
|
||||
aDescendIntoRows, parentIsOpen, aResult);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// not found
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
|
@ -127,6 +127,15 @@ public:
|
|||
void FindRowContentAtIndex(PRInt32& aIndex, nsIContent* aParent,
|
||||
nsIContent** aResult);
|
||||
|
||||
// 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);
|
||||
|
||||
NS_IMETHOD IndexOfItem(nsIContent* aRoot, nsIContent* aContent,
|
||||
PRBool aDescendIntoRows, // Invariant
|
||||
PRBool aParentIsOpen,
|
||||
PRInt32 *aResult);
|
||||
|
||||
NS_IMETHOD InternalPositionChanged(PRBool aUp, PRInt32 aDelta);
|
||||
|
||||
protected: // Data Members
|
||||
|
|
Загрузка…
Ссылка в новой задаче