grid fixes for tree bugs

-r Hyatt
This commit is contained in:
evaughan%netscape.com 2000-07-10 20:10:27 +00:00
Родитель 94faf4f61c
Коммит 3f9c79ee07
14 изменённых файлов: 498 добавлений и 30 удалений

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

@ -111,6 +111,8 @@ XUL_ATOM(autostretch, "autostretch")
XUL_ATOM(autorepeatbutton, "autorepeatbutton")
XUL_ATOM(bulletinboard, "bulletinboard")
XUL_ATOM(titledbox, "titledbox")
XUL_ATOM(title, "title")
XUL_ATOM(titledboxContentPseudo, ":titledbox-content")

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

@ -85,3 +85,5 @@ NS_XULATOM(width);
NS_XULATOM(window);
NS_XULATOM(xulcontentsgenerated);
NS_XULATOM(scrollbox);
NS_XULATOM(left);
NS_XULATOM(top);

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

@ -3953,6 +3953,11 @@ nsXULElement::GetMappedAttributeImpact(const nsIAtom* aAttribute,
// Ignore 'width' and 'height' on a <window>
if (nsXULAtoms::width == aAttribute || nsXULAtoms::height == aAttribute)
aHint = NS_STYLE_HINT_NONE;
} else {
// if left or top changes we reflow. This will happen in xul containers that
// manage positioned children such as a bulletinboard.
if (nsXULAtoms::left == aAttribute || nsXULAtoms::top == aAttribute)
aHint = NS_STYLE_HINT_REFLOW;
}
return NS_OK;

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

@ -269,6 +269,9 @@ NS_NewTempleLayout ( nsIPresShell* aPresShell, nsCOMPtr<nsIBoxLayout>& aNewLayou
nsresult
NS_NewTreeLayout ( nsIPresShell* aPresShell, nsCOMPtr<nsIBoxLayout>& aNewLayout );
nsresult
NS_NewBulletinBoardLayout ( nsIPresShell* aPresShell, nsCOMPtr<nsIBoxLayout>& aNewLayout );
// end grid
#endif
@ -4064,7 +4067,10 @@ nsCSSFrameConstructor::HasGfxScrollbars()
}
}
return mHasGfxScrollbars;
//return mHasGfxScrollbars;
// we no longer support native scrollbars. Except in form elements. So
// we always return true
return PR_TRUE;
}
nsresult
@ -6135,6 +6141,36 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
}
// End of STACK CONSTRUCTION logic
// BULLETINBOARD CONSTRUCTION
else if (aTag == nsXULAtoms::bulletinboard) {
processChildren = PR_TRUE;
isReplaced = PR_TRUE;
nsCOMPtr<nsIBoxLayout> layout;
NS_NewBulletinBoardLayout(aPresShell, layout);
rv = NS_NewBoxFrame(aPresShell, &newFrame, PR_FALSE, layout);
const nsStyleDisplay* display = (const nsStyleDisplay*)
aStyleContext->GetStyleData(eStyleStruct_Display);
if (IsScrollable(aPresContext, display)) {
// set the top to be the newly created scrollframe
BuildScrollFrame(aPresShell, aPresContext, aState, aContent, aStyleContext, newFrame, aParentFrame,
topFrame, aStyleContext);
// we have a scrollframe so the parent becomes the scroll frame.
newFrame->GetParent(&aParentFrame);
primaryFrameSet = PR_TRUE;
frameHasBeenInitialized = PR_TRUE;
}
}
// End of STACK CONSTRUCTION logic
// DECK CONSTRUCTION
else if (aTag == nsXULAtoms::deck || aTag == nsXULAtoms::tabpanel) {
processChildren = PR_TRUE;
@ -6231,26 +6267,29 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
InitAndRestoreFrame(aPresContext, aState, aContent,
geometricParent, aStyleContext, nsnull, newFrame);
/*
// if our parent is a block frame then do things the way html likes it
// if not then we are in a box so do what boxes like. On example is boxes
// do not support the absolute positioning of their children. While html blocks
// thats why we call different things here.
geometricParent->GetFrameType(&frameType);
if ((frameType == nsLayoutAtoms::blockFrame) ||
(frameType == nsLayoutAtoms::areaFrame)) {
nsCOMPtr<nsIAtom> frameType;
geometricParent->GetFrameType(getter_AddRefs(frameType));
if ((frameType.get() == nsLayoutAtoms::blockFrame) ||
(frameType.get() == nsLayoutAtoms::areaFrame)) {
*/
// See if we need to create a view, e.g. the frame is absolutely positioned
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, newFrame,
aStyleContext, PR_FALSE);
/*
/*
} else {
// we are in a box so do the box thing.
nsBoxFrame::CreateViewForFrame(aPresContext, newFrame,
aStyleContext, PR_FALSE);
}
*/
}
// Process the child content if requested

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

@ -269,6 +269,9 @@ NS_NewTempleLayout ( nsIPresShell* aPresShell, nsCOMPtr<nsIBoxLayout>& aNewLayou
nsresult
NS_NewTreeLayout ( nsIPresShell* aPresShell, nsCOMPtr<nsIBoxLayout>& aNewLayout );
nsresult
NS_NewBulletinBoardLayout ( nsIPresShell* aPresShell, nsCOMPtr<nsIBoxLayout>& aNewLayout );
// end grid
#endif
@ -4064,7 +4067,10 @@ nsCSSFrameConstructor::HasGfxScrollbars()
}
}
return mHasGfxScrollbars;
//return mHasGfxScrollbars;
// we no longer support native scrollbars. Except in form elements. So
// we always return true
return PR_TRUE;
}
nsresult
@ -6135,6 +6141,36 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
}
// End of STACK CONSTRUCTION logic
// BULLETINBOARD CONSTRUCTION
else if (aTag == nsXULAtoms::bulletinboard) {
processChildren = PR_TRUE;
isReplaced = PR_TRUE;
nsCOMPtr<nsIBoxLayout> layout;
NS_NewBulletinBoardLayout(aPresShell, layout);
rv = NS_NewBoxFrame(aPresShell, &newFrame, PR_FALSE, layout);
const nsStyleDisplay* display = (const nsStyleDisplay*)
aStyleContext->GetStyleData(eStyleStruct_Display);
if (IsScrollable(aPresContext, display)) {
// set the top to be the newly created scrollframe
BuildScrollFrame(aPresShell, aPresContext, aState, aContent, aStyleContext, newFrame, aParentFrame,
topFrame, aStyleContext);
// we have a scrollframe so the parent becomes the scroll frame.
newFrame->GetParent(&aParentFrame);
primaryFrameSet = PR_TRUE;
frameHasBeenInitialized = PR_TRUE;
}
}
// End of STACK CONSTRUCTION logic
// DECK CONSTRUCTION
else if (aTag == nsXULAtoms::deck || aTag == nsXULAtoms::tabpanel) {
processChildren = PR_TRUE;
@ -6231,26 +6267,29 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell,
InitAndRestoreFrame(aPresContext, aState, aContent,
geometricParent, aStyleContext, nsnull, newFrame);
/*
// if our parent is a block frame then do things the way html likes it
// if not then we are in a box so do what boxes like. On example is boxes
// do not support the absolute positioning of their children. While html blocks
// thats why we call different things here.
geometricParent->GetFrameType(&frameType);
if ((frameType == nsLayoutAtoms::blockFrame) ||
(frameType == nsLayoutAtoms::areaFrame)) {
nsCOMPtr<nsIAtom> frameType;
geometricParent->GetFrameType(getter_AddRefs(frameType));
if ((frameType.get() == nsLayoutAtoms::blockFrame) ||
(frameType.get() == nsLayoutAtoms::areaFrame)) {
*/
// See if we need to create a view, e.g. the frame is absolutely positioned
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, newFrame,
aStyleContext, PR_FALSE);
/*
/*
} else {
// we are in a box so do the box thing.
nsBoxFrame::CreateViewForFrame(aPresContext, newFrame,
aStyleContext, PR_FALSE);
}
*/
}
// Process the child content if requested

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

@ -30,6 +30,7 @@ MODULE = layout
LIBRARY_NAME = gkxulbase_s
CPPSRCS = \
nsBulletinBoardLayout.cpp \
nsScrollBoxObject.cpp \
nsScrollBoxFrame.cpp \
nsTreeLayout.cpp \

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

@ -27,6 +27,7 @@ MODULE=raptor
DEFINES=-D_IMPL_NS_HTML -DWIN32_LEAN_AND_MEAN
CPPSRCS= \
nsBulletinBoardLayout.cpp \
nsScrollBoxFrame.cpp \
nsEditorBoxObject.cpp \
nsIFrameBoxObject.cpp \
@ -97,6 +98,7 @@ CPPSRCS= \
$(NULL)
CPP_OBJS= \
.\$(OBJDIR)\nsBulletinBoardLayout.obj \
.\$(OBJDIR)\nsScrollBoxFrame.obj \
.\$(OBJDIR)\nsEditorBoxObject.obj \
.\$(OBJDIR)\nsIFrameBoxObject.obj \

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

@ -434,6 +434,13 @@ nsBox::RelayoutDirtyChild(nsBoxLayoutState& aState, nsIBox* aChild)
GetFrame(&frame);
frame->GetFrameState(&state);
if (aChild != nsnull) {
nsCOMPtr<nsIBoxLayout> layout;
GetLayoutManager(getter_AddRefs(layout));
if (layout)
layout->ChildBecameDirty(this, aState, aChild);
}
// if we are not dirty mark ourselves dirty and tell our parent we are dirty too.
if (!(state & NS_FRAME_HAS_DIRTY_CHILDREN)) {
// Mark yourself as dirty and needing to be recalculated
@ -441,13 +448,6 @@ nsBox::RelayoutDirtyChild(nsBoxLayoutState& aState, nsIBox* aChild)
frame->SetFrameState(state);
NeedsRecalc();
if (aChild != nsnull) {
nsCOMPtr<nsIBoxLayout> layout;
GetLayoutManager(getter_AddRefs(layout));
if (layout)
layout->ChildBecameDirty(this, aState, aChild);
}
nsIBox* parent = nsnull;
GetParentBox(&parent);
if (parent)

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

@ -0,0 +1,290 @@
/* -*- 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):
*/
//
// Eric Vaughan
// Netscape Communications
//
// See documentation in associated header file
//
#include "nsBulletinBoardLayout.h"
#include "nsIStyleContext.h"
#include "nsCOMPtr.h"
#include "nsBoxLayoutState.h"
#include "nsBox.h"
#include "nsHTMLAtoms.h"
#include "nsXULAtoms.h"
#include "nsIContent.h"
#include "nsINameSpaceManager.h"
nsCOMPtr<nsIBoxLayout> nsBulletinBoardLayout::gInstance = new nsBulletinBoardLayout();
nsresult
NS_NewBulletinBoardLayout( nsIPresShell* aPresShell, nsCOMPtr<nsIBoxLayout>& aNewLayout)
{
// we have not instance variables so just return our static one.
aNewLayout = nsBulletinBoardLayout::gInstance;
return NS_OK;
}
nsBulletinBoardLayout::nsBulletinBoardLayout()
{
}
NS_IMETHODIMP
nsBulletinBoardLayout::GetPrefSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSize)
{
aSize.width = 0;
aSize.height = 0;
// we are as wide as the widest child plus its left offset
// we are tall as the tallest child plus its top offset
nsIBox* child = nsnull;
aBox->GetChildBox(&child);
while (child)
{
nsSize pref(0,0);
child->GetPrefSize(aState, pref);
AddMargin(child, pref);
AddOffset(aState, child, pref);
AddLargestSize(aSize, pref);
child->GetNextBox(&child);
}
// now add our border and padding and insets
AddBorderAndPadding(aBox, aSize);
AddInset(aBox, aSize);
return NS_OK;
}
NS_IMETHODIMP
nsBulletinBoardLayout::GetMinSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSize)
{
aSize.width = 0;
aSize.height = 0;
// run through all the children and get there min, max, and preferred sizes
// return us the size of the box
nsIBox* child = nsnull;
aBox->GetChildBox(&child);
while (child)
{
nsSize min(0,0);
child->GetMinSize(aState, min);
AddMargin(child, min);
AddOffset(aState, child, min);
AddLargestSize(aSize, min);
child->GetNextBox(&child);
}
// now add our border and padding and insets
AddBorderAndPadding(aBox, aSize);
AddInset(aBox,aSize);
return NS_OK;
}
NS_IMETHODIMP
nsBulletinBoardLayout::GetMaxSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSize)
{
aSize.width = NS_INTRINSICSIZE;
aSize.height = NS_INTRINSICSIZE;
// run through all the children and get there min, max, and preferred sizes
// return us the size of the box
nsIBox* child = nsnull;
aBox->GetChildBox(&child);
while (child)
{
// if completely redefined don't even ask our child for its size.
nsSize max(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
child->GetMaxSize(aState, max);
AddMargin(child, max);
AddOffset(aState, child, max);
AddSmallestSize(aSize, max);
child->GetNextBox(&child);
}
// now add our border and padding and insets
AddBorderAndPadding(aBox, aSize);
AddInset(aBox, aSize);
return NS_OK;
}
NS_IMETHODIMP
nsBulletinBoardLayout::GetAscent(nsIBox* aBox, nsBoxLayoutState& aState, nscoord& aAscent)
{
nsSize size(0,0);
GetPrefSize(aBox, aState, size);
aAscent = size.height;
return NS_OK;
}
nsresult
nsBulletinBoardLayout::AddOffset(nsBoxLayoutState& aState, nsIBox* aChild, nsSize& aSize)
{
nsSize offset(0,0);
// get the left and top offsets
const nsStylePosition* pos;
nsIFrame* frame;
aChild->GetFrame(&frame);
frame->GetStyleData(eStyleStruct_Position,(const nsStyleStruct*&) pos);
if (eStyleUnit_Coord == pos->mOffset.GetLeftUnit()) {
nsStyleCoord left = 0;
pos->mOffset.GetLeft(left);
offset.width = left.GetCoordValue();
}
if (eStyleUnit_Coord == pos->mOffset.GetTopUnit()) {
nsStyleCoord top = 0;
pos->mOffset.GetTop(top);
offset.height = top.GetCoordValue();
}
nsCOMPtr<nsIContent> content;
frame->GetContent(getter_AddRefs(content));
if (content) {
nsIPresContext* presContext = aState.GetPresContext();
nsAutoString value;
PRInt32 error;
if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::left, value))
{
float p2t;
presContext->GetScaledPixelsToTwips(&p2t);
value.Trim("%");
offset.width = NSIntPixelsToTwips(value.ToInteger(&error), p2t);
}
if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::top, value))
{
float p2t;
presContext->GetScaledPixelsToTwips(&p2t);
value.Trim("%");
offset.height = NSIntPixelsToTwips(value.ToInteger(&error), p2t);
}
}
aSize += offset;
return NS_OK;
}
NS_IMETHODIMP
nsBulletinBoardLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
{
nsRect clientRect;
aBox->GetClientRect(clientRect);
nsRect childRect;
nsIBox* child = nsnull;
aBox->GetChildBox(&child);
nsRect damageRect;
PRBool damageRectSet = PR_FALSE;
while (child)
{
// only layout dirty children
PRBool isDirty = PR_FALSE;
PRBool hasDirtyChildren = PR_FALSE;
child->IsDirty(isDirty);
child->HasDirtyChildren(hasDirtyChildren);
if (isDirty || hasDirtyChildren) {
nsRect oldRect;
child->GetBounds(oldRect);
// get the preferred size of the child
nsSize pref(0,0);
child->GetPrefSize(aState, pref);
// add in its margin
nsMargin margin;
child->GetMargin(margin);
// offset it from the inside of our left top border by the offset
nsSize offset(0,0);
AddOffset(aState, child, offset);
childRect.width = pref.width;
childRect.height = pref.height;
childRect.x = clientRect.x + offset.width + margin.left;
childRect.y = clientRect.y + offset.height + margin.top;
if (childRect != oldRect)
{
// redraw the new and old positions if the
// child moved.
// if the new and old rect intersect meaning we just moved a little
// then just redraw the intersection. If they don't intersect meaning
// we moved far redraw both separately.
if (childRect.Intersects(oldRect)) {
nsRect u;
u.UnionRect(oldRect, childRect);
aBox->Redraw(aState, &u);
} else {
aBox->Redraw(aState, &oldRect);
aBox->Redraw(aState, &childRect);
}
}
// layout child
child->SetBounds(aState, childRect);
child->Layout(aState);
}
child->GetNextBox(&child);
}
return NS_OK;
}

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

@ -0,0 +1,63 @@
/* -*- 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):
*/
/**
Eric D Vaughan
A frame that can have multiple children. Only one child may be displayed at one time. So the
can be flipped though like a deck of cards.
**/
#ifndef nsBulletinBoardLayout_h___
#define nsBulletinBoardLayout_h___
#include "nsBoxLayout.h"
#include "nsCOMPtr.h"
class nsBulletinBoardLayout : public nsBoxLayout
{
public:
friend nsresult NS_NewBulletinBoardLayout(nsIPresShell* aPresShell, nsCOMPtr<nsIBoxLayout>& aNewLayout);
nsBulletinBoardLayout();
NS_IMETHOD Layout(nsIBox* aBox, nsBoxLayoutState& aState);
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 GetAscent(nsIBox* aBox, nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent);
protected:
virtual nsresult AddOffset(nsBoxLayoutState& aState, nsIBox* aChild, nsSize& aSize);
private:
static nsCOMPtr<nsIBoxLayout> gInstance;
}; // class nsBulletinBoardLayout
#endif

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

@ -225,21 +225,37 @@ nsStackLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
if (childRect.height < 0)
childRect.height = 0;
child->SetBounds(aState, childRect);
child->Layout(aState);
child->GetBounds(childRect);
childRect.Inflate(margin);
// did the child push back on us and get bigger?
if (childRect.width > clientRect.width) {
clientRect.width = childRect.width;
grow = PR_TRUE;
}
if (childRect.height > clientRect.height) {
clientRect.height = childRect.height;
grow = PR_TRUE;
nsRect oldRect;
child->GetBounds(oldRect);
PRBool sizeChanged = (oldRect != childRect);
// only layout dirty children
PRBool isDirty = PR_FALSE;
PRBool hasDirtyChildren = PR_FALSE;
child->IsDirty(isDirty);
child->HasDirtyChildren(hasDirtyChildren);
if (sizeChanged || isDirty || hasDirtyChildren) {
child->SetBounds(aState, childRect);
child->Layout(aState);
child->GetBounds(childRect);
childRect.Inflate(margin);
// did the child push back on us and get bigger?
if (childRect.width > clientRect.width) {
clientRect.width = childRect.width;
grow = PR_TRUE;
}
if (childRect.height > clientRect.height) {
clientRect.height = childRect.height;
grow = PR_TRUE;
}
}
child->GetNextBox(&child);

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

@ -111,6 +111,8 @@ XUL_ATOM(autostretch, "autostretch")
XUL_ATOM(autorepeatbutton, "autorepeatbutton")
XUL_ATOM(bulletinboard, "bulletinboard")
XUL_ATOM(titledbox, "titledbox")
XUL_ATOM(title, "title")
XUL_ATOM(titledboxContentPseudo, ":titledbox-content")

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

@ -85,3 +85,5 @@ NS_XULATOM(width);
NS_XULATOM(window);
NS_XULATOM(xulcontentsgenerated);
NS_XULATOM(scrollbox);
NS_XULATOM(left);
NS_XULATOM(top);

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

@ -3953,6 +3953,11 @@ nsXULElement::GetMappedAttributeImpact(const nsIAtom* aAttribute,
// Ignore 'width' and 'height' on a <window>
if (nsXULAtoms::width == aAttribute || nsXULAtoms::height == aAttribute)
aHint = NS_STYLE_HINT_NONE;
} else {
// if left or top changes we reflow. This will happen in xul containers that
// manage positioned children such as a bulletinboard.
if (nsXULAtoms::left == aAttribute || nsXULAtoms::top == aAttribute)
aHint = NS_STYLE_HINT_REFLOW;
}
return NS_OK;