зеркало из https://github.com/mozilla/pjs.git
Tree/grid work. Bug#30511. r=danm
This commit is contained in:
Родитель
bf84b6aaa4
Коммит
330c612d46
|
@ -30,6 +30,10 @@ MODULE = layout
|
||||||
LIBRARY_NAME = raptorxulbase_s
|
LIBRARY_NAME = raptorxulbase_s
|
||||||
|
|
||||||
CPPSRCS = \
|
CPPSRCS = \
|
||||||
|
nsTreeLayout.cpp \
|
||||||
|
nsXULTreeSliceFrame.cpp \
|
||||||
|
nsXULTreeGroupFrame.cpp \
|
||||||
|
nsXULTreeOuterGroupFrame.cpp \
|
||||||
nsBrowserBoxObject.cpp \
|
nsBrowserBoxObject.cpp \
|
||||||
nsIFrameBoxObject.cpp \
|
nsIFrameBoxObject.cpp \
|
||||||
nsEditorBoxObject.cpp \
|
nsEditorBoxObject.cpp \
|
||||||
|
|
|
@ -78,8 +78,10 @@ CPPSRCS= \
|
||||||
nsTreeItemDragCapturer.cpp \
|
nsTreeItemDragCapturer.cpp \
|
||||||
nsXULTreeFrame.cpp \
|
nsXULTreeFrame.cpp \
|
||||||
nsXULTreeGroupFrame.cpp \
|
nsXULTreeGroupFrame.cpp \
|
||||||
|
nsXULTreeOuterGroupFrame.cpp \
|
||||||
nsXULTreeSliceFrame.cpp \
|
nsXULTreeSliceFrame.cpp \
|
||||||
nsXULTreeCellFrame.cpp \
|
nsXULTreeCellFrame.cpp \
|
||||||
|
nsTreeLayout.cpp \
|
||||||
nsSpinnerFrame.cpp \
|
nsSpinnerFrame.cpp \
|
||||||
nsScrollbarFrame.cpp \
|
nsScrollbarFrame.cpp \
|
||||||
nsScrollbarButtonFrame.cpp \
|
nsScrollbarButtonFrame.cpp \
|
||||||
|
@ -147,8 +149,10 @@ CPP_OBJS= \
|
||||||
.\$(OBJDIR)\nsTreeItemDragCapturer.obj \
|
.\$(OBJDIR)\nsTreeItemDragCapturer.obj \
|
||||||
.\$(OBJDIR)\nsXULTreeFrame.obj \
|
.\$(OBJDIR)\nsXULTreeFrame.obj \
|
||||||
.\$(OBJDIR)\nsXULTreeGroupFrame.obj \
|
.\$(OBJDIR)\nsXULTreeGroupFrame.obj \
|
||||||
|
.\$(OBJDIR)\nsXULTreeOuterGroupFrame.obj \
|
||||||
.\$(OBJDIR)\nsXULTreeSliceFrame.obj \
|
.\$(OBJDIR)\nsXULTreeSliceFrame.obj \
|
||||||
.\$(OBJDIR)\nsXULTreeCellFrame.obj \
|
.\$(OBJDIR)\nsXULTreeCellFrame.obj \
|
||||||
|
.\$(OBJDIR)\nsTreeLayout.obj \
|
||||||
.\$(OBJDIR)\nsSpinnerFrame.obj \
|
.\$(OBJDIR)\nsSpinnerFrame.obj \
|
||||||
.\$(OBJDIR)\nsScrollbarFrame.obj \
|
.\$(OBJDIR)\nsScrollbarFrame.obj \
|
||||||
.\$(OBJDIR)\nsScrollbarButtonFrame.obj \
|
.\$(OBJDIR)\nsScrollbarButtonFrame.obj \
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Netscape Communications
|
||||||
|
* Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Original Author: David W. Hyatt (hyatt@netscape.com)
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef nsIScrollbarFrame_h___
|
||||||
|
#define nsIScrollbarFrame_h___
|
||||||
|
|
||||||
|
// {9A6B0416-4A5D-4550-BEB5-C94D18A69A94}
|
||||||
|
#define NS_ISCROLLBARFRAME_IID \
|
||||||
|
{ 0x9a6b0416, 0x4a5d, 0x4550, { 0xbe, 0xb5, 0xc9, 0x4d, 0x18, 0xa6, 0x9a, 0x94 } }
|
||||||
|
|
||||||
|
static NS_DEFINE_IID(kIScrollbarFrameIID, NS_ISCROLLBARFRAME_IID);
|
||||||
|
|
||||||
|
class nsIScrollbarMediator;
|
||||||
|
|
||||||
|
class nsIScrollbarFrame : public nsISupports {
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const nsIID& GetIID() { static nsIID iid = NS_ISCROLLBARFRAME_IID; return iid; }
|
||||||
|
|
||||||
|
NS_IMETHOD GetScrollbarMediator(nsIScrollbarMediator** aResult) = 0;
|
||||||
|
NS_IMETHOD SetScrollbarMediator(nsIScrollbarMediator* aMediator) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Netscape Communications
|
||||||
|
* Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Original Author: David W. Hyatt (hyatt@netscape.com)
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef nsIScrollbarMediator_h___
|
||||||
|
#define nsIScrollbarMediator_h___
|
||||||
|
|
||||||
|
// {351C003A-E8F7-4d10-8BFA-635C9860D650}
|
||||||
|
#define NS_ISCROLLBARMEDIATOR_IID \
|
||||||
|
{ 0x351c003a, 0xe8f7, 0x4d10, { 0x8b, 0xfa, 0x63, 0x5c, 0x98, 0x60, 0xd6, 0x50 } }
|
||||||
|
|
||||||
|
static NS_DEFINE_IID(kIScrollbarMediatorIID, NS_ISCROLLBARMEDIATOR_IID);
|
||||||
|
|
||||||
|
class nsIScrollbarMediator : public nsISupports {
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const nsIID& GetIID() { static nsIID iid = NS_ISCROLLBARMEDIATOR_IID; return iid; }
|
||||||
|
|
||||||
|
NS_IMETHOD PositionChanged(PRInt32 aOldIndex, PRInt32 aNewIndex) = 0;
|
||||||
|
NS_IMETHOD ScrollbarButtonPressed(PRInt32 aOldIndex, PRInt32 aNewIndex) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Netscape Communications
|
||||||
|
* Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Original Author: David W. Hyatt (hyatt@netscape.com)
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef nsIXULTreeSlice_h___
|
||||||
|
#define nsIXULTreeSlice_h___
|
||||||
|
|
||||||
|
#include "nsISupports.h"
|
||||||
|
|
||||||
|
// {B74EA9FF-0B55-413f-8DBF-AA5FE431731F}
|
||||||
|
#define NS_ITREESLICE_IID { 0xb74ea9ff, 0xb55, 0x413f, { 0x8d, 0xbf, 0xaa, 0x5f, 0xe4, 0x31, 0x73, 0x1f } }
|
||||||
|
|
||||||
|
class nsIXULTreeSlice : public nsISupports
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const nsIID& GetIID() { static nsIID iid = NS_ITREESLICE_IID; return iid; }
|
||||||
|
|
||||||
|
NS_IMETHOD IsOutermostFrame(PRBool* aResult) = 0;
|
||||||
|
NS_IMETHOD IsGroupFrame(PRBool* aResult) = 0;
|
||||||
|
NS_IMETHOD IsRowFrame(PRBool* aResult) = 0;
|
||||||
|
|
||||||
|
}; // class nsIXULTreeSlice
|
||||||
|
|
||||||
|
#endif
|
|
@ -39,6 +39,8 @@
|
||||||
#include "nsXULAtoms.h"
|
#include "nsXULAtoms.h"
|
||||||
#include "nsIReflowCommand.h"
|
#include "nsIReflowCommand.h"
|
||||||
#include "nsSliderFrame.h"
|
#include "nsSliderFrame.h"
|
||||||
|
#include "nsIScrollbarFrame.h"
|
||||||
|
#include "nsIScrollbarMediator.h"
|
||||||
#include "nsRepeatService.h"
|
#include "nsRepeatService.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -145,6 +147,7 @@ nsScrollbarButtonFrame::MouseClicked()
|
||||||
|
|
||||||
// get the current pos
|
// get the current pos
|
||||||
PRInt32 curpos = nsSliderFrame::GetCurrentPosition(content);
|
PRInt32 curpos = nsSliderFrame::GetCurrentPosition(content);
|
||||||
|
PRInt32 oldpos = curpos;
|
||||||
|
|
||||||
// get the max pos
|
// get the max pos
|
||||||
PRInt32 maxpos = nsSliderFrame::GetMaxPosition(content);
|
PRInt32 maxpos = nsSliderFrame::GetMaxPosition(content);
|
||||||
|
@ -168,6 +171,16 @@ nsScrollbarButtonFrame::MouseClicked()
|
||||||
else if (curpos > maxpos)
|
else if (curpos > maxpos)
|
||||||
curpos = maxpos;
|
curpos = maxpos;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIScrollbarFrame> sb(do_QueryInterface(scrollbar));
|
||||||
|
if (sb) {
|
||||||
|
nsCOMPtr<nsIScrollbarMediator> m;
|
||||||
|
sb->GetScrollbarMediator(getter_AddRefs(m));
|
||||||
|
if (m) {
|
||||||
|
m->ScrollbarButtonPressed(oldpos, curpos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// set the current position of the slider.
|
// set the current position of the slider.
|
||||||
char v[100];
|
char v[100];
|
||||||
sprintf(v, "%d", curpos);
|
sprintf(v, "%d", curpos);
|
||||||
|
|
|
@ -266,6 +266,7 @@ NS_NewScrollbarFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame )
|
||||||
// QueryInterface
|
// QueryInterface
|
||||||
//
|
//
|
||||||
NS_INTERFACE_MAP_BEGIN(nsScrollbarFrame)
|
NS_INTERFACE_MAP_BEGIN(nsScrollbarFrame)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIScrollbarFrame)
|
||||||
NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame)
|
NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,15 +29,17 @@
|
||||||
|
|
||||||
|
|
||||||
#include "nsBoxFrame.h"
|
#include "nsBoxFrame.h"
|
||||||
|
#include "nsIScrollbarFrame.h"
|
||||||
|
|
||||||
class nsISupportsArray;
|
class nsISupportsArray;
|
||||||
|
class nsIScrollbarMediator;
|
||||||
|
|
||||||
nsresult NS_NewScrollbarFrame(nsIPresShell* aPresShell, nsIFrame** aResult) ;
|
nsresult NS_NewScrollbarFrame(nsIPresShell* aPresShell, nsIFrame** aResult) ;
|
||||||
|
|
||||||
class nsScrollbarFrame : public nsBoxFrame
|
class nsScrollbarFrame : public nsBoxFrame, public nsIScrollbarFrame
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
nsScrollbarFrame(nsIPresShell* aShell):nsBoxFrame(aShell) {}
|
nsScrollbarFrame(nsIPresShell* aShell):nsBoxFrame(aShell), mScrollbarMediator(nsnull) {}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
NS_IMETHOD GetFrameName(nsString& aResult) const {
|
NS_IMETHOD GetFrameName(nsString& aResult) const {
|
||||||
|
@ -79,6 +81,12 @@ public:
|
||||||
nsIFrame* aPrevInFlow);
|
nsIFrame* aPrevInFlow);
|
||||||
|
|
||||||
|
|
||||||
|
// nsIScrollbarFrame
|
||||||
|
NS_IMETHOD SetScrollbarMediator(nsIScrollbarMediator* aMediator) { mScrollbarMediator = aMediator; return NS_OK; };
|
||||||
|
NS_IMETHOD GetScrollbarMediator(nsIScrollbarMediator** aResult) { *aResult = mScrollbarMediator; return NS_OK; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsIScrollbarMediator* mScrollbarMediator;
|
||||||
}; // class nsScrollbarFrame
|
}; // class nsScrollbarFrame
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -54,6 +54,8 @@
|
||||||
#include "nsTitledButtonFrame.h"
|
#include "nsTitledButtonFrame.h"
|
||||||
#include "nsScrollbarButtonFrame.h"
|
#include "nsScrollbarButtonFrame.h"
|
||||||
#include "nsIScrollbarListener.h"
|
#include "nsIScrollbarListener.h"
|
||||||
|
#include "nsIScrollbarMediator.h"
|
||||||
|
#include "nsIScrollbarFrame.h"
|
||||||
#include "nsISupportsArray.h"
|
#include "nsISupportsArray.h"
|
||||||
#include "nsIXMLContent.h"
|
#include "nsIXMLContent.h"
|
||||||
#include "nsXULAtoms.h"
|
#include "nsXULAtoms.h"
|
||||||
|
@ -679,6 +681,18 @@ nsSliderFrame::SetCurrentPosition(nsIContent* scrollbar, nsIFrame* aThumbFrame,
|
||||||
else if (newpos < 0)
|
else if (newpos < 0)
|
||||||
newpos = 0;
|
newpos = 0;
|
||||||
|
|
||||||
|
nsIBox* scrollbarBox = GetScrollbar();
|
||||||
|
nsCOMPtr<nsIScrollbarFrame> scrollbarFrame(do_QueryInterface(scrollbarBox));
|
||||||
|
if (scrollbarFrame) {
|
||||||
|
// See if we have a mediator.
|
||||||
|
nsCOMPtr<nsIScrollbarMediator> mediator;
|
||||||
|
scrollbarFrame->GetScrollbarMediator(getter_AddRefs(mediator));
|
||||||
|
if (mediator) {
|
||||||
|
mediator->PositionChanged(GetCurrentPosition(scrollbar), newpos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char ch[100];
|
char ch[100];
|
||||||
sprintf(ch,"%d", newpos);
|
sprintf(ch,"%d", newpos);
|
||||||
|
|
||||||
|
|
|
@ -163,7 +163,7 @@ nsTempleLayout::BuildBoxSizeList(nsIBox* aBox, nsBoxLayoutState& aState, nsBoxSi
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
aFirst = first;
|
aFirst = first;
|
||||||
else
|
else if (aLast)
|
||||||
(aLast)->next = first;
|
(aLast)->next = first;
|
||||||
aLast = last;
|
aLast = last;
|
||||||
}
|
}
|
||||||
|
@ -192,8 +192,11 @@ nsTempleLayout::BuildBoxSizeList(nsIBox* aBox, nsBoxLayoutState& aState, nsBoxSi
|
||||||
PRBool isHorizontal = PR_FALSE;
|
PRBool isHorizontal = PR_FALSE;
|
||||||
aBox->GetOrientation(isHorizontal);
|
aBox->GetOrientation(isHorizontal);
|
||||||
|
|
||||||
aFirst->Add(leftMargin,isHorizontal);
|
if (aFirst)
|
||||||
aLast->Add(rightMargin,isHorizontal);
|
aFirst->Add(leftMargin,isHorizontal);
|
||||||
|
|
||||||
|
if (aLast)
|
||||||
|
aLast->Add(rightMargin,isHorizontal);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,6 +123,7 @@ PRBool nsTreeFrame::IsAutoLayout(const nsHTMLReflowState* aReflowState)
|
||||||
|
|
||||||
void nsTreeFrame::SetSelection(nsIPresContext* aPresContext, nsTreeCellFrame* aFrame)
|
void nsTreeFrame::SetSelection(nsIPresContext* aPresContext, nsTreeCellFrame* aFrame)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
nsCOMPtr<nsIContent> cellContent;
|
nsCOMPtr<nsIContent> cellContent;
|
||||||
aFrame->GetContent(getter_AddRefs(cellContent));
|
aFrame->GetContent(getter_AddRefs(cellContent));
|
||||||
|
|
||||||
|
@ -143,10 +144,12 @@ void nsTreeFrame::SetSelection(nsIPresContext* aPresContext, nsTreeCellFrame* aF
|
||||||
treeElement->SelectItem(itemElement);
|
treeElement->SelectItem(itemElement);
|
||||||
mContent->UnsetAttribute(kNameSpaceID_None, kSuppressSelectChange, PR_FALSE);
|
mContent->UnsetAttribute(kNameSpaceID_None, kSuppressSelectChange, PR_FALSE);
|
||||||
treeElement->SelectCell(cellElement);
|
treeElement->SelectCell(cellElement);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsTreeFrame::ToggleSelection(nsIPresContext* aPresContext, nsTreeCellFrame* aFrame)
|
void nsTreeFrame::ToggleSelection(nsIPresContext* aPresContext, nsTreeCellFrame* aFrame)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
nsCOMPtr<nsIContent> cellContent;
|
nsCOMPtr<nsIContent> cellContent;
|
||||||
aFrame->GetContent(getter_AddRefs(cellContent));
|
aFrame->GetContent(getter_AddRefs(cellContent));
|
||||||
|
|
||||||
|
@ -165,10 +168,12 @@ void nsTreeFrame::ToggleSelection(nsIPresContext* aPresContext, nsTreeCellFrame*
|
||||||
treeElement->ToggleItemSelection(itemElement);
|
treeElement->ToggleItemSelection(itemElement);
|
||||||
mContent->UnsetAttribute(kNameSpaceID_None, kSuppressSelectChange, PR_FALSE);
|
mContent->UnsetAttribute(kNameSpaceID_None, kSuppressSelectChange, PR_FALSE);
|
||||||
treeElement->ToggleCellSelection(cellElement);
|
treeElement->ToggleCellSelection(cellElement);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsTreeFrame::RangedSelection(nsIPresContext* aPresContext, nsTreeCellFrame* aEndFrame)
|
void nsTreeFrame::RangedSelection(nsIPresContext* aPresContext, nsTreeCellFrame* aEndFrame)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
nsCOMPtr<nsIContent> endCellContent;
|
nsCOMPtr<nsIContent> endCellContent;
|
||||||
aEndFrame->GetContent(getter_AddRefs(endCellContent));
|
aEndFrame->GetContent(getter_AddRefs(endCellContent));
|
||||||
if (!endCellContent)
|
if (!endCellContent)
|
||||||
|
@ -188,6 +193,7 @@ void nsTreeFrame::RangedSelection(nsIPresContext* aPresContext, nsTreeCellFrame*
|
||||||
nsCOMPtr<nsIDOMXULElement> endElement = do_QueryInterface(endItemContent);
|
nsCOMPtr<nsIDOMXULElement> endElement = do_QueryInterface(endItemContent);
|
||||||
|
|
||||||
treeElement->SelectItemRange(nsnull, endElement);
|
treeElement->SelectItemRange(nsnull, endElement);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -0,0 +1,208 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Netscape Communications
|
||||||
|
* Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Original Author:
|
||||||
|
// David W Hyatt (hyatt@netscape.com)
|
||||||
|
// Netscape Communications
|
||||||
|
//
|
||||||
|
// See documentation in associated header file
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "nsTreeLayout.h"
|
||||||
|
#include "nsBoxLayoutState.h"
|
||||||
|
#include "nsIBox.h"
|
||||||
|
#include "nsIScrollableFrame.h"
|
||||||
|
#include "nsBox.h"
|
||||||
|
|
||||||
|
// ------ nsTreeLayout ------
|
||||||
|
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
NS_NewTreeLayout( nsIPresShell* aPresShell, nsCOMPtr<nsIBoxLayout>& aNewLayout)
|
||||||
|
{
|
||||||
|
aNewLayout = new nsTreeLayout(aPresShell);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTreeLayout::nsTreeLayout(nsIPresShell* aPresShell):nsTempleLayout(aPresShell)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsXULTreeOuterGroupFrame* nsTreeLayout::GetOuterFrame(nsIBox* aBox)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIXULTreeSlice> slice(do_QueryInterface(aBox));
|
||||||
|
if (slice) {
|
||||||
|
PRBool outer;
|
||||||
|
slice->IsOutermostFrame(&outer);
|
||||||
|
if (outer)
|
||||||
|
return (nsXULTreeOuterGroupFrame*) aBox;
|
||||||
|
}
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsXULTreeGroupFrame* nsTreeLayout::GetGroupFrame(nsIBox* aBox)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIXULTreeSlice> slice(do_QueryInterface(aBox));
|
||||||
|
if (slice) {
|
||||||
|
PRBool group;
|
||||||
|
slice->IsGroupFrame(&group);
|
||||||
|
if (group)
|
||||||
|
return (nsXULTreeGroupFrame*) aBox;
|
||||||
|
}
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsXULTreeSliceFrame* nsTreeLayout::GetRowFrame(nsIBox* aBox)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIXULTreeSlice> slice(do_QueryInterface(aBox));
|
||||||
|
if (slice) {
|
||||||
|
PRBool row;
|
||||||
|
slice->IsRowFrame(&row);
|
||||||
|
if (row)
|
||||||
|
return (nsXULTreeSliceFrame*) aBox;
|
||||||
|
}
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsTreeLayout::GetPrefSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
|
||||||
|
{
|
||||||
|
nsresult rv = nsTempleLayout::GetPrefSize(aBox, aBoxLayoutState, aSize);
|
||||||
|
nsXULTreeOuterGroupFrame* frame = GetOuterFrame(aBox);
|
||||||
|
if (frame)
|
||||||
|
aSize.height = frame->GetRowCount() * frame->GetRowHeightTwips();
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsTreeLayout::GetMinSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
|
||||||
|
{
|
||||||
|
nsresult rv = nsTempleLayout::GetMinSize(aBox, aBoxLayoutState, aSize);
|
||||||
|
nsXULTreeOuterGroupFrame* frame = GetOuterFrame(aBox);
|
||||||
|
if (frame)
|
||||||
|
aSize.height = frame->GetRowCount() * frame->GetRowHeightTwips();
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsTreeLayout::GetMaxSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
|
||||||
|
{
|
||||||
|
nsresult rv = nsTempleLayout::GetMaxSize(aBox, aBoxLayoutState, aSize);
|
||||||
|
nsXULTreeOuterGroupFrame* frame = GetOuterFrame(aBox);
|
||||||
|
if (frame)
|
||||||
|
aSize.height = frame->GetRowCount() * frame->GetRowHeightTwips();
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsTreeLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
|
||||||
|
{
|
||||||
|
// Get the start y position.
|
||||||
|
nsXULTreeGroupFrame* frame = GetGroupFrame(aBox);
|
||||||
|
if (!frame) {
|
||||||
|
NS_ERROR("Frame encountered that isn't a tree row group!\n");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get our client rect.
|
||||||
|
nsRect clientRect;
|
||||||
|
aBox->GetClientRect(clientRect);
|
||||||
|
|
||||||
|
// Get the starting y position and the remaining available
|
||||||
|
// height.
|
||||||
|
nscoord availableHeight = frame->GetAvailableHeight();
|
||||||
|
nscoord yOffset = frame->GetYPosition();
|
||||||
|
nscoord currY = 0;
|
||||||
|
|
||||||
|
if (availableHeight <= 0)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
// Walk our frames, building them dynamically as needed.
|
||||||
|
nsIBox* box = frame->GetFirstTreeBox();
|
||||||
|
while (box) {
|
||||||
|
// If this box is dirty or if it has dirty children, we
|
||||||
|
// call layout on it.
|
||||||
|
PRBool dirty = PR_FALSE;
|
||||||
|
PRBool dirtyChildren = PR_FALSE;
|
||||||
|
box->IsDirty(dirty);
|
||||||
|
box->HasDirtyChildren(dirtyChildren);
|
||||||
|
|
||||||
|
PRBool sizeChanged = PR_FALSE;
|
||||||
|
nsRect childRect;
|
||||||
|
box->GetContentRect(childRect);
|
||||||
|
nsMargin margin(0,0,0,0);
|
||||||
|
box->GetMargin(margin);
|
||||||
|
childRect.Inflate(margin);
|
||||||
|
nsSize size;
|
||||||
|
box->NeedsRecalc();
|
||||||
|
box->GetPrefSize(aState, size);
|
||||||
|
if (clientRect.width != childRect.width || size.height != childRect.height)
|
||||||
|
sizeChanged = PR_TRUE;
|
||||||
|
|
||||||
|
if (sizeChanged || dirty || dirtyChildren || aState.GetLayoutReason() == nsBoxLayoutState::Initial) {
|
||||||
|
PRBool isRow = PR_TRUE;
|
||||||
|
nsXULTreeGroupFrame* childGroup = GetGroupFrame(box);
|
||||||
|
if (childGroup) {
|
||||||
|
// Set the available height.
|
||||||
|
childGroup->SetAvailableHeight(availableHeight);
|
||||||
|
isRow = PR_FALSE;
|
||||||
|
}
|
||||||
|
childRect.width = clientRect.width;
|
||||||
|
|
||||||
|
box->GetMargin(margin);
|
||||||
|
childRect.Deflate(margin);
|
||||||
|
box->SetBounds(aState, childRect);
|
||||||
|
box->Layout(aState);
|
||||||
|
// Get the prefsize.
|
||||||
|
nsSize size;
|
||||||
|
box->NeedsRecalc();
|
||||||
|
box->GetPrefSize(aState, size);
|
||||||
|
childRect.height = size.height;
|
||||||
|
box->SetBounds(aState, childRect);
|
||||||
|
if (isRow) {
|
||||||
|
frame->GetOuterFrame()->SetRowHeight(size.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Place the child by just grabbing its rect and adjusting the x,y.
|
||||||
|
box->GetContentRect(childRect);
|
||||||
|
childRect.x = 0;
|
||||||
|
childRect.y = currY + yOffset;
|
||||||
|
yOffset += childRect.height;
|
||||||
|
availableHeight -= childRect.height;
|
||||||
|
box->GetMargin(margin);
|
||||||
|
childRect.Deflate(margin);
|
||||||
|
childRect.width < 0 ? 0 : childRect.width;
|
||||||
|
childRect.height < 0 ? 0 : childRect.height;
|
||||||
|
|
||||||
|
box->SetBounds(aState, childRect);
|
||||||
|
|
||||||
|
if (!frame->ContinueReflow(availableHeight))
|
||||||
|
break;
|
||||||
|
|
||||||
|
box = frame->GetNextTreeBox(box);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Netscape Communications
|
||||||
|
* Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Original Author:
|
||||||
|
David W. Hyatt(hyatt@netscape.com)
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef nsTreeLayout_h___
|
||||||
|
#define nsTreeLayout_h___
|
||||||
|
|
||||||
|
#include "nsTempleLayout.h"
|
||||||
|
#include "nsXULTreeOuterGroupFrame.h"
|
||||||
|
#include "nsXULTreeSliceFrame.h"
|
||||||
|
|
||||||
|
class nsTreeLayout : public nsTempleLayout
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsTreeLayout(nsIPresShell* aShell);
|
||||||
|
|
||||||
|
NS_IMETHOD GetPrefSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
|
||||||
|
NS_IMETHOD GetMinSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
|
||||||
|
NS_IMETHOD GetMaxSize(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
|
||||||
|
|
||||||
|
NS_IMETHOD Layout(nsIBox* aBox, nsBoxLayoutState& aState);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
nsXULTreeOuterGroupFrame* GetOuterFrame(nsIBox* aBox);
|
||||||
|
nsXULTreeGroupFrame* GetGroupFrame(nsIBox* aBox);
|
||||||
|
nsXULTreeSliceFrame* GetRowFrame(nsIBox* aBox);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
|
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsXULTreeGroupFrame.h"
|
#include "nsXULTreeGroupFrame.h"
|
||||||
|
#include "nsCSSFrameConstructor.h"
|
||||||
|
#include "nsBoxLayoutState.h"
|
||||||
|
#include "nsISupportsArray.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// NS_NewXULTreeGroupFrame
|
// NS_NewXULTreeGroupFrame
|
||||||
|
@ -47,13 +50,477 @@ NS_NewXULTreeGroupFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool a
|
||||||
|
|
||||||
} // NS_NewXULTreeGroupFrame
|
} // NS_NewXULTreeGroupFrame
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(nsrefcnt)
|
||||||
|
nsXULTreeGroupFrame::AddRef(void)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(nsrefcnt)
|
||||||
|
nsXULTreeGroupFrame::Release(void)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// QueryInterface
|
||||||
|
//
|
||||||
|
NS_INTERFACE_MAP_BEGIN(nsXULTreeGroupFrame)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIXULTreeSlice)
|
||||||
|
NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame)
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
nsXULTreeGroupFrame::nsXULTreeGroupFrame(nsIPresShell* aPresShell, PRBool aIsRoot, nsIBoxLayout* aLayoutManager, PRBool aIsHorizontal)
|
nsXULTreeGroupFrame::nsXULTreeGroupFrame(nsIPresShell* aPresShell, PRBool aIsRoot, nsIBoxLayout* aLayoutManager, PRBool aIsHorizontal)
|
||||||
:nsBoxFrame(aPresShell, aIsRoot, aLayoutManager, aIsHorizontal)
|
:nsBoxFrame(aPresShell, aIsRoot, aLayoutManager, aIsHorizontal), mFrameConstructor(nsnull), mPresContext(nsnull),
|
||||||
|
mOuterFrame(nsnull), mAvailableHeight(10000), mTopFrame(nsnull), mBottomFrame(nsnull), mLinkupFrame(nsnull),
|
||||||
|
mContentChain(nsnull)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
nsXULTreeGroupFrame::~nsXULTreeGroupFrame()
|
nsXULTreeGroupFrame::~nsXULTreeGroupFrame()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nsXULTreeGroupFrame::LocateFrame(nsIFrame* aStartFrame, nsIFrame** aResult)
|
||||||
|
{
|
||||||
|
if (aStartFrame == nsnull)
|
||||||
|
*aResult = mFrames.FirstChild();
|
||||||
|
else aStartFrame->GetNextSibling(aResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIFrame*
|
||||||
|
nsXULTreeGroupFrame::GetFirstFrame()
|
||||||
|
{
|
||||||
|
LocateFrame(nsnull, &mTopFrame);
|
||||||
|
return mTopFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIFrame*
|
||||||
|
nsXULTreeGroupFrame::GetNextFrame(nsIFrame* aPrevFrame)
|
||||||
|
{
|
||||||
|
nsIFrame* result;
|
||||||
|
LocateFrame(aPrevFrame, &result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIFrame*
|
||||||
|
nsXULTreeGroupFrame::GetLastFrame()
|
||||||
|
{
|
||||||
|
return mFrames.LastChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIBox*
|
||||||
|
nsXULTreeGroupFrame::GetFirstTreeBox()
|
||||||
|
{
|
||||||
|
// Clear ourselves out.
|
||||||
|
mLinkupFrame = nsnull;
|
||||||
|
mBottomFrame = mTopFrame;
|
||||||
|
|
||||||
|
// If we have a frame and no content chain (e.g., unresolved/uncreated content)
|
||||||
|
if (mTopFrame && !mContentChain) {
|
||||||
|
nsCOMPtr<nsIBox> box(do_QueryInterface(mTopFrame));
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if we have any frame whatsoever.
|
||||||
|
LocateFrame(nsnull, &mTopFrame);
|
||||||
|
|
||||||
|
mBottomFrame = mTopFrame;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIContent> startContent;
|
||||||
|
|
||||||
|
if (mContentChain) {
|
||||||
|
nsCOMPtr<nsISupports> supports;
|
||||||
|
mContentChain->GetElementAt(0, getter_AddRefs(supports));
|
||||||
|
nsCOMPtr<nsIContent> chainContent = do_QueryInterface(supports);
|
||||||
|
startContent = chainContent;
|
||||||
|
|
||||||
|
if (mTopFrame) {
|
||||||
|
// We have a content chain. If the top frame is the same as our content
|
||||||
|
// chain, we can go ahead and destroy our content chain and return the
|
||||||
|
// top frame.
|
||||||
|
nsCOMPtr<nsIContent> topContent;
|
||||||
|
mTopFrame->GetContent(getter_AddRefs(topContent));
|
||||||
|
if (chainContent.get() == topContent.get()) {
|
||||||
|
// The two content nodes are the same. Our content chain has
|
||||||
|
// been synched up, and we can now remove our element and
|
||||||
|
// pass the content chain inwards.
|
||||||
|
InitSubContentChain((nsXULTreeGroupFrame*)mTopFrame);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIBox> box(do_QueryInterface(mTopFrame));
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
else mLinkupFrame = mTopFrame; // We have some frames that we'll eventually catch up with.
|
||||||
|
// Cache the pointer to the first of these frames, so
|
||||||
|
// we'll know it when we hit it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mTopFrame) {
|
||||||
|
nsCOMPtr<nsIBox> box(do_QueryInterface(mTopFrame));
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't have a top frame instantiated. Let's
|
||||||
|
// try to make one.
|
||||||
|
|
||||||
|
// If startContent is initialized, we have a content chain, and
|
||||||
|
// we're using that content node to make our frame.
|
||||||
|
// Otherwise we have nothing, and we should just try to grab the first child.
|
||||||
|
if (!startContent) {
|
||||||
|
PRInt32 childCount;
|
||||||
|
mContent->ChildCount(childCount);
|
||||||
|
nsCOMPtr<nsIContent> childContent;
|
||||||
|
if (childCount > 0) {
|
||||||
|
mContent->ChildAt(0, *getter_AddRefs(childContent));
|
||||||
|
startContent = childContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startContent) {
|
||||||
|
PRBool isAppend = (mLinkupFrame == nsnull);
|
||||||
|
|
||||||
|
mFrameConstructor->CreateTreeWidgetContent(mPresContext, this, nsnull, startContent,
|
||||||
|
&mTopFrame, isAppend, PR_FALSE,
|
||||||
|
nsnull);
|
||||||
|
|
||||||
|
mBottomFrame = mTopFrame;
|
||||||
|
nsCOMPtr<nsIXULTreeSlice> slice(do_QueryInterface(mTopFrame));
|
||||||
|
PRBool isGroup = PR_FALSE;
|
||||||
|
if (slice)
|
||||||
|
slice->IsGroupFrame(&isGroup);
|
||||||
|
|
||||||
|
if (isGroup && mContentChain) {
|
||||||
|
// We have just instantiated a row group, and we have a content chain. This
|
||||||
|
// means we need to potentially pass a sub-content chain to the instantiated
|
||||||
|
// frame, so that it can also sync up with its children.
|
||||||
|
InitSubContentChain((nsXULTreeGroupFrame*)mTopFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetContentChain(nsnull);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIBox> box(do_QueryInterface(mTopFrame));
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
return nsnull;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIBox*
|
||||||
|
nsXULTreeGroupFrame::GetNextTreeBox(nsIBox* aBox)
|
||||||
|
{
|
||||||
|
// We're ultra-cool. We build our frames on the fly.
|
||||||
|
nsIFrame* result;
|
||||||
|
nsIFrame* frame;
|
||||||
|
aBox->GetFrame(&frame);
|
||||||
|
LocateFrame(frame, &result);
|
||||||
|
if (result && (result == mLinkupFrame)) {
|
||||||
|
// We haven't really found a result. We've only found a result if
|
||||||
|
// the linkup frame is really the next frame following the
|
||||||
|
// previous frame.
|
||||||
|
nsCOMPtr<nsIContent> prevContent;
|
||||||
|
frame->GetContent(getter_AddRefs(prevContent));
|
||||||
|
nsCOMPtr<nsIContent> linkupContent;
|
||||||
|
mLinkupFrame->GetContent(getter_AddRefs(linkupContent));
|
||||||
|
PRInt32 i, j;
|
||||||
|
mContent->IndexOf(prevContent, i);
|
||||||
|
mContent->IndexOf(linkupContent, j);
|
||||||
|
if (i+1==j) {
|
||||||
|
// We have found a match and successfully linked back up with our
|
||||||
|
// old frame.
|
||||||
|
mBottomFrame = mLinkupFrame;
|
||||||
|
mLinkupFrame = nsnull;
|
||||||
|
nsCOMPtr<nsIBox> box(do_QueryInterface(result));
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
else result = nsnull; // No true linkup. We need to make a frame.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
// No result found. See if there's a content node that wants a frame.
|
||||||
|
PRInt32 i, childCount;
|
||||||
|
nsCOMPtr<nsIContent> prevContent;
|
||||||
|
frame->GetContent(getter_AddRefs(prevContent));
|
||||||
|
nsCOMPtr<nsIContent> parentContent;
|
||||||
|
mContent->IndexOf(prevContent, i);
|
||||||
|
mContent->ChildCount(childCount);
|
||||||
|
if (i+1 < childCount) {
|
||||||
|
|
||||||
|
// There is a content node that wants a frame.
|
||||||
|
nsCOMPtr<nsIContent> nextContent;
|
||||||
|
mContent->ChildAt(i+1, *getter_AddRefs(nextContent));
|
||||||
|
nsIFrame* prevFrame = nsnull; // Default is to append
|
||||||
|
PRBool isAppend = PR_TRUE;
|
||||||
|
if (mLinkupFrame) {
|
||||||
|
// This will be an insertion, since we have frames on the end.
|
||||||
|
aBox->GetFrame(&prevFrame);
|
||||||
|
isAppend = PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mFrameConstructor->CreateTreeWidgetContent(mPresContext, this, prevFrame, nextContent,
|
||||||
|
&result, isAppend, PR_FALSE,
|
||||||
|
nsnull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mBottomFrame = result;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIBox> box(do_QueryInterface(result));
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXULTreeGroupFrame::TreeInsertFrames(nsIFrame* aPrevFrame, nsIFrame* aFrameList)
|
||||||
|
{
|
||||||
|
// insert the frames to our info list
|
||||||
|
nsBoxLayoutState state(mPresContext);
|
||||||
|
Insert(state, aPrevFrame, aFrameList);
|
||||||
|
|
||||||
|
mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXULTreeGroupFrame::TreeAppendFrames(nsIFrame* aFrameList)
|
||||||
|
{
|
||||||
|
// append them after
|
||||||
|
nsBoxLayoutState state(mPresContext);
|
||||||
|
Append(state,aFrameList);
|
||||||
|
|
||||||
|
mFrames.AppendFrames(nsnull, aFrameList);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXULTreeGroupFrame::OnContentInserted(nsIPresContext* aPresContext, nsIFrame* aNextSibling, PRInt32 aIndex)
|
||||||
|
{
|
||||||
|
nsIFrame* currFrame = aNextSibling;
|
||||||
|
|
||||||
|
// this will probably never happen -
|
||||||
|
// if we haven't created the topframe, it doesn't matter if
|
||||||
|
// content was inserted
|
||||||
|
if (mTopFrame == nsnull) return;
|
||||||
|
|
||||||
|
// if we're inserting content at the top of visible content,
|
||||||
|
// then ignore it because it would go off-screen
|
||||||
|
// except of course in the case of the first row, where we're
|
||||||
|
// actually adding visible content
|
||||||
|
if(aNextSibling == mTopFrame) {
|
||||||
|
if (aIndex == 0)
|
||||||
|
// it's the first row, blow away mTopFrame so it can be
|
||||||
|
// crecreated later
|
||||||
|
mTopFrame = nsnull;
|
||||||
|
else
|
||||||
|
// it's not visible, nothing to do
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (currFrame) {
|
||||||
|
nsIFrame* nextFrame;
|
||||||
|
currFrame->GetNextSibling(&nextFrame);
|
||||||
|
mFrameConstructor->RemoveMappingsForFrameSubtree(aPresContext, currFrame, nsnull);
|
||||||
|
|
||||||
|
nsBoxLayoutState state(aPresContext);
|
||||||
|
Remove(state, currFrame);
|
||||||
|
mFrames.DestroyFrame(aPresContext, currFrame);
|
||||||
|
currFrame = nextFrame;
|
||||||
|
}
|
||||||
|
nsBoxLayoutState state(aPresContext);
|
||||||
|
MarkDirtyChildren(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsXULTreeGroupFrame::OnContentRemoved(nsIPresContext* aPresContext,
|
||||||
|
nsIFrame* aChildFrame,
|
||||||
|
PRInt32 aIndex)
|
||||||
|
{
|
||||||
|
// if we're removing the top row, the new top row is the next row
|
||||||
|
if (mTopFrame && mTopFrame == aChildFrame)
|
||||||
|
mTopFrame->GetNextSibling(&mTopFrame);
|
||||||
|
|
||||||
|
// if we're removing the last frame in this rowgroup and if we have
|
||||||
|
// a scrollbar, we have to yank in some rows from above
|
||||||
|
/* if (!mTopFrame && mScrollbar && mCurrentIndex > 0) {
|
||||||
|
// sync up the scrollbar, now that we've scrolled one row
|
||||||
|
mCurrentIndex--;
|
||||||
|
nsAutoString indexStr;
|
||||||
|
PRInt32 pixelIndex = mCurrentIndex * SCROLL_FACTOR;
|
||||||
|
indexStr.AppendInt(pixelIndex);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIContent> scrollbarContent;
|
||||||
|
mScrollbar->GetContent(getter_AddRefs(scrollbarContent));
|
||||||
|
scrollbarContent->SetAttribute(kNameSpaceID_None, nsXULAtoms::curpos,
|
||||||
|
indexStr, PR_TRUE);
|
||||||
|
|
||||||
|
// Now force the reflow to happen immediately, because we need to
|
||||||
|
// deal with cleaning out the content chain.
|
||||||
|
nsCOMPtr<nsIPresShell> shell;
|
||||||
|
aPresContext->GetShell(getter_AddRefs(shell));
|
||||||
|
shell->FlushPendingNotifications();
|
||||||
|
|
||||||
|
return; // All frames got deleted anyway by the pos change.
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Go ahead and delete the frame.
|
||||||
|
nsBoxLayoutState state(aPresContext);
|
||||||
|
if (aChildFrame) {
|
||||||
|
Remove(state, aChildFrame);
|
||||||
|
mFrameConstructor->RemoveMappingsForFrameSubtree(aPresContext, aChildFrame, nsnull);
|
||||||
|
mFrames.DestroyFrame(aPresContext, aChildFrame);
|
||||||
|
|
||||||
|
}
|
||||||
|
MarkDirtyChildren(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool nsXULTreeGroupFrame::ContinueReflow(nscoord height)
|
||||||
|
{
|
||||||
|
if (height <= 0) {
|
||||||
|
nsIFrame* lastChild = GetLastFrame();
|
||||||
|
nsIFrame* startingPoint = mBottomFrame;
|
||||||
|
if (startingPoint == nsnull) {
|
||||||
|
// We just want to delete everything but the first item.
|
||||||
|
startingPoint = GetFirstFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastChild != startingPoint) {
|
||||||
|
// We have some hangers on (probably caused by shrinking the size of the window).
|
||||||
|
// Nuke them.
|
||||||
|
nsIFrame* currFrame;
|
||||||
|
startingPoint->GetNextSibling(&currFrame);
|
||||||
|
while (currFrame) {
|
||||||
|
nsIFrame* nextFrame;
|
||||||
|
currFrame->GetNextSibling(&nextFrame);
|
||||||
|
mFrameConstructor->RemoveMappingsForFrameSubtree(mPresContext, currFrame, nsnull);
|
||||||
|
|
||||||
|
nsBoxLayoutState state(mPresContext);
|
||||||
|
Remove(state, currFrame);
|
||||||
|
|
||||||
|
mFrames.DestroyFrame(mPresContext, currFrame);
|
||||||
|
|
||||||
|
currFrame = nextFrame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void nsXULTreeGroupFrame::DestroyRows(PRInt32& aRowsToLose)
|
||||||
|
{
|
||||||
|
// We need to destroy frames until our row count has been properly
|
||||||
|
// reduced. A reflow will then pick up and create the new frames.
|
||||||
|
nsIFrame* childFrame = GetFirstFrame();
|
||||||
|
while (childFrame && aRowsToLose > 0) {
|
||||||
|
nsCOMPtr<nsIXULTreeSlice> slice(do_QueryInterface(childFrame));
|
||||||
|
if (!slice) continue;
|
||||||
|
PRBool isRowGroup;
|
||||||
|
slice->IsGroupFrame(&isRowGroup);
|
||||||
|
if (isRowGroup)
|
||||||
|
{
|
||||||
|
nsXULTreeGroupFrame* childGroup = (nsXULTreeGroupFrame*)childFrame;
|
||||||
|
childGroup->DestroyRows(aRowsToLose);
|
||||||
|
if (aRowsToLose == 0) {
|
||||||
|
nsIBox* box = nsnull;
|
||||||
|
childGroup->GetChildBox(&box);
|
||||||
|
if (box) // Still have kids. Just return.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Lost a row.
|
||||||
|
aRowsToLose--;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIFrame* nextFrame = GetNextFrame(childFrame);
|
||||||
|
mFrameConstructor->RemoveMappingsForFrameSubtree(mPresContext, childFrame, nsnull);
|
||||||
|
nsBoxLayoutState state(mPresContext);
|
||||||
|
Remove(state, childFrame);
|
||||||
|
mFrames.DestroyFrame(mPresContext, childFrame);
|
||||||
|
mTopFrame = childFrame = nextFrame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsXULTreeGroupFrame::ReverseDestroyRows(PRInt32& aRowsToLose)
|
||||||
|
{
|
||||||
|
// We need to destroy frames until our row count has been properly
|
||||||
|
// reduced. A reflow will then pick up and create the new frames.
|
||||||
|
nsIFrame* childFrame = GetLastFrame();
|
||||||
|
while (childFrame && aRowsToLose > 0) {
|
||||||
|
nsCOMPtr<nsIXULTreeSlice> slice(do_QueryInterface(childFrame));
|
||||||
|
if (!slice) continue;
|
||||||
|
PRBool isRowGroup;
|
||||||
|
slice->IsGroupFrame(&isRowGroup);
|
||||||
|
if (isRowGroup)
|
||||||
|
{
|
||||||
|
nsXULTreeGroupFrame* childGroup = (nsXULTreeGroupFrame*)childFrame;
|
||||||
|
childGroup->ReverseDestroyRows(aRowsToLose);
|
||||||
|
if (aRowsToLose == 0) {
|
||||||
|
nsIBox* box = nsnull;
|
||||||
|
childGroup->GetChildBox(&box);
|
||||||
|
if (box) // Still have kids. Just return.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Lost a row.
|
||||||
|
aRowsToLose--;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIFrame* prevFrame;
|
||||||
|
prevFrame = mFrames.GetPrevSiblingFor(childFrame);
|
||||||
|
mFrameConstructor->RemoveMappingsForFrameSubtree(mPresContext, childFrame, nsnull);
|
||||||
|
nsBoxLayoutState state(mPresContext);
|
||||||
|
Remove(state, childFrame);
|
||||||
|
mFrames.DestroyFrame(mPresContext, childFrame);
|
||||||
|
mBottomFrame = childFrame = prevFrame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXULTreeGroupFrame::GetFirstRowContent(nsIContent** aResult)
|
||||||
|
{
|
||||||
|
*aResult = nsnull;
|
||||||
|
nsIFrame* kid = GetFirstFrame();
|
||||||
|
while (kid) {
|
||||||
|
nsCOMPtr<nsIXULTreeSlice> slice(do_QueryInterface(kid));
|
||||||
|
if (!slice)
|
||||||
|
continue;
|
||||||
|
PRBool isRowGroup;
|
||||||
|
slice->IsGroupFrame(&isRowGroup);
|
||||||
|
if (isRowGroup) {
|
||||||
|
((nsXULTreeGroupFrame*)kid)->GetFirstRowContent(aResult);
|
||||||
|
if (*aResult)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
kid->GetContent(aResult); // The ADDREF happens here.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
kid = GetNextFrame(kid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsXULTreeGroupFrame::SetContentChain(nsISupportsArray* aContentChain)
|
||||||
|
{
|
||||||
|
NS_IF_RELEASE(mContentChain);
|
||||||
|
mContentChain = aContentChain;
|
||||||
|
NS_IF_ADDREF(mContentChain);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsXULTreeGroupFrame::InitSubContentChain(nsXULTreeGroupFrame* aRowGroupFrame)
|
||||||
|
{
|
||||||
|
if (mContentChain) {
|
||||||
|
mContentChain->RemoveElementAt(0);
|
||||||
|
PRUint32 chainSize;
|
||||||
|
mContentChain->Count(&chainSize);
|
||||||
|
if (chainSize > 0 && aRowGroupFrame) {
|
||||||
|
aRowGroupFrame->SetContentChain(mContentChain);
|
||||||
|
}
|
||||||
|
// The chain is dead. Long live the chain.
|
||||||
|
SetContentChain(nsnull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -23,10 +23,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nsBoxFrame.h"
|
#include "nsBoxFrame.h"
|
||||||
|
#include "nsIXULTreeSlice.h"
|
||||||
|
|
||||||
class nsXULTreeGroupFrame : public nsBoxFrame
|
class nsCSSFrameConstructor;
|
||||||
|
class nsXULTreeOuterGroupFrame;
|
||||||
|
|
||||||
|
class nsXULTreeGroupFrame : public nsBoxFrame, public nsIXULTreeSlice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
friend nsresult NS_NewXULTreeGroupFrame(nsIPresShell* aPresShell,
|
friend nsresult NS_NewXULTreeGroupFrame(nsIPresShell* aPresShell,
|
||||||
nsIFrame** aNewFrame,
|
nsIFrame** aNewFrame,
|
||||||
PRBool aIsRoot = PR_FALSE,
|
PRBool aIsRoot = PR_FALSE,
|
||||||
|
@ -37,6 +43,60 @@ protected:
|
||||||
nsXULTreeGroupFrame(nsIPresShell* aPresShell, PRBool aIsRoot = nsnull, nsIBoxLayout* aLayoutManager = nsnull, PRBool aDefaultHorizontal = PR_TRUE);
|
nsXULTreeGroupFrame(nsIPresShell* aPresShell, PRBool aIsRoot = nsnull, nsIBoxLayout* aLayoutManager = nsnull, PRBool aDefaultHorizontal = PR_TRUE);
|
||||||
virtual ~nsXULTreeGroupFrame();
|
virtual ~nsXULTreeGroupFrame();
|
||||||
|
|
||||||
protected: // Data Members
|
void LocateFrame(nsIFrame* aStartFrame, nsIFrame** aResult);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void InitGroup(nsCSSFrameConstructor* aFC, nsIPresContext* aContext, nsXULTreeOuterGroupFrame* aOuterFrame)
|
||||||
|
{
|
||||||
|
mFrameConstructor = aFC;
|
||||||
|
mPresContext = aContext;
|
||||||
|
mOuterFrame = aOuterFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsXULTreeOuterGroupFrame* GetOuterFrame() { return mOuterFrame; };
|
||||||
|
nsIBox* GetFirstTreeBox();
|
||||||
|
nsIBox* GetNextTreeBox(nsIBox* aBox);
|
||||||
|
|
||||||
|
nsIFrame* GetFirstFrame();
|
||||||
|
nsIFrame* GetNextFrame(nsIFrame* aCurrFrame);
|
||||||
|
nsIFrame* GetLastFrame();
|
||||||
|
|
||||||
|
NS_IMETHOD IsDirty(PRBool& aDirtyFlag) { aDirtyFlag = PR_TRUE; return NS_OK; };
|
||||||
|
|
||||||
|
NS_IMETHOD TreeAppendFrames(nsIFrame* aFrameList);
|
||||||
|
|
||||||
|
NS_IMETHOD TreeInsertFrames(nsIFrame* aPrevFrame,
|
||||||
|
nsIFrame* aFrameList);
|
||||||
|
|
||||||
|
// Responses to changes
|
||||||
|
void OnContentInserted(nsIPresContext* aPresContext, nsIFrame* aNextSibling, PRInt32 aIndex);
|
||||||
|
void OnContentRemoved(nsIPresContext* aPresContext, nsIFrame* aChildFrame, PRInt32 aIndex);
|
||||||
|
|
||||||
|
// nsIXULTreeSlice
|
||||||
|
NS_IMETHOD IsOutermostFrame(PRBool* aResult) { *aResult = PR_FALSE; return NS_OK; };
|
||||||
|
NS_IMETHOD IsGroupFrame(PRBool* aResult) { *aResult = PR_TRUE; return NS_OK; };
|
||||||
|
NS_IMETHOD IsRowFrame(PRBool* aResult) { *aResult = PR_FALSE; return NS_OK; };
|
||||||
|
|
||||||
|
virtual nscoord GetAvailableHeight() { return mAvailableHeight; };
|
||||||
|
void SetAvailableHeight(nscoord aHeight) { mAvailableHeight = aHeight; };
|
||||||
|
|
||||||
|
virtual nscoord GetYPosition() { return 0; };
|
||||||
|
PRBool ContinueReflow(nscoord height);
|
||||||
|
|
||||||
|
void DestroyRows(PRInt32& aRowsToLose);
|
||||||
|
void ReverseDestroyRows(PRInt32& aRowsToLose);
|
||||||
|
void GetFirstRowContent(nsIContent** aResult);
|
||||||
|
|
||||||
|
void SetContentChain(nsISupportsArray* aContentChain);
|
||||||
|
void InitSubContentChain(nsXULTreeGroupFrame* aRowGroupFrame);
|
||||||
|
|
||||||
|
protected: // Data Members
|
||||||
|
nsCSSFrameConstructor* mFrameConstructor; // We don't own this. (No addref/release allowed, punk.)
|
||||||
|
nsIPresContext* mPresContext;
|
||||||
|
nsXULTreeOuterGroupFrame* mOuterFrame;
|
||||||
|
nscoord mAvailableHeight;
|
||||||
|
nsIFrame* mTopFrame;
|
||||||
|
nsIFrame* mBottomFrame;
|
||||||
|
nsIFrame* mLinkupFrame;
|
||||||
|
nsISupportsArray* mContentChain; // Our content chain
|
||||||
}; // class nsXULTreeGroupFrame
|
}; // class nsXULTreeGroupFrame
|
||||||
|
|
|
@ -0,0 +1,700 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Netscape Communications
|
||||||
|
* Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Original Author: David W. Hyatt (hyatt@netscape.com)
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsXULTreeOuterGroupFrame.h"
|
||||||
|
#include "nsXULAtoms.h"
|
||||||
|
#include "nsIContent.h"
|
||||||
|
#include "nsINameSpaceManager.h"
|
||||||
|
#include "nsIScrollableFrame.h"
|
||||||
|
#include "nsIScrollbarFrame.h"
|
||||||
|
#include "nsISupportsArray.h"
|
||||||
|
#include "nsCSSFrameConstructor.h"
|
||||||
|
|
||||||
|
#define TICK_FACTOR 50
|
||||||
|
|
||||||
|
//
|
||||||
|
// NS_NewXULTreeOuterGroupFrame
|
||||||
|
//
|
||||||
|
// Creates a new TreeOuterGroup frame
|
||||||
|
//
|
||||||
|
nsresult
|
||||||
|
NS_NewXULTreeOuterGroupFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoot,
|
||||||
|
nsIBoxLayout* aLayoutManager, PRBool aIsHorizontal)
|
||||||
|
{
|
||||||
|
NS_PRECONDITION(aNewFrame, "null OUT ptr");
|
||||||
|
if (nsnull == aNewFrame) {
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
nsXULTreeOuterGroupFrame* it = new (aPresShell) nsXULTreeOuterGroupFrame(aPresShell, aIsRoot, aLayoutManager, aIsHorizontal);
|
||||||
|
if (!it)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
*aNewFrame = it;
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
} // NS_NewXULTreeOuterGroupFrame
|
||||||
|
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
nsXULTreeOuterGroupFrame::nsXULTreeOuterGroupFrame(nsIPresShell* aPresShell, PRBool aIsRoot, nsIBoxLayout* aLayoutManager, PRBool aIsHorizontal)
|
||||||
|
:nsXULTreeGroupFrame(aPresShell, aIsRoot, aLayoutManager, aIsHorizontal),
|
||||||
|
mRowGroupInfo(nsnull), mRowHeight(TREE_LINE_HEIGHT), mCurrentIndex(0), mTwipIndex(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
nsXULTreeOuterGroupFrame::~nsXULTreeOuterGroupFrame()
|
||||||
|
{
|
||||||
|
delete mRowGroupInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(nsrefcnt)
|
||||||
|
nsXULTreeOuterGroupFrame::AddRef(void)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(nsrefcnt)
|
||||||
|
nsXULTreeOuterGroupFrame::Release(void)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// QueryInterface
|
||||||
|
//
|
||||||
|
NS_INTERFACE_MAP_BEGIN(nsXULTreeOuterGroupFrame)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIScrollbarMediator)
|
||||||
|
NS_INTERFACE_MAP_END_INHERITING(nsXULTreeGroupFrame)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXULTreeOuterGroupFrame::Init(nsIPresContext* aPresContext, nsIContent* aContent,
|
||||||
|
nsIFrame* aParent, nsIStyleContext* aContext, nsIFrame* aPrevInFlow)
|
||||||
|
{
|
||||||
|
nsresult rv = nsXULTreeGroupFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
|
||||||
|
|
||||||
|
float p2t;
|
||||||
|
aPresContext->GetScaledPixelsToTwips(&p2t);
|
||||||
|
mOnePixel = NSIntPixelsToTwips(1, p2t);
|
||||||
|
|
||||||
|
nsIFrame* box;
|
||||||
|
aParent->GetParent(&box);
|
||||||
|
if (!box)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIScrollableFrame> scrollFrame(do_QueryInterface(box));
|
||||||
|
if (!scrollFrame)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
nsIBox* verticalScrollbar;
|
||||||
|
scrollFrame->GetScrollbarBox(PR_TRUE, &verticalScrollbar);
|
||||||
|
if (!verticalScrollbar) {
|
||||||
|
NS_ERROR("Unable to install the scrollbar mediator on the tree widget. You must be using GFX scrollbars.");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIScrollbarFrame> scrollbarFrame(do_QueryInterface(verticalScrollbar));
|
||||||
|
scrollbarFrame->SetScrollbarMediator(this);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
} // Init
|
||||||
|
|
||||||
|
nscoord
|
||||||
|
nsXULTreeOuterGroupFrame::GetYPosition()
|
||||||
|
{
|
||||||
|
nsIBox* box;
|
||||||
|
GetParentBox(&box);
|
||||||
|
if (!box)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
box->GetParentBox(&box);
|
||||||
|
if (!box)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIScrollableFrame> scrollFrame(do_QueryInterface(box));
|
||||||
|
if (!scrollFrame)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nscoord x, y;
|
||||||
|
scrollFrame->GetScrollPosition(mPresContext, x, y);
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXULTreeOuterGroupFrame::VerticalScroll(PRInt32 aDelta)
|
||||||
|
{
|
||||||
|
nsIBox* box;
|
||||||
|
GetParentBox(&box);
|
||||||
|
if (!box)
|
||||||
|
return;
|
||||||
|
|
||||||
|
box->GetParentBox(&box);
|
||||||
|
if (!box)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIScrollableFrame> scrollFrame(do_QueryInterface(box));
|
||||||
|
if (!scrollFrame)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nscoord x, y;
|
||||||
|
scrollFrame->GetScrollPosition(mPresContext, x, y);
|
||||||
|
|
||||||
|
scrollFrame->ScrollTo(mPresContext, x, aDelta);
|
||||||
|
}
|
||||||
|
|
||||||
|
nscoord
|
||||||
|
nsXULTreeOuterGroupFrame::GetAvailableHeight()
|
||||||
|
{
|
||||||
|
nsIBox* box;
|
||||||
|
GetParentBox(&box);
|
||||||
|
if (!box)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
box->GetParentBox(&box);
|
||||||
|
if (!box)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIScrollableFrame> scrollFrame(do_QueryInterface(box));
|
||||||
|
if (!scrollFrame)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nscoord x, y;
|
||||||
|
scrollFrame->GetClipSize(mPresContext, &x, &y);
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXULTreeOuterGroupFrame::ComputeTotalRowCount(PRInt32& aCount, nsIContent* aParent)
|
||||||
|
{
|
||||||
|
if (!mRowGroupInfo) {
|
||||||
|
mRowGroupInfo = new nsXULTreeRowGroupInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
PRInt32 childCount;
|
||||||
|
aParent->ChildCount(childCount);
|
||||||
|
|
||||||
|
for (PRInt32 i = 0; i < childCount; i++) {
|
||||||
|
nsCOMPtr<nsIContent> childContent;
|
||||||
|
aParent->ChildAt(i, *getter_AddRefs(childContent));
|
||||||
|
nsCOMPtr<nsIAtom> tag;
|
||||||
|
childContent->GetTag(*getter_AddRefs(tag));
|
||||||
|
if (tag.get() == nsXULAtoms::treerow) {
|
||||||
|
if ((aCount%TICK_FACTOR) == 0)
|
||||||
|
mRowGroupInfo->Add(childContent);
|
||||||
|
|
||||||
|
mRowGroupInfo->mLastChild = childContent;
|
||||||
|
|
||||||
|
aCount++;
|
||||||
|
}
|
||||||
|
else if (tag.get() == nsXULAtoms::treeitem) {
|
||||||
|
// Descend into this row group and try to find the next row.
|
||||||
|
ComputeTotalRowCount(aCount, childContent);
|
||||||
|
}
|
||||||
|
else if (tag.get() == nsXULAtoms::treechildren) {
|
||||||
|
// If it's open, descend into its treechildren.
|
||||||
|
nsCOMPtr<nsIAtom> openAtom = dont_AddRef(NS_NewAtom("open"));
|
||||||
|
nsAutoString isOpen;
|
||||||
|
nsCOMPtr<nsIContent> parent;
|
||||||
|
childContent->GetParent(*getter_AddRefs(parent));
|
||||||
|
parent->GetAttribute(kNameSpaceID_None, openAtom, isOpen);
|
||||||
|
if (isOpen.EqualsWithConversion("true"))
|
||||||
|
ComputeTotalRowCount(aCount, childContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXULTreeOuterGroupFrame::ScrollbarButtonPressed(PRInt32 aOldIndex, PRInt32 aNewIndex)
|
||||||
|
{
|
||||||
|
if (aOldIndex == aNewIndex)
|
||||||
|
return NS_OK;
|
||||||
|
if (aNewIndex < aOldIndex)
|
||||||
|
mCurrentIndex--;
|
||||||
|
else mCurrentIndex++;
|
||||||
|
if (mCurrentIndex < 0) {
|
||||||
|
mCurrentIndex = 0;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
InternalPositionChanged(aNewIndex < aOldIndex, 1);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXULTreeOuterGroupFrame::PositionChanged(PRInt32 aOldIndex, PRInt32 aNewIndex)
|
||||||
|
{
|
||||||
|
if (aOldIndex == aNewIndex)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
printf("Old Index: %d, New Index: %d\n", aOldIndex, aNewIndex);
|
||||||
|
|
||||||
|
PRInt32 oldTwipIndex, newTwipIndex;
|
||||||
|
oldTwipIndex = (aOldIndex*mOnePixel);
|
||||||
|
newTwipIndex = (aNewIndex*mOnePixel);
|
||||||
|
|
||||||
|
PRInt32 twipDelta = newTwipIndex > oldTwipIndex ? newTwipIndex - oldTwipIndex : oldTwipIndex - newTwipIndex;
|
||||||
|
PRInt32 delta = twipDelta / mRowHeight;
|
||||||
|
PRInt32 remainder = twipDelta % mRowHeight;
|
||||||
|
if (remainder > (mRowHeight/2))
|
||||||
|
delta++;
|
||||||
|
|
||||||
|
if (delta == 0)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
mCurrentIndex = newTwipIndex > oldTwipIndex ? mCurrentIndex + delta : mCurrentIndex - delta;
|
||||||
|
|
||||||
|
if (mCurrentIndex < 0) {
|
||||||
|
mCurrentIndex = 0;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return InternalPositionChanged(newTwipIndex < oldTwipIndex, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXULTreeOuterGroupFrame::InternalPositionChanged(PRBool aUp, PRInt32 aDelta)
|
||||||
|
{
|
||||||
|
PRInt32 visibleRows = GetAvailableHeight()/mRowHeight;
|
||||||
|
|
||||||
|
// Get our presentation context.
|
||||||
|
if (aDelta < visibleRows) {
|
||||||
|
if (mContentChain) {
|
||||||
|
// XXX This could cause problems because of async reflow.
|
||||||
|
// Eventually we need to make the code smart enough to look at a content chain
|
||||||
|
// when building ANOTHER content chain.
|
||||||
|
|
||||||
|
// Ensure all reflows happen first.
|
||||||
|
nsCOMPtr<nsIPresShell> shell;
|
||||||
|
mPresContext->GetShell(getter_AddRefs(shell));
|
||||||
|
shell->FlushPendingNotifications();
|
||||||
|
}
|
||||||
|
|
||||||
|
PRInt32 loseRows = aDelta;
|
||||||
|
|
||||||
|
// scrolling down
|
||||||
|
if (!aUp) {
|
||||||
|
// Figure out how many rows we have to lose off the top.
|
||||||
|
DestroyRows(loseRows);
|
||||||
|
}
|
||||||
|
// scrolling up
|
||||||
|
else {
|
||||||
|
// Get our first row content.
|
||||||
|
nsCOMPtr<nsIContent> rowContent;
|
||||||
|
GetFirstRowContent(getter_AddRefs(rowContent));
|
||||||
|
|
||||||
|
// Figure out how many rows we have to lose off the bottom.
|
||||||
|
ReverseDestroyRows(loseRows);
|
||||||
|
|
||||||
|
// Now that we've lost some rows, we need to create a
|
||||||
|
// content chain that provides a hint for moving forward.
|
||||||
|
nsCOMPtr<nsIContent> topRowContent;
|
||||||
|
PRInt32 findContent = aDelta;
|
||||||
|
FindPreviousRowContent(findContent, rowContent, nsnull, getter_AddRefs(topRowContent));
|
||||||
|
ConstructContentChain(topRowContent);
|
||||||
|
//Now construct the chain for the old top row so its content chain gets
|
||||||
|
//set up correctly.
|
||||||
|
ConstructOldContentChain(rowContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Just blow away all our frames, but keep a content chain
|
||||||
|
// as a hint to figure out how to build the frames.
|
||||||
|
// Remove the scrollbar first.
|
||||||
|
// get the starting row index and row count
|
||||||
|
|
||||||
|
mFrameConstructor->RemoveMappingsForFrameSubtree(mPresContext, this, nsnull);
|
||||||
|
nsBoxLayoutState state(mPresContext);
|
||||||
|
mFirstChild = mLastChild = nsnull;
|
||||||
|
mFrames.DestroyFrames(mPresContext);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIContent> topRowContent;
|
||||||
|
FindRowContentAtIndex(mCurrentIndex, mContent, getter_AddRefs(topRowContent));
|
||||||
|
|
||||||
|
if (topRowContent)
|
||||||
|
ConstructContentChain(topRowContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
mTopFrame = mBottomFrame = nsnull; // Make sure everything is cleared out.
|
||||||
|
|
||||||
|
nsBoxLayoutState state(mPresContext);
|
||||||
|
MarkDirtyChildren(state);
|
||||||
|
|
||||||
|
VerticalScroll(mCurrentIndex*mRowHeight);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXULTreeOuterGroupFrame::ConstructContentChain(nsIContent* aRowContent)
|
||||||
|
{
|
||||||
|
// Create the content chain array.
|
||||||
|
NS_IF_RELEASE(mContentChain);
|
||||||
|
NS_NewISupportsArray(&mContentChain);
|
||||||
|
|
||||||
|
// Move up the chain until we hit our content node.
|
||||||
|
nsCOMPtr<nsIContent> currContent = dont_QueryInterface(aRowContent);
|
||||||
|
while (currContent && (currContent.get() != mContent)) {
|
||||||
|
mContentChain->InsertElementAt(currContent, 0);
|
||||||
|
nsCOMPtr<nsIContent> otherContent = currContent;
|
||||||
|
otherContent->GetParent(*getter_AddRefs(currContent));
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ASSERTION(currContent.get() == mContent, "Disaster! Content not contained in our tree!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXULTreeOuterGroupFrame::ConstructOldContentChain(nsIContent* aOldRowContent)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIContent> childOfCommonAncestor;
|
||||||
|
|
||||||
|
//Find the first child of the common ancestor between the new top row's content chain
|
||||||
|
//and the old top row. Everything between this child and the old top row potentially need
|
||||||
|
//to have their content chains reset.
|
||||||
|
FindChildOfCommonContentChainAncestor(aOldRowContent, getter_AddRefs(childOfCommonAncestor));
|
||||||
|
|
||||||
|
if (childOfCommonAncestor) {
|
||||||
|
//Set up the old top rows content chian.
|
||||||
|
CreateOldContentChain(aOldRowContent, childOfCommonAncestor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXULTreeOuterGroupFrame::FindChildOfCommonContentChainAncestor(nsIContent *startContent, nsIContent **child)
|
||||||
|
{
|
||||||
|
PRUint32 count;
|
||||||
|
if (mContentChain)
|
||||||
|
{
|
||||||
|
nsresult rv = mContentChain->Count(&count);
|
||||||
|
|
||||||
|
if (NS_SUCCEEDED(rv) && (count >0)) {
|
||||||
|
for (PRInt32 curItem = count - 1; curItem >= 0; curItem--) {
|
||||||
|
nsCOMPtr<nsISupports> supports;
|
||||||
|
mContentChain->GetElementAt(curItem, getter_AddRefs(supports));
|
||||||
|
nsCOMPtr<nsIContent> curContent = do_QueryInterface(supports);
|
||||||
|
|
||||||
|
//See if curContent is an ancestor of startContent.
|
||||||
|
if (IsAncestor(curContent, startContent, child))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//mContent isn't actually put in the content chain, so we need to
|
||||||
|
//check it separately.
|
||||||
|
if (IsAncestor(mContent, startContent, child))
|
||||||
|
return;
|
||||||
|
|
||||||
|
*child = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if oldRowContent is an ancestor of rowContent, return true,
|
||||||
|
// and return the previous ancestor if requested
|
||||||
|
PRBool
|
||||||
|
nsXULTreeOuterGroupFrame::IsAncestor(nsIContent *aRowContent, nsIContent *aOldRowContent, nsIContent** firstDescendant)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIContent> prevContent;
|
||||||
|
nsCOMPtr<nsIContent> currContent = dont_QueryInterface(aOldRowContent);
|
||||||
|
|
||||||
|
while (currContent) {
|
||||||
|
if (aRowContent == currContent.get()) {
|
||||||
|
if (firstDescendant) {
|
||||||
|
*firstDescendant = prevContent;
|
||||||
|
NS_IF_ADDREF(*firstDescendant);
|
||||||
|
}
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
prevContent = currContent;
|
||||||
|
prevContent->GetParent(*getter_AddRefs(currContent));
|
||||||
|
}
|
||||||
|
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXULTreeOuterGroupFrame::CreateOldContentChain(nsIContent* aOldRowContent, nsIContent* topOfChain)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIContent> currContent = dont_QueryInterface(aOldRowContent);
|
||||||
|
nsCOMPtr<nsIContent> prevContent;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPresShell> shell;
|
||||||
|
mPresContext->GetShell(getter_AddRefs(shell));
|
||||||
|
|
||||||
|
//For each item between the (oldtoprow) and
|
||||||
|
// (the new first child of common ancestry between new top row and old top row)
|
||||||
|
// we need to see if the content chain has to be reset.
|
||||||
|
while (currContent.get() != topOfChain) {
|
||||||
|
nsIFrame* primaryFrame = nsnull;
|
||||||
|
shell->GetPrimaryFrameFor(currContent, &primaryFrame);
|
||||||
|
|
||||||
|
if (primaryFrame) {
|
||||||
|
nsCOMPtr<nsIXULTreeSlice> slice(do_QueryInterface(primaryFrame));
|
||||||
|
PRBool isRowGroup = PR_FALSE;
|
||||||
|
if (slice)
|
||||||
|
slice->IsGroupFrame(&isRowGroup);
|
||||||
|
|
||||||
|
if (isRowGroup) {
|
||||||
|
//Get the current content's parent's first child
|
||||||
|
nsCOMPtr<nsIContent> parent;
|
||||||
|
currContent->GetParent(*getter_AddRefs(parent));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIContent> firstChild;
|
||||||
|
parent->ChildAt(0, *getter_AddRefs(firstChild));
|
||||||
|
|
||||||
|
nsIFrame* parentFrame;
|
||||||
|
primaryFrame->GetParent(&parentFrame);
|
||||||
|
PRBool isParentRowGroup = PR_FALSE;
|
||||||
|
nsCOMPtr<nsIXULTreeSlice> slice(do_QueryInterface(parentFrame));
|
||||||
|
if (slice)
|
||||||
|
slice->IsGroupFrame(&isParentRowGroup);
|
||||||
|
|
||||||
|
if (isParentRowGroup) {
|
||||||
|
//Get the current content's parent's first frame.
|
||||||
|
nsXULTreeGroupFrame *parentRowGroupFrame =
|
||||||
|
(nsXULTreeGroupFrame*)parentFrame;
|
||||||
|
nsIFrame *currentTopFrame = parentRowGroupFrame->GetFirstFrame();
|
||||||
|
|
||||||
|
nsCOMPtr<nsIContent> topContent;
|
||||||
|
currentTopFrame->GetContent(getter_AddRefs(topContent));
|
||||||
|
|
||||||
|
// If the current content's parent's first child is different
|
||||||
|
// than the current frame's parent's first child then we know
|
||||||
|
// they are out of synch and we need to set the content
|
||||||
|
// chain correctly.
|
||||||
|
if(topContent.get() != firstChild.get()) {
|
||||||
|
nsCOMPtr<nsISupportsArray> contentChain;
|
||||||
|
NS_NewISupportsArray(getter_AddRefs(contentChain));
|
||||||
|
contentChain->InsertElementAt(firstChild, 0);
|
||||||
|
parentRowGroupFrame->SetContentChain(contentChain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prevContent = currContent;
|
||||||
|
prevContent->GetParent(*getter_AddRefs(currContent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXULTreeOuterGroupFrame::FindRowContentAtIndex(PRInt32& aIndex,
|
||||||
|
nsIContent* aParent,
|
||||||
|
nsIContent** aResult)
|
||||||
|
{
|
||||||
|
// Init to nsnull.
|
||||||
|
*aResult = nsnull;
|
||||||
|
|
||||||
|
// Walk over the tick array.
|
||||||
|
if (mRowGroupInfo == nsnull)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PRUint32 index = 0;
|
||||||
|
PRUint32 arrayCount;
|
||||||
|
mRowGroupInfo->mTickArray->Count(&arrayCount);
|
||||||
|
nsCOMPtr<nsIContent> startContent;
|
||||||
|
PRUint32 location = aIndex/TICK_FACTOR + 1;
|
||||||
|
PRUint32 point = location*TICK_FACTOR;
|
||||||
|
if (location >= arrayCount) {
|
||||||
|
startContent = mRowGroupInfo->mLastChild;
|
||||||
|
point = mRowGroupInfo->mRowCount-1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nsCOMPtr<nsISupports> supp = getter_AddRefs(mRowGroupInfo->mTickArray->ElementAt(location));
|
||||||
|
startContent = do_QueryInterface(supp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!startContent) {
|
||||||
|
NS_ERROR("The tree's tick array is confused!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRInt32 delta = (PRInt32)(point-aIndex);
|
||||||
|
FindPreviousRowContent(delta, startContent, nsnull, aResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXULTreeOuterGroupFrame::FindPreviousRowContent(PRInt32& aDelta, nsIContent* aUpwardHint,
|
||||||
|
nsIContent* aDownwardHint,
|
||||||
|
nsIContent** aResult)
|
||||||
|
{
|
||||||
|
// Init to nsnull.
|
||||||
|
*aResult = nsnull;
|
||||||
|
|
||||||
|
// It disappoints me that this function is completely tied to the content nodes,
|
||||||
|
// but I can't see any other way to handle this. I don't have the frames, so I have nothing
|
||||||
|
// else to fall back on but the content nodes.
|
||||||
|
PRInt32 index = 0;
|
||||||
|
nsCOMPtr<nsIContent> parentContent;
|
||||||
|
if (aUpwardHint) {
|
||||||
|
aUpwardHint->GetParent(*getter_AddRefs(parentContent));
|
||||||
|
if (!parentContent) {
|
||||||
|
NS_ERROR("Parent content should not be NULL!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parentContent->IndexOf(aUpwardHint, index);
|
||||||
|
}
|
||||||
|
else if (aDownwardHint) {
|
||||||
|
parentContent = dont_QueryInterface(aDownwardHint);
|
||||||
|
parentContent->ChildCount(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let me see inside the damn nsCOMptrs
|
||||||
|
nsIAtom* aAtom;
|
||||||
|
parentContent->GetTag(aAtom);
|
||||||
|
nsAutoString result;
|
||||||
|
aAtom->ToString(result);
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (PRInt32 i = index-1; i >= 0; i--) {
|
||||||
|
nsCOMPtr<nsIContent> childContent;
|
||||||
|
parentContent->ChildAt(i, *getter_AddRefs(childContent));
|
||||||
|
nsCOMPtr<nsIAtom> tag;
|
||||||
|
childContent->GetTag(*getter_AddRefs(tag));
|
||||||
|
if (tag.get() == nsXULAtoms::treerow) {
|
||||||
|
aDelta--;
|
||||||
|
if (aDelta == 0) {
|
||||||
|
*aResult = childContent;
|
||||||
|
NS_IF_ADDREF(*aResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tag.get() == nsXULAtoms::treeitem) {
|
||||||
|
// If it's open, descend into its treechildren node first.
|
||||||
|
nsCOMPtr<nsIAtom> openAtom = dont_AddRef(NS_NewAtom("open"));
|
||||||
|
nsAutoString isOpen;
|
||||||
|
childContent->GetAttribute(kNameSpaceID_None, openAtom, isOpen);
|
||||||
|
if (isOpen.EqualsWithConversion("true")) {
|
||||||
|
// Find the <treechildren> node.
|
||||||
|
PRInt32 childContentCount;
|
||||||
|
nsCOMPtr<nsIContent> grandChild;
|
||||||
|
childContent->ChildCount(childContentCount);
|
||||||
|
|
||||||
|
PRInt32 j;
|
||||||
|
for (j = childContentCount-1; j >= 0; j--) {
|
||||||
|
|
||||||
|
childContent->ChildAt(j, *getter_AddRefs(grandChild));
|
||||||
|
nsCOMPtr<nsIAtom> grandChildTag;
|
||||||
|
grandChild->GetTag(*getter_AddRefs(grandChildTag));
|
||||||
|
if (grandChildTag.get() == nsXULAtoms::treechildren)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j >= 0 && grandChild)
|
||||||
|
FindPreviousRowContent(aDelta, nsnull, grandChild, aResult);
|
||||||
|
|
||||||
|
if (aDelta == 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Descend into this row group and try to find a previous row.
|
||||||
|
FindPreviousRowContent(aDelta, nsnull, childContent, aResult);
|
||||||
|
if (aDelta == 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAtom> tag;
|
||||||
|
parentContent->GetTag(*getter_AddRefs(tag));
|
||||||
|
if (tag && tag.get() == nsXULAtoms::tree) {
|
||||||
|
// Hopeless. It ain't in there.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!aDownwardHint) // We didn't find it here. We need to go up to our parent, using ourselves as a hint.
|
||||||
|
FindPreviousRowContent(aDelta, parentContent, nsnull, aResult);
|
||||||
|
|
||||||
|
// Bail. There's nothing else we can do.
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXULTreeOuterGroupFrame::FindNextRowContent(PRInt32& aDelta, nsIContent* aUpwardHint,
|
||||||
|
nsIContent* aDownwardHint,
|
||||||
|
nsIContent** aResult)
|
||||||
|
{
|
||||||
|
// Init to nsnull.
|
||||||
|
*aResult = nsnull;
|
||||||
|
|
||||||
|
// It disappoints me that this function is completely tied to the content nodes,
|
||||||
|
// but I can't see any other way to handle this. I don't have the frames, so I have nothing
|
||||||
|
// else to fall back on but the content nodes.
|
||||||
|
PRInt32 index = -1;
|
||||||
|
nsCOMPtr<nsIContent> parentContent;
|
||||||
|
if (aUpwardHint) {
|
||||||
|
aUpwardHint->GetParent(*getter_AddRefs(parentContent));
|
||||||
|
if (!parentContent) {
|
||||||
|
NS_ERROR("Parent content should not be NULL!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parentContent->IndexOf(aUpwardHint, index);
|
||||||
|
}
|
||||||
|
else if (aDownwardHint) {
|
||||||
|
parentContent = dont_QueryInterface(aDownwardHint);
|
||||||
|
}
|
||||||
|
|
||||||
|
PRInt32 childCount;
|
||||||
|
parentContent->ChildCount(childCount);
|
||||||
|
for (PRInt32 i = index+1; i < childCount; i++) {
|
||||||
|
nsCOMPtr<nsIContent> childContent;
|
||||||
|
parentContent->ChildAt(i, *getter_AddRefs(childContent));
|
||||||
|
nsCOMPtr<nsIAtom> tag;
|
||||||
|
childContent->GetTag(*getter_AddRefs(tag));
|
||||||
|
if (tag.get() == nsXULAtoms::treerow) {
|
||||||
|
aDelta--;
|
||||||
|
if (aDelta == 0) {
|
||||||
|
*aResult = childContent;
|
||||||
|
NS_IF_ADDREF(*aResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tag.get() == nsXULAtoms::treeitem) {
|
||||||
|
// Descend into this row group and try to find a next row.
|
||||||
|
FindNextRowContent(aDelta, nsnull, childContent, aResult);
|
||||||
|
if (aDelta == 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (tag.get() == nsXULAtoms::treechildren) {
|
||||||
|
// If it's open, descend into its treechildren node first.
|
||||||
|
nsCOMPtr<nsIAtom> openAtom = dont_AddRef(NS_NewAtom("open"));
|
||||||
|
nsAutoString isOpen;
|
||||||
|
parentContent->GetAttribute(kNameSpaceID_None, openAtom, isOpen);
|
||||||
|
if (isOpen.EqualsWithConversion("true")) {
|
||||||
|
FindNextRowContent(aDelta, nsnull, childContent, aResult);
|
||||||
|
if (aDelta == 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAtom> tag;
|
||||||
|
parentContent->GetTag(*getter_AddRefs(tag));
|
||||||
|
if (tag && tag.get() == nsXULAtoms::tree) {
|
||||||
|
// Hopeless. It ain't in there.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!aDownwardHint) // We didn't find it here. We need to go up to our parent, using ourselves as a hint.
|
||||||
|
FindNextRowContent(aDelta, parentContent, nsnull, aResult);
|
||||||
|
|
||||||
|
// Bail. There's nothing else we can do.
|
||||||
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Netscape Communications
|
||||||
|
* Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Original Author: David W. Hyatt (hyatt@netscape.com)
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsBoxLayoutState.h"
|
||||||
|
#include "nsISupportsArray.h"
|
||||||
|
#include "nsXULTreeGroupFrame.h"
|
||||||
|
#include "nsIScrollbarMediator.h"
|
||||||
|
#include "nsIPresContext.h"
|
||||||
|
|
||||||
|
class nsCSSFrameConstructor;
|
||||||
|
|
||||||
|
#define TREE_LINE_HEIGHT 225
|
||||||
|
|
||||||
|
class nsXULTreeRowGroupInfo {
|
||||||
|
public:
|
||||||
|
PRInt32 mRowCount;
|
||||||
|
nsCOMPtr<nsISupportsArray> mTickArray;
|
||||||
|
nsIContent* mLastChild;
|
||||||
|
|
||||||
|
nsXULTreeRowGroupInfo() :mRowCount(-1),mLastChild(nsnull)
|
||||||
|
{
|
||||||
|
NS_NewISupportsArray(getter_AddRefs(mTickArray));
|
||||||
|
};
|
||||||
|
|
||||||
|
~nsXULTreeRowGroupInfo() { Clear(); };
|
||||||
|
|
||||||
|
void Add(nsIContent* aContent) {
|
||||||
|
mTickArray->AppendElement(aContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear() {
|
||||||
|
mLastChild = nsnull;
|
||||||
|
mRowCount = -1;
|
||||||
|
mTickArray->Clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class nsXULTreeOuterGroupFrame : public nsXULTreeGroupFrame, public nsIScrollbarMediator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
friend nsresult NS_NewXULTreeOuterGroupFrame(nsIPresShell* aPresShell,
|
||||||
|
nsIFrame** aNewFrame,
|
||||||
|
PRBool aIsRoot = PR_FALSE,
|
||||||
|
nsIBoxLayout* aLayoutManager = nsnull,
|
||||||
|
PRBool aDefaultHorizontal = PR_TRUE);
|
||||||
|
|
||||||
|
NS_IMETHOD Init(nsIPresContext* aPresContext, nsIContent* aContent,
|
||||||
|
nsIFrame* aParent, nsIStyleContext* aContext, nsIFrame* aPrevInFlow);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
nsXULTreeOuterGroupFrame(nsIPresShell* aPresShell, PRBool aIsRoot = nsnull, nsIBoxLayout* aLayoutManager = nsnull, PRBool aDefaultHorizontal = PR_TRUE);
|
||||||
|
virtual ~nsXULTreeOuterGroupFrame();
|
||||||
|
|
||||||
|
void ComputeTotalRowCount(PRInt32& aRowCount, nsIContent* aParent);
|
||||||
|
|
||||||
|
public:
|
||||||
|
NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize)
|
||||||
|
{
|
||||||
|
NeedsRecalc();
|
||||||
|
return nsXULTreeGroupFrame::GetPrefSize(aBoxLayoutState, aSize);
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMETHOD IsOutermostFrame(PRBool *aResult) { *aResult = PR_TRUE; return NS_OK; };
|
||||||
|
|
||||||
|
PRInt32 GetRowCount() { if (mRowGroupInfo && (mRowGroupInfo->mRowCount != -1)) return mRowGroupInfo->mRowCount; PRInt32 count = 0;
|
||||||
|
ComputeTotalRowCount(count, mContent); mRowGroupInfo->mRowCount = count; return count; };
|
||||||
|
|
||||||
|
PRInt32 GetRowHeightTwips() {
|
||||||
|
return mRowHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearRowGroupInfo() { if (mRowGroupInfo) mRowGroupInfo->Clear(); NeedsRecalc(); };
|
||||||
|
|
||||||
|
void SetRowHeight(PRInt32 aRowHeight)
|
||||||
|
{
|
||||||
|
if (mRowHeight != aRowHeight) {
|
||||||
|
mRowHeight = aRowHeight;
|
||||||
|
nsBoxLayoutState state(mPresContext);
|
||||||
|
MarkDirtyChildren(state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
nscoord GetYPosition();
|
||||||
|
nscoord GetAvailableHeight();
|
||||||
|
|
||||||
|
NS_IMETHOD PositionChanged(PRInt32 aOldIndex, PRInt32 aNewIndex);
|
||||||
|
NS_IMETHOD ScrollbarButtonPressed(PRInt32 aOldIndex, PRInt32 aNewIndex);
|
||||||
|
|
||||||
|
void VerticalScroll(PRInt32 aDelta);
|
||||||
|
|
||||||
|
void ConstructContentChain(nsIContent* aRowContent);
|
||||||
|
void ConstructOldContentChain(nsIContent* aOldRowContent);
|
||||||
|
void CreateOldContentChain(nsIContent* aOldRowContent, nsIContent* topOfChain);
|
||||||
|
|
||||||
|
void FindChildOfCommonContentChainAncestor(nsIContent *startContent, nsIContent **child);
|
||||||
|
|
||||||
|
PRBool IsAncestor(nsIContent *aRowContent, nsIContent *aOldRowContent, nsIContent **firstDescendant);
|
||||||
|
|
||||||
|
void FindPreviousRowContent(PRInt32& aDelta, nsIContent* aUpwardHint,
|
||||||
|
nsIContent* aDownwardHint, nsIContent** aResult);
|
||||||
|
void FindNextRowContent(PRInt32& aDelta, nsIContent* aUpwardHint,
|
||||||
|
nsIContent* aDownwardHint, nsIContent** aResult);
|
||||||
|
void FindRowContentAtIndex(PRInt32& aIndex, nsIContent* aParent,
|
||||||
|
nsIContent** aResult);
|
||||||
|
|
||||||
|
NS_IMETHOD InternalPositionChanged(PRBool aUp, PRInt32 aDelta);
|
||||||
|
|
||||||
|
protected: // Data Members
|
||||||
|
nsXULTreeRowGroupInfo* mRowGroupInfo;
|
||||||
|
PRInt32 mRowHeight;
|
||||||
|
nscoord mOnePixel;
|
||||||
|
PRInt32 mCurrentIndex; // Row-based
|
||||||
|
PRInt32 mTwipIndex; // Not really accurate. Used to handle thumb dragging
|
||||||
|
}; // class nsXULTreeOuterGroupFrame
|
|
@ -48,6 +48,25 @@ NS_NewXULTreeSliceFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool a
|
||||||
} // NS_NewXULTreeSliceFrame
|
} // NS_NewXULTreeSliceFrame
|
||||||
|
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(nsrefcnt)
|
||||||
|
nsXULTreeSliceFrame::AddRef(void)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(nsrefcnt)
|
||||||
|
nsXULTreeSliceFrame::Release(void)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// QueryInterface
|
||||||
|
//
|
||||||
|
NS_INTERFACE_MAP_BEGIN(nsXULTreeSliceFrame)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIXULTreeSlice)
|
||||||
|
NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame)
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
nsXULTreeSliceFrame::nsXULTreeSliceFrame(nsIPresShell* aPresShell, PRBool aIsRoot, nsIBoxLayout* aLayoutManager, PRBool aIsHorizontal)
|
nsXULTreeSliceFrame::nsXULTreeSliceFrame(nsIPresShell* aPresShell, PRBool aIsRoot, nsIBoxLayout* aLayoutManager, PRBool aIsHorizontal)
|
||||||
:nsBoxFrame(aPresShell, aIsRoot, aLayoutManager, aIsHorizontal)
|
:nsBoxFrame(aPresShell, aIsRoot, aLayoutManager, aIsHorizontal)
|
||||||
|
|
|
@ -23,16 +23,24 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nsBoxFrame.h"
|
#include "nsBoxFrame.h"
|
||||||
|
#include "nsIXULTreeSlice.h"
|
||||||
|
|
||||||
class nsXULTreeSliceFrame : public nsBoxFrame
|
class nsXULTreeSliceFrame : public nsBoxFrame, public nsIXULTreeSlice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
friend nsresult NS_NewXULTreeSliceFrame(nsIPresShell* aPresShell,
|
friend nsresult NS_NewXULTreeSliceFrame(nsIPresShell* aPresShell,
|
||||||
nsIFrame** aNewFrame,
|
nsIFrame** aNewFrame,
|
||||||
PRBool aIsRoot = PR_FALSE,
|
PRBool aIsRoot = PR_FALSE,
|
||||||
nsIBoxLayout* aLayoutManager = nsnull,
|
nsIBoxLayout* aLayoutManager = nsnull,
|
||||||
PRBool aDefaultHorizontal = PR_TRUE);
|
PRBool aDefaultHorizontal = PR_TRUE);
|
||||||
|
|
||||||
|
// nsIXULTreeSlice
|
||||||
|
NS_IMETHOD IsOutermostFrame(PRBool* aResult) { *aResult = PR_FALSE; return NS_OK; };
|
||||||
|
NS_IMETHOD IsGroupFrame(PRBool* aResult) { *aResult = PR_FALSE; return NS_OK; };
|
||||||
|
NS_IMETHOD IsRowFrame(PRBool* aResult) { *aResult = PR_TRUE; return NS_OK; };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsXULTreeSliceFrame(nsIPresShell* aPresShell, PRBool aIsRoot = nsnull, nsIBoxLayout* aLayoutManager = nsnull, PRBool aDefaultHorizontal = PR_TRUE);
|
nsXULTreeSliceFrame(nsIPresShell* aPresShell, PRBool aIsRoot = nsnull, nsIBoxLayout* aLayoutManager = nsnull, PRBool aDefaultHorizontal = PR_TRUE);
|
||||||
virtual ~nsXULTreeSliceFrame();
|
virtual ~nsXULTreeSliceFrame();
|
||||||
|
|
Загрузка…
Ссылка в новой задаче