2000-03-31 07:02:06 +00:00
|
|
|
/* -*- 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):
|
|
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
//
|
|
|
|
// Eric Vaughan
|
|
|
|
// Netscape Communications
|
|
|
|
//
|
|
|
|
// See documentation in associated header file
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "nsBoxLayoutState.h"
|
|
|
|
#include "nsSprocketLayout.h"
|
|
|
|
#include "nsIStyleContext.h"
|
|
|
|
#include "nsIPresContext.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsIViewManager.h"
|
|
|
|
#include "nsIView.h"
|
|
|
|
#include "nsIPresShell.h"
|
|
|
|
#include "nsHTMLContainerFrame.h"
|
|
|
|
#include "nsBoxFrame.h"
|
|
|
|
#include "nsINameSpaceManager.h"
|
|
|
|
#include "nsHTMLAtoms.h"
|
|
|
|
#include "nsXULAtoms.h"
|
|
|
|
#include "nsBoxFrame.h"
|
|
|
|
|
2000-04-05 00:19:00 +00:00
|
|
|
nsCOMPtr<nsIBoxLayout> nsSprocketLayout::gInstance = new nsSprocketLayout();
|
|
|
|
|
2000-06-02 22:15:09 +00:00
|
|
|
//#define DEBUG_GROW
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
#define DEBUG_SPRING_SIZE 8
|
|
|
|
#define DEBUG_BORDER_SIZE 2
|
|
|
|
#define COIL_SIZE 8
|
|
|
|
|
2000-04-05 00:19:00 +00:00
|
|
|
|
|
|
|
nsresult
|
|
|
|
NS_NewSprocketLayout( nsIPresShell* aPresShell, nsCOMPtr<nsIBoxLayout>& aNewLayout)
|
|
|
|
{
|
|
|
|
// we have not instance variables so just return our static one.
|
|
|
|
aNewLayout = nsSprocketLayout::gInstance;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsSprocketLayout::nsSprocketLayout()
|
2000-03-31 07:02:06 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsSprocketLayout::IsHorizontal(nsIBox* aBox) const
|
|
|
|
{
|
|
|
|
nsIFrame* frame = nsnull;
|
|
|
|
aBox->GetFrame(&frame);
|
|
|
|
nsFrameState state;
|
|
|
|
frame->GetFrameState(&state);
|
|
|
|
return state & NS_STATE_IS_HORIZONTAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSprocketLayout::GetFrameState(nsIBox* aBox, nsFrameState& aState)
|
|
|
|
{
|
|
|
|
nsIFrame* frame = nsnull;
|
|
|
|
aBox->GetFrame(&frame);
|
|
|
|
frame->GetFrameState(&aState);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSprocketLayout::SetFrameState(nsIBox* aBox, nsFrameState aState)
|
|
|
|
{
|
|
|
|
nsIFrame* frame = nsnull;
|
|
|
|
aBox->GetFrame(&frame);
|
|
|
|
frame->SetFrameState(aState);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
|
|
|
|
{
|
2000-05-16 20:46:08 +00:00
|
|
|
// see if we are collapsed. If we are? its easy. Layout out each child at 0,0,0,0;
|
|
|
|
PRBool collapsed = PR_FALSE;
|
|
|
|
aBox->IsCollapsed(aState, collapsed);
|
|
|
|
if (collapsed) {
|
|
|
|
nsIBox* child;
|
|
|
|
aBox->GetChildBox(&child);
|
|
|
|
while(child)
|
|
|
|
{
|
|
|
|
nsContainerBox::LayoutChildAt(aState, child, nsRect(0,0,0,0));
|
|
|
|
child->GetNextBox(&child);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
aState.PushStackMemory();
|
|
|
|
|
|
|
|
// ----- figure out our size ----------
|
|
|
|
nsRect contentRect;
|
|
|
|
aBox->GetContentRect(contentRect);
|
|
|
|
|
|
|
|
// -- make sure we remove our border and padding ----
|
|
|
|
nsRect clientRect;
|
|
|
|
aBox->GetClientRect(clientRect);
|
|
|
|
|
|
|
|
nsRect originalClientRect(clientRect);
|
|
|
|
|
|
|
|
nsFrameState frameState = 0;
|
|
|
|
GetFrameState(aBox, frameState);
|
|
|
|
|
|
|
|
//if (frameState & NS_STATE_CURRENTLY_IN_DEBUG)
|
2000-10-28 22:17:53 +00:00
|
|
|
// printf("In debug\n");
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
// ----- build a list of our child desired sizes and computeds sizes ------
|
|
|
|
|
|
|
|
nsBoxSize* boxSizes = nsnull;
|
|
|
|
nsComputedBoxSize* computedBoxSizes = nsnull;
|
|
|
|
|
|
|
|
nscoord maxAscent = 0;
|
|
|
|
aBox->GetAscent(aState, maxAscent);
|
|
|
|
|
2000-04-26 04:00:29 +00:00
|
|
|
nscoord min = 0;
|
|
|
|
nscoord max = 0;
|
2000-03-31 07:02:06 +00:00
|
|
|
PRInt32 flexes = 0;
|
2000-04-26 04:00:29 +00:00
|
|
|
PopulateBoxSizes(aBox, aState, boxSizes, computedBoxSizes, min, max, flexes);
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-04-25 07:10:48 +00:00
|
|
|
nscoord size = clientRect.width;
|
2000-03-31 07:02:06 +00:00
|
|
|
if (!IsHorizontal(aBox))
|
2000-04-25 07:10:48 +00:00
|
|
|
size = clientRect.height;
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-04-25 07:10:48 +00:00
|
|
|
ComputeChildSizes(aBox, aState, size, boxSizes, computedBoxSizes);
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (IsHorizontal(aBox)) {
|
2000-04-25 07:10:48 +00:00
|
|
|
clientRect.width = size;
|
2000-04-26 04:00:29 +00:00
|
|
|
if (clientRect.height < min)
|
|
|
|
clientRect.height = min;
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
if (frameState & NS_STATE_AUTO_STRETCH) {
|
2000-04-26 04:00:29 +00:00
|
|
|
if (clientRect.height > max)
|
|
|
|
clientRect.height = max;
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
|
|
|
} else {
|
2000-04-25 07:10:48 +00:00
|
|
|
clientRect.height = size;
|
2000-04-26 04:00:29 +00:00
|
|
|
if (clientRect.width < min)
|
|
|
|
clientRect.width = min;
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
if (frameState & NS_STATE_AUTO_STRETCH) {
|
2000-04-26 04:00:29 +00:00
|
|
|
if (clientRect.width > max)
|
|
|
|
clientRect.width = max;
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------
|
|
|
|
// layout all children
|
|
|
|
// ----------------------
|
|
|
|
|
|
|
|
PRBool needsRedraw = PR_FALSE;
|
|
|
|
PRBool finished;
|
|
|
|
nscoord passes = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// ok what we want to do if flow each child at the location given in the spring.
|
|
|
|
// unfortunately after flowing a child it might get bigger. We have not control over this
|
|
|
|
// so it the child gets bigger or smaller than we expected we will have to do a 2nd, 3rd, 4th pass to
|
|
|
|
// adjust.
|
|
|
|
|
|
|
|
nscoord x = 0;
|
|
|
|
nscoord y = 0;
|
|
|
|
nsIBox::Halignment halign;
|
|
|
|
nsIBox::Valignment valign;
|
|
|
|
aBox->GetVAlign(valign);
|
|
|
|
aBox->GetHAlign(halign);
|
|
|
|
nscoord origX = 0;
|
|
|
|
nscoord origY = 0;
|
|
|
|
|
|
|
|
PRBool childResized = PR_FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
passes = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_REFLOW
|
|
|
|
if (passes > 0) {
|
|
|
|
AddIndents();
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("ChildResized doing pass: %d\n", passes);
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
finished = PR_TRUE;
|
|
|
|
|
|
|
|
x = clientRect.x;
|
|
|
|
y = clientRect.y;
|
|
|
|
|
2000-06-23 05:15:04 +00:00
|
|
|
//if (!(frameState & NS_STATE_AUTO_STRETCH)) {
|
2000-03-31 07:02:06 +00:00
|
|
|
if (frameState & NS_STATE_IS_HORIZONTAL) {
|
|
|
|
switch(halign) {
|
|
|
|
case nsBoxFrame::hAlign_Left:
|
|
|
|
x = clientRect.x;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsBoxFrame::hAlign_Center:
|
|
|
|
x = clientRect.x + (originalClientRect.width - clientRect.width)/2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsBoxFrame::hAlign_Right:
|
|
|
|
x = clientRect.x + (originalClientRect.width - clientRect.width);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch(valign) {
|
|
|
|
case nsBoxFrame::vAlign_Top:
|
|
|
|
case nsBoxFrame::vAlign_BaseLine:
|
|
|
|
y = clientRect.y;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsBoxFrame::vAlign_Middle:
|
|
|
|
y = clientRect.y + (originalClientRect.height - clientRect.height)/2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsBoxFrame::vAlign_Bottom:
|
|
|
|
y = clientRect.y + (originalClientRect.height - clientRect.height);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2000-06-23 05:15:04 +00:00
|
|
|
// }
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
origX = x;
|
|
|
|
origY = y;
|
|
|
|
|
|
|
|
nscoord nextX = x;
|
|
|
|
nscoord nextY = y;
|
|
|
|
|
|
|
|
nsComputedBoxSize* childComputedBoxSize = computedBoxSizes;
|
|
|
|
nsBoxSize* childBoxSize = boxSizes;
|
|
|
|
|
|
|
|
nsIBox* child = nsnull;
|
|
|
|
aBox->GetChildBox(&child);
|
|
|
|
|
|
|
|
PRInt32 count = 0;
|
2000-04-11 23:55:15 +00:00
|
|
|
while (child || (childBoxSize && childBoxSize->bogus))
|
2000-03-31 07:02:06 +00:00
|
|
|
{
|
|
|
|
nscoord width = clientRect.width;
|
|
|
|
nscoord height = clientRect.height;
|
|
|
|
|
|
|
|
nsSize prefSize(0,0);
|
|
|
|
nsSize minSize(0,0);
|
|
|
|
nsSize maxSize(0,0);
|
|
|
|
|
2000-04-11 23:55:15 +00:00
|
|
|
if (!childBoxSize->bogus) {
|
|
|
|
if (!(frameState & NS_STATE_AUTO_STRETCH)) {
|
|
|
|
child->GetPrefSize(aState, prefSize);
|
|
|
|
child->GetMinSize(aState, minSize);
|
|
|
|
child->GetMaxSize(aState, maxSize);
|
|
|
|
nsBox::BoundsCheck(minSize, prefSize, maxSize);
|
|
|
|
|
|
|
|
AddMargin(child, prefSize);
|
|
|
|
width = prefSize.width > originalClientRect.width ? originalClientRect.width : prefSize.width;
|
|
|
|
height = prefSize.height > originalClientRect.height ? originalClientRect.height : prefSize.height;
|
|
|
|
}
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// figure our our child's computed width and height
|
|
|
|
if (frameState & NS_STATE_IS_HORIZONTAL) {
|
|
|
|
width = childComputedBoxSize->size;
|
|
|
|
} else {
|
|
|
|
height = childComputedBoxSize->size;
|
|
|
|
}
|
|
|
|
|
2000-06-02 22:15:09 +00:00
|
|
|
if (frameState & NS_STATE_IS_HORIZONTAL)
|
|
|
|
x += (childBoxSize->left);
|
|
|
|
else
|
|
|
|
y += (childBoxSize->left);
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
nextX = x;
|
|
|
|
nextY = y;
|
|
|
|
|
|
|
|
nsRect childRect(x, y, width, height);
|
|
|
|
|
2000-05-16 20:46:08 +00:00
|
|
|
// if (!childBoxSize->collapsed) {
|
2000-04-11 23:55:15 +00:00
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
if (childRect.width > clientRect.width || childRect.height > clientRect.height) {
|
|
|
|
if (childRect.width > clientRect.width)
|
|
|
|
clientRect.width = childRect.width;
|
|
|
|
|
|
|
|
if (childRect.height > clientRect.height)
|
|
|
|
clientRect.height = childRect.height;
|
|
|
|
}
|
2000-05-16 20:46:08 +00:00
|
|
|
// }
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
ComputeChildsNextPosition(aBox, child,
|
|
|
|
x,
|
|
|
|
y,
|
|
|
|
nextX,
|
|
|
|
nextY,
|
|
|
|
childRect,
|
|
|
|
originalClientRect,
|
|
|
|
childBoxSize->ascent,
|
|
|
|
maxAscent);
|
|
|
|
|
|
|
|
|
2000-06-02 22:15:09 +00:00
|
|
|
if (frameState & NS_STATE_IS_HORIZONTAL)
|
|
|
|
nextX += (childBoxSize->right);
|
|
|
|
else
|
|
|
|
nextY += (childBoxSize->right);
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
childRect.x = x;
|
|
|
|
childRect.y = y;
|
|
|
|
|
2000-04-11 23:55:15 +00:00
|
|
|
if (childBoxSize->bogus)
|
|
|
|
{
|
|
|
|
childComputedBoxSize = childComputedBoxSize->next;
|
|
|
|
childBoxSize = childBoxSize->next;
|
|
|
|
count++;
|
|
|
|
x = nextX;
|
|
|
|
y = nextY;
|
|
|
|
continue;
|
|
|
|
}
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-04-11 23:55:15 +00:00
|
|
|
nsMargin margin(0,0,0,0);
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
PRBool layout = PR_TRUE;
|
|
|
|
|
2000-04-11 23:55:15 +00:00
|
|
|
child->GetMargin(margin);
|
2000-05-31 20:14:28 +00:00
|
|
|
//if (childRect.width >= margin.left + margin.right && childRect.height >= margin.top + margin.bottom)
|
|
|
|
childRect.Deflate(margin);
|
|
|
|
if (childRect.width < 0)
|
2000-06-02 22:15:09 +00:00
|
|
|
childRect.width = 0;
|
|
|
|
|
2000-05-31 20:14:28 +00:00
|
|
|
if (childRect.height < 0)
|
2000-06-02 22:15:09 +00:00
|
|
|
childRect.height = 0;
|
2000-04-11 23:55:15 +00:00
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
if (passes > 0) {
|
|
|
|
layout = PR_FALSE;
|
|
|
|
} else {
|
|
|
|
// always layout if we are dirty or have dirty children
|
|
|
|
PRBool dirty = PR_FALSE;
|
|
|
|
PRBool dirtyChildren = PR_FALSE;
|
|
|
|
child->IsDirty(dirty);
|
|
|
|
child->HasDirtyChildren(dirtyChildren);
|
|
|
|
if (!(dirty || dirtyChildren) && aState.GetLayoutReason() != nsBoxLayoutState::Initial) {
|
|
|
|
layout = PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRect oldRect(0,0,0,0);
|
2000-04-11 23:55:15 +00:00
|
|
|
PRBool sizeChanged = PR_FALSE;
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-05-16 20:46:08 +00:00
|
|
|
// if (childBoxSize->collapsed || layout) {
|
2000-04-11 23:55:15 +00:00
|
|
|
child->GetBounds(oldRect);
|
|
|
|
child->SetBounds(aState, childRect);
|
|
|
|
sizeChanged = (childRect.width != oldRect.width || childRect.height != oldRect.height);
|
2000-05-16 20:46:08 +00:00
|
|
|
// }
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-06-06 01:25:03 +00:00
|
|
|
PRBool possibleRedraw = PR_FALSE;
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
if (sizeChanged) {
|
|
|
|
nsSize maxSize;
|
|
|
|
child->GetMaxSize(aState, maxSize);
|
|
|
|
|
|
|
|
// make sure the size is in our max size.
|
|
|
|
if (childRect.width > maxSize.width)
|
|
|
|
childRect.width = maxSize.width;
|
|
|
|
|
|
|
|
if (childRect.height > maxSize.height)
|
|
|
|
childRect.height = maxSize.height;
|
|
|
|
|
|
|
|
// set it again
|
|
|
|
child->SetBounds(aState, childRect);
|
|
|
|
|
2000-06-06 01:25:03 +00:00
|
|
|
// ok a child changed size so we should redraw the whole box. But it still has the possibility of
|
|
|
|
// redeeming itself. If it happens to get bigger during layout like
|
|
|
|
// wrapping text might. It may still end up the same size as it was. Then
|
|
|
|
// we don't need to redraw ourselves.
|
|
|
|
possibleRedraw = PR_TRUE;
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (layout || sizeChanged) {
|
|
|
|
child->Layout(aState);
|
|
|
|
}
|
2000-04-11 23:55:15 +00:00
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
// make collapsed children not show up
|
2000-05-16 20:46:08 +00:00
|
|
|
// if (childBoxSize && childBoxSize->collapsed) {
|
|
|
|
// if (layout || sizeChanged)
|
|
|
|
// child->Collapse(aState);
|
|
|
|
// else
|
|
|
|
// child->SetBounds(aState, nsRect(0,0,0,0));
|
|
|
|
//} else
|
|
|
|
{
|
2000-03-31 07:02:06 +00:00
|
|
|
// if the child was html it may have changed its rect. Lets look
|
|
|
|
nsRect newChildRect;
|
|
|
|
child->GetBounds(newChildRect);
|
|
|
|
|
|
|
|
if (newChildRect != childRect)
|
|
|
|
{
|
2000-06-02 22:15:09 +00:00
|
|
|
#ifdef DEBUG_GROW
|
|
|
|
child->DumpBox(stdout);
|
2000-10-28 22:17:53 +00:00
|
|
|
printf(" GREW from (%d,%d) -> (%d,%d)\n", childRect.width, childRect.height, newChildRect.width, newChildRect.height);
|
2000-06-02 22:15:09 +00:00
|
|
|
#endif
|
2000-03-31 07:02:06 +00:00
|
|
|
newChildRect.Inflate(margin);
|
|
|
|
childRect.Inflate(margin);
|
|
|
|
|
|
|
|
// ok the child changed size
|
|
|
|
ChildResized(aBox,
|
|
|
|
aState,
|
|
|
|
child,
|
|
|
|
childBoxSize,
|
|
|
|
childComputedBoxSize,
|
|
|
|
boxSizes,
|
|
|
|
computedBoxSizes,
|
|
|
|
childRect,
|
|
|
|
newChildRect,
|
|
|
|
clientRect,
|
|
|
|
flexes,
|
|
|
|
finished);
|
|
|
|
|
|
|
|
childResized = PR_TRUE;
|
|
|
|
|
|
|
|
if (clientRect.width > originalClientRect.width || clientRect.height > originalClientRect.height) {
|
|
|
|
if (clientRect.width > originalClientRect.width)
|
|
|
|
originalClientRect.width = clientRect.width;
|
|
|
|
|
|
|
|
if (clientRect.height > originalClientRect.height)
|
|
|
|
originalClientRect.height = clientRect.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// if the child resized then recompute it position.
|
|
|
|
ComputeChildsNextPosition(aBox, child,
|
|
|
|
x,
|
|
|
|
y,
|
|
|
|
nextX,
|
|
|
|
nextY,
|
|
|
|
newChildRect,
|
|
|
|
originalClientRect,
|
|
|
|
childBoxSize->ascent,
|
|
|
|
maxAscent);
|
|
|
|
|
|
|
|
newChildRect.x = x;
|
|
|
|
newChildRect.y = y;
|
|
|
|
|
2000-05-16 20:46:08 +00:00
|
|
|
if (newChildRect.width >= margin.left + margin.right && newChildRect.height >= margin.top + margin.bottom)
|
|
|
|
newChildRect.Deflate(margin);
|
|
|
|
|
|
|
|
if (childRect.width >= margin.left + margin.right && childRect.height >= margin.top + margin.bottom)
|
|
|
|
childRect.Deflate(margin);
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
child->SetBounds(aState, newChildRect);
|
|
|
|
|
2000-06-06 01:25:03 +00:00
|
|
|
// if the child resized but was the exact size it was. Don't redraw.
|
|
|
|
if (oldRect.width == newChildRect.width || oldRect.height == newChildRect.height)
|
|
|
|
possibleRedraw = PR_FALSE;
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
// if we are the first we don't need to do a second pass
|
|
|
|
if (count == 0)
|
|
|
|
finished = PR_TRUE;
|
|
|
|
}
|
2000-04-11 23:55:15 +00:00
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
x = nextX;
|
|
|
|
y = nextY;
|
|
|
|
}
|
|
|
|
|
2000-06-06 01:25:03 +00:00
|
|
|
if (possibleRedraw)
|
|
|
|
needsRedraw = PR_TRUE;
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
childComputedBoxSize = childComputedBoxSize->next;
|
|
|
|
childBoxSize = childBoxSize->next;
|
|
|
|
|
|
|
|
child->GetNextBox(&child);
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
passes++;
|
2000-04-26 04:00:29 +00:00
|
|
|
NS_ASSERTION(passes < 10, "A Box's child is constantly growing!!!!!");
|
2000-03-31 07:02:06 +00:00
|
|
|
if (passes > 10) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (PR_FALSE == finished);
|
|
|
|
|
|
|
|
while(boxSizes)
|
|
|
|
{
|
2000-04-05 23:46:48 +00:00
|
|
|
nsBoxSize* toDelete = boxSizes;
|
2000-03-31 07:02:06 +00:00
|
|
|
boxSizes = boxSizes->next;
|
|
|
|
delete toDelete;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(computedBoxSizes)
|
|
|
|
{
|
2000-04-05 23:46:48 +00:00
|
|
|
nsComputedBoxSize* toDelete = computedBoxSizes;
|
2000-03-31 07:02:06 +00:00
|
|
|
computedBoxSizes = computedBoxSizes->next;
|
|
|
|
delete toDelete;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (childResized) {
|
|
|
|
// see if one of our children forced us to get bigger
|
|
|
|
nsRect tmpClientRect(originalClientRect);
|
|
|
|
nsMargin bp(0,0,0,0);
|
|
|
|
aBox->GetBorderAndPadding(bp);
|
|
|
|
tmpClientRect.Inflate(bp);
|
|
|
|
aBox->GetInset(bp);
|
|
|
|
tmpClientRect.Inflate(bp);
|
|
|
|
|
|
|
|
if (tmpClientRect.width > contentRect.width || tmpClientRect.height > contentRect.height)
|
|
|
|
{
|
|
|
|
// if it did reset our bounds.
|
|
|
|
nsRect bounds(0,0,0,0);
|
|
|
|
aBox->GetBounds(bounds);
|
|
|
|
if (tmpClientRect.width > contentRect.width)
|
|
|
|
bounds.width = tmpClientRect.width;
|
|
|
|
|
|
|
|
if (tmpClientRect.height > contentRect.height)
|
|
|
|
bounds.height = tmpClientRect.height;
|
|
|
|
|
|
|
|
aBox->SetBounds(aState, bounds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
x = clientRect.x;
|
|
|
|
y = clientRect.y;
|
|
|
|
|
2000-06-23 05:15:04 +00:00
|
|
|
//if (!(frameState & NS_STATE_AUTO_STRETCH)) {
|
2000-03-31 07:02:06 +00:00
|
|
|
if (frameState & NS_STATE_IS_HORIZONTAL) {
|
|
|
|
switch(halign) {
|
|
|
|
case nsBoxFrame::hAlign_Left:
|
|
|
|
x = clientRect.x;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsBoxFrame::hAlign_Center:
|
|
|
|
x = clientRect.x + (originalClientRect.width - clientRect.width)/2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsBoxFrame::hAlign_Right:
|
|
|
|
x = clientRect.x + (originalClientRect.width - clientRect.width);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch(valign) {
|
|
|
|
case nsBoxFrame::vAlign_Top:
|
|
|
|
case nsBoxFrame::vAlign_BaseLine:
|
|
|
|
y = clientRect.y;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsBoxFrame::vAlign_Middle:
|
|
|
|
y = clientRect.y + (originalClientRect.height - clientRect.height)/2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsBoxFrame::vAlign_Bottom:
|
|
|
|
y = clientRect.y + (originalClientRect.height - clientRect.height);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2000-06-23 05:15:04 +00:00
|
|
|
//}
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
if (x != origX || y != origY) {
|
|
|
|
nsIBox* child = nsnull;
|
|
|
|
// reposition all our children
|
|
|
|
aBox->GetChildBox(&child);
|
|
|
|
|
|
|
|
while (child)
|
|
|
|
{
|
|
|
|
nsRect childRect;
|
|
|
|
child->GetBounds(childRect);
|
|
|
|
childRect.x += (x - origX);
|
|
|
|
childRect.y += (y - origY);
|
|
|
|
child->SetBounds(aState, childRect);
|
|
|
|
child->GetNextBox(&child);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (needsRedraw)
|
|
|
|
aBox->Redraw(aState);
|
|
|
|
|
|
|
|
aState.PopStackMemory();
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSprocketLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBoxSize*& aBoxSizes, nsComputedBoxSize*& aComputedBoxSizes, nscoord& aMinSize, nscoord& aMaxSize, PRInt32& aFlexes)
|
|
|
|
{
|
2000-06-23 05:15:04 +00:00
|
|
|
// used for the equal size flag
|
|
|
|
nscoord biggestPrefWidth = 0;
|
|
|
|
nscoord biggestMinWidth = 0;
|
|
|
|
nscoord smallestMaxWidth = NS_INTRINSICSIZE;
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
nsFrameState frameState = 0;
|
|
|
|
GetFrameState(aBox, frameState);
|
|
|
|
|
|
|
|
//if (frameState & NS_STATE_CURRENTLY_IN_DEBUG)
|
2000-10-28 22:17:53 +00:00
|
|
|
// printf("In debug\n");
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
aMinSize = 0;
|
|
|
|
aMaxSize = NS_INTRINSICSIZE;
|
|
|
|
|
|
|
|
PRBool isHorizontal;
|
|
|
|
|
|
|
|
if (IsHorizontal(aBox))
|
|
|
|
isHorizontal = PR_TRUE;
|
|
|
|
else
|
|
|
|
isHorizontal = PR_FALSE;
|
|
|
|
|
|
|
|
// this is a nice little optimization
|
|
|
|
// it turns out that if we only have 1 flexable child
|
|
|
|
// then it does not matter what its prefered size is
|
|
|
|
// there is nothing to flex it relative. This is great
|
|
|
|
// because we can avoid asking for a preferred size in this
|
|
|
|
// case. Why is this good? Well you might have html inside it
|
|
|
|
// and asking html for its preferred size is rather expensive.
|
|
|
|
// so we can just optimize it out this way.
|
|
|
|
|
|
|
|
// set flexes
|
|
|
|
nsIBox* child = nsnull;
|
|
|
|
aBox->GetChildBox(&child);
|
|
|
|
|
|
|
|
aFlexes = 0;
|
2000-04-18 00:17:00 +00:00
|
|
|
nsBoxSize* currentBox = nsnull;
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-04-18 00:17:00 +00:00
|
|
|
/*
|
|
|
|
nsBoxSize* start = aBoxSizes;
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
while(child)
|
|
|
|
{
|
2000-04-18 00:17:00 +00:00
|
|
|
// ok if we started with a list move down the list
|
|
|
|
// until we reach the end. Then start looking at childen.
|
|
|
|
// This feature is used extensively for Grid.
|
2000-03-31 07:02:06 +00:00
|
|
|
nscoord flex = 0;
|
|
|
|
|
2000-04-18 00:17:00 +00:00
|
|
|
if (!start) {
|
|
|
|
if (!currentBox) {
|
|
|
|
aBoxSizes = new (aState) nsBoxSize();
|
|
|
|
currentBox = aBoxSizes;
|
|
|
|
} else {
|
|
|
|
currentBox->next = new (aState) nsBoxSize();
|
|
|
|
currentBox = currentBox->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
child->GetFlex(aState, flex);
|
|
|
|
PRBool collapsed = PR_FALSE;
|
|
|
|
child->IsCollapsed(aState, collapsed);
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-04-18 00:17:00 +00:00
|
|
|
currentBox->flex = flex;
|
|
|
|
currentBox->collapsed = collapsed;
|
|
|
|
} else {
|
|
|
|
flex = start->flex;
|
|
|
|
start = start->next;
|
|
|
|
}
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
if (flex > 0)
|
|
|
|
aFlexes++;
|
|
|
|
|
|
|
|
child->GetNextBox(&child);
|
|
|
|
}
|
2000-04-18 00:17:00 +00:00
|
|
|
*/
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
// get pref, min, max
|
|
|
|
aBox->GetChildBox(&child);
|
|
|
|
currentBox = aBoxSizes;
|
2000-04-18 00:17:00 +00:00
|
|
|
nsBoxSize* last = nsnull;
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
while(child)
|
|
|
|
{
|
|
|
|
nsSize pref(0,0);
|
|
|
|
nsSize min(0,0);
|
2000-04-18 00:17:00 +00:00
|
|
|
nsSize max(NS_INTRINSICSIZE,NS_INTRINSICSIZE);
|
2000-05-16 20:46:08 +00:00
|
|
|
nscoord ascent = 0;
|
|
|
|
|
|
|
|
PRBool collapsed = PR_FALSE;
|
|
|
|
child->IsCollapsed(aState, collapsed);
|
2000-04-18 00:17:00 +00:00
|
|
|
|
2000-05-16 20:46:08 +00:00
|
|
|
if (!collapsed) {
|
2000-04-18 00:17:00 +00:00
|
|
|
// only one flexible child? Cool we will just make its preferred size
|
|
|
|
// 0 then and not even have to ask for it.
|
|
|
|
//if (flexes != 1) {
|
2000-05-16 20:46:08 +00:00
|
|
|
|
|
|
|
child->GetPrefSize(aState, pref);
|
|
|
|
child->GetMinSize(aState, min);
|
|
|
|
child->GetMaxSize(aState, max);
|
|
|
|
child->GetAscent(aState, ascent);
|
|
|
|
nsMargin margin;
|
|
|
|
child->GetMargin(margin);
|
|
|
|
ascent += margin.top + margin.bottom;
|
2000-04-18 00:17:00 +00:00
|
|
|
//}
|
|
|
|
|
2000-05-16 20:46:08 +00:00
|
|
|
nsBox::BoundsCheck(min, pref, max);
|
2000-04-18 00:17:00 +00:00
|
|
|
|
2000-05-16 20:46:08 +00:00
|
|
|
AddMargin(child, pref);
|
|
|
|
AddMargin(child, min);
|
|
|
|
AddMargin(child, max);
|
|
|
|
}
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-04-18 00:17:00 +00:00
|
|
|
if (!currentBox) {
|
|
|
|
// create one.
|
|
|
|
currentBox = new (aState) nsBoxSize();
|
|
|
|
if (!aBoxSizes) {
|
|
|
|
aBoxSizes = currentBox;
|
|
|
|
last = aBoxSizes;
|
2000-03-31 07:02:06 +00:00
|
|
|
} else {
|
2000-04-18 00:17:00 +00:00
|
|
|
last->next = currentBox;
|
|
|
|
last = currentBox;
|
|
|
|
}
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-04-18 00:17:00 +00:00
|
|
|
nscoord minWidth;
|
|
|
|
nscoord maxWidth;
|
|
|
|
nscoord prefWidth;
|
|
|
|
|
|
|
|
// get sizes from child
|
|
|
|
if (isHorizontal) {
|
|
|
|
minWidth = min.width;
|
|
|
|
maxWidth = max.width;
|
|
|
|
prefWidth = pref.width;
|
|
|
|
} else {
|
|
|
|
minWidth = min.height;
|
|
|
|
maxWidth = max.height;
|
|
|
|
prefWidth = pref.height;
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
|
|
|
|
2000-04-18 00:17:00 +00:00
|
|
|
nscoord flex = 0;
|
|
|
|
child->GetFlex(aState, flex);
|
|
|
|
|
2000-05-16 20:46:08 +00:00
|
|
|
// set them if you collapsed you are not flexible.
|
|
|
|
if (collapsed)
|
|
|
|
currentBox->flex = 0;
|
|
|
|
else
|
|
|
|
currentBox->flex = flex;
|
|
|
|
|
2000-06-23 05:15:04 +00:00
|
|
|
// we we specified all our children are equal size;
|
|
|
|
if (frameState & NS_STATE_EQUAL_SIZE) {
|
2000-04-18 00:17:00 +00:00
|
|
|
|
2000-06-23 05:15:04 +00:00
|
|
|
if (prefWidth > biggestPrefWidth)
|
|
|
|
biggestPrefWidth = prefWidth;
|
|
|
|
|
|
|
|
if (minWidth > biggestMinWidth)
|
|
|
|
biggestMinWidth = minWidth;
|
|
|
|
|
|
|
|
if (maxWidth < smallestMaxWidth)
|
|
|
|
smallestMaxWidth = maxWidth;
|
|
|
|
} else { // not we can set our children right now.
|
|
|
|
currentBox->pref = prefWidth;
|
|
|
|
currentBox->min = minWidth;
|
|
|
|
currentBox->max = maxWidth;
|
|
|
|
}
|
2000-05-16 20:46:08 +00:00
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
NS_ASSERTION(minWidth <= prefWidth && prefWidth <= maxWidth,"Bad min, pref, max widths!");
|
|
|
|
|
2000-04-18 00:17:00 +00:00
|
|
|
}
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-04-18 00:17:00 +00:00
|
|
|
if (!isHorizontal) {
|
|
|
|
if (min.width > aMinSize)
|
|
|
|
aMinSize = min.width;
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-04-18 00:17:00 +00:00
|
|
|
if (max.width < aMaxSize)
|
|
|
|
aMaxSize = max.width;
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-04-18 00:17:00 +00:00
|
|
|
} else {
|
|
|
|
if (min.height > aMinSize)
|
|
|
|
aMinSize = min.height;
|
|
|
|
|
|
|
|
if (max.height < aMaxSize)
|
|
|
|
aMaxSize = max.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
currentBox->ascent = ascent;
|
2000-06-23 05:15:04 +00:00
|
|
|
currentBox->collapsed = collapsed;
|
2000-04-18 00:17:00 +00:00
|
|
|
aFlexes += currentBox->flex;
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
child->GetNextBox(&child);
|
2000-04-18 00:17:00 +00:00
|
|
|
|
|
|
|
last = currentBox;
|
2000-03-31 07:02:06 +00:00
|
|
|
currentBox = currentBox->next;
|
2000-04-18 00:17:00 +00:00
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
2000-06-23 05:15:04 +00:00
|
|
|
|
|
|
|
// we we specified all our children are equal size;
|
|
|
|
if (frameState & NS_STATE_EQUAL_SIZE) {
|
|
|
|
currentBox = aBoxSizes;
|
|
|
|
|
|
|
|
while(currentBox)
|
|
|
|
{
|
|
|
|
if (!currentBox->collapsed) {
|
|
|
|
currentBox->pref = biggestPrefWidth;
|
|
|
|
currentBox->min = biggestMinWidth;
|
|
|
|
currentBox->max = smallestMaxWidth;
|
|
|
|
} else {
|
|
|
|
currentBox->pref = 0;
|
|
|
|
currentBox->min = 0;
|
|
|
|
currentBox->max = 0;
|
|
|
|
}
|
|
|
|
currentBox = currentBox->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSprocketLayout::ComputeChildsNextPosition(nsIBox* aBox,
|
|
|
|
nsIBox* aChild,
|
|
|
|
nscoord& aCurX,
|
|
|
|
nscoord& aCurY,
|
|
|
|
nscoord& aNextX,
|
|
|
|
nscoord& aNextY,
|
|
|
|
const nsRect& aCurrentChildSize,
|
|
|
|
const nsRect& aBoxRect,
|
|
|
|
nscoord childAscent,
|
|
|
|
nscoord aMaxAscent)
|
|
|
|
{
|
|
|
|
nsFrameState frameState = 0;
|
|
|
|
GetFrameState(aBox, frameState);
|
|
|
|
|
|
|
|
nsIBox::Halignment halign;
|
|
|
|
nsIBox::Valignment valign;
|
|
|
|
aBox->GetVAlign(valign);
|
|
|
|
aBox->GetHAlign(halign);
|
|
|
|
|
|
|
|
if (IsHorizontal(aBox)) {
|
|
|
|
aNextX = aCurX + aCurrentChildSize.width;
|
|
|
|
|
|
|
|
if (frameState & NS_STATE_AUTO_STRETCH) {
|
|
|
|
aCurY = aBoxRect.y;
|
|
|
|
} else {
|
|
|
|
switch (valign)
|
|
|
|
{
|
|
|
|
case nsBoxFrame::vAlign_BaseLine:
|
|
|
|
aCurY = aBoxRect.y + (aMaxAscent - childAscent);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsBoxFrame::vAlign_Top:
|
|
|
|
aCurY = aBoxRect.y;
|
|
|
|
break;
|
|
|
|
case nsBoxFrame::vAlign_Middle:
|
|
|
|
aCurY = aBoxRect.y + (aBoxRect.height/2 - aCurrentChildSize.height/2);
|
|
|
|
break;
|
|
|
|
case nsBoxFrame::vAlign_Bottom:
|
|
|
|
aCurY = aBoxRect.y + aBoxRect.height - aCurrentChildSize.height;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
aNextY = aCurY + aCurrentChildSize.height;
|
|
|
|
if (frameState & NS_STATE_AUTO_STRETCH) {
|
|
|
|
aCurX = aBoxRect.x;
|
|
|
|
} else {
|
|
|
|
switch (halign)
|
|
|
|
{
|
|
|
|
case nsBoxFrame::hAlign_Left:
|
|
|
|
aCurX = aBoxRect.x;
|
|
|
|
break;
|
|
|
|
case nsBoxFrame::hAlign_Center:
|
|
|
|
aCurX = aBoxRect.x + (aBoxRect.width/2 - aCurrentChildSize.width/2);
|
|
|
|
break;
|
|
|
|
case nsBoxFrame::hAlign_Right:
|
|
|
|
aCurX = aBoxRect.x + aBoxRect.width - aCurrentChildSize.width;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSprocketLayout::ChildResized(nsIBox* aBox,
|
|
|
|
nsBoxLayoutState& aState,
|
|
|
|
nsIBox* aChild,
|
|
|
|
nsBoxSize* aChildBoxSize,
|
|
|
|
nsComputedBoxSize* aChildComputedSize,
|
|
|
|
nsBoxSize* aBoxSizes,
|
|
|
|
nsComputedBoxSize* aComputedBoxSizes,
|
|
|
|
const nsRect& aChildLayoutRect,
|
|
|
|
nsRect& aChildActualRect,
|
|
|
|
nsRect& aContainingRect,
|
|
|
|
PRInt32 aFlexes,
|
|
|
|
PRBool& aFinished)
|
|
|
|
|
|
|
|
{
|
|
|
|
nsRect childCurrentRect(aChildLayoutRect);
|
|
|
|
|
|
|
|
PRBool isHorizontal = IsHorizontal(aBox);
|
|
|
|
nscoord childLayoutWidth = GET_WIDTH(aChildLayoutRect,isHorizontal);
|
|
|
|
nscoord& childActualWidth = GET_WIDTH(aChildActualRect,isHorizontal);
|
|
|
|
nscoord& containingWidth = GET_WIDTH(aContainingRect,isHorizontal);
|
|
|
|
|
2000-04-26 04:00:29 +00:00
|
|
|
//nscoord childLayoutHeight = GET_HEIGHT(aChildLayoutRect,isHorizontal);
|
2000-03-31 07:02:06 +00:00
|
|
|
nscoord& childActualHeight = GET_HEIGHT(aChildActualRect,isHorizontal);
|
|
|
|
nscoord& containingHeight = GET_HEIGHT(aContainingRect,isHorizontal);
|
|
|
|
|
|
|
|
PRBool recompute = PR_FALSE;
|
|
|
|
|
|
|
|
// if we are a horizontal box see if the child will fit inside us.
|
|
|
|
if ( childActualHeight > containingHeight) {
|
|
|
|
// if we are a horizontal box and the the child it bigger than our height
|
|
|
|
|
|
|
|
// ok if the height changed then we need to reflow everyone but us at the new height
|
|
|
|
// so we will set the changed index to be us. And signal that we need a new pass.
|
|
|
|
|
|
|
|
nsSize max(0,0);
|
|
|
|
aChild->GetMaxSize(aState, max);
|
2000-04-05 23:46:48 +00:00
|
|
|
AddMargin(aChild, max);
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
if (isHorizontal)
|
|
|
|
childActualHeight = max.height < childActualHeight ? max.height : childActualHeight;
|
|
|
|
else
|
|
|
|
childActualHeight = max.width < childActualHeight ? max.width : childActualHeight;
|
|
|
|
|
|
|
|
// only set if it changes
|
|
|
|
if (childActualHeight > containingHeight) {
|
|
|
|
containingHeight = childActualHeight;
|
|
|
|
|
|
|
|
// remember we do not need to clear the resized list because changing the height of a horizontal box
|
|
|
|
// will not affect the width of any of its children because block flow left to right, top to bottom. Just trust me
|
|
|
|
// on this one.
|
|
|
|
aFinished = PR_FALSE;
|
|
|
|
|
|
|
|
// only recompute if there are flexes.
|
|
|
|
if (aFlexes > 0) {
|
|
|
|
// relayout everything
|
|
|
|
recompute = PR_TRUE;
|
|
|
|
InvalidateComputedSizes(aComputedBoxSizes);
|
|
|
|
nsComputedBoxSize* node = aComputedBoxSizes;
|
|
|
|
|
|
|
|
while(node) {
|
|
|
|
node->resized = PR_FALSE;
|
|
|
|
node = node->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (childActualWidth > childLayoutWidth) {
|
|
|
|
nsSize max(0,0);
|
|
|
|
aChild->GetMaxSize(aState, max);
|
2000-04-05 23:46:48 +00:00
|
|
|
AddMargin(aChild, max);
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
// our width now becomes the new size
|
|
|
|
|
|
|
|
if (isHorizontal)
|
|
|
|
childActualWidth = max.width < childActualWidth ? max.width : childActualWidth;
|
|
|
|
else
|
|
|
|
childActualWidth = max.height < childActualWidth ? max.height : childActualWidth;
|
|
|
|
|
|
|
|
if (childActualWidth > childLayoutWidth) {
|
|
|
|
aChildComputedSize->size = childActualWidth;
|
|
|
|
aChildBoxSize->min = childActualWidth;
|
|
|
|
if (aChildBoxSize->pref < childActualWidth)
|
|
|
|
aChildBoxSize->pref = childActualWidth;
|
|
|
|
|
|
|
|
// if we have flexible elements with us then reflex things. Otherwise we can skip doing it.
|
|
|
|
if (aFlexes > 0) {
|
|
|
|
InvalidateComputedSizes(aComputedBoxSizes);
|
|
|
|
|
|
|
|
nsComputedBoxSize* node = aComputedBoxSizes;
|
|
|
|
aChildComputedSize->resized = PR_TRUE;
|
|
|
|
|
|
|
|
while(node) {
|
|
|
|
if (node->resized)
|
|
|
|
node->valid = PR_TRUE;
|
|
|
|
|
|
|
|
node = node->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
recompute = PR_TRUE;
|
|
|
|
aFinished = PR_FALSE;
|
|
|
|
} else {
|
|
|
|
containingWidth += aChildComputedSize->size - childLayoutWidth;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (recompute)
|
2000-04-03 03:55:38 +00:00
|
|
|
ComputeChildSizes(aBox, aState, containingWidth, aBoxSizes, aComputedBoxSizes);
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
if (childCurrentRect != aChildActualRect) {
|
2000-04-26 07:28:19 +00:00
|
|
|
// the childRect includes the margin
|
|
|
|
// make sure we remove it before setting
|
|
|
|
// the bounds.
|
|
|
|
nsMargin margin(0,0,0,0);
|
|
|
|
aChild->GetMargin(margin);
|
|
|
|
nsRect rect(aChildActualRect);
|
2000-05-16 20:46:08 +00:00
|
|
|
if (rect.width >= margin.left + margin.right && rect.height >= margin.top + margin.bottom)
|
|
|
|
rect.Deflate(margin);
|
|
|
|
|
2000-04-26 07:28:19 +00:00
|
|
|
aChild->SetBounds(aState, rect);
|
2000-03-31 07:02:06 +00:00
|
|
|
aChild->Layout(aState);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSprocketLayout::InvalidateComputedSizes(nsComputedBoxSize* aComputedBoxSizes)
|
|
|
|
{
|
|
|
|
while(aComputedBoxSizes) {
|
|
|
|
aComputedBoxSizes->valid = PR_FALSE;
|
|
|
|
aComputedBoxSizes = aComputedBoxSizes->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-04-03 03:55:38 +00:00
|
|
|
nsSprocketLayout::ComputeChildSizes(nsIBox* aBox,
|
|
|
|
nsBoxLayoutState& aState,
|
2000-03-31 07:02:06 +00:00
|
|
|
nscoord& aGivenSize,
|
|
|
|
nsBoxSize* aBoxSizes,
|
2000-04-05 06:41:27 +00:00
|
|
|
nsComputedBoxSize*& aComputedBoxSizes)
|
2000-03-31 07:02:06 +00:00
|
|
|
{
|
2000-05-22 23:23:04 +00:00
|
|
|
|
2000-06-02 22:15:09 +00:00
|
|
|
// float p2t;
|
|
|
|
// aState.GetPresContext()->GetScaledPixelsToTwips(&p2t);
|
|
|
|
//nscoord onePixel = NSIntPixelsToTwips(1, p2t);
|
2000-05-22 23:23:04 +00:00
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
PRInt32 sizeRemaining = aGivenSize;
|
|
|
|
PRInt32 springConstantsRemaining = 0;
|
|
|
|
|
|
|
|
// ----- calculate the springs constants and the size remaining -----
|
|
|
|
|
2000-05-15 04:12:31 +00:00
|
|
|
if (!aComputedBoxSizes)
|
2000-04-05 23:46:48 +00:00
|
|
|
aComputedBoxSizes = new (aState) nsComputedBoxSize();
|
2000-04-05 06:41:27 +00:00
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
nsBoxSize* boxSizes = aBoxSizes;
|
|
|
|
nsComputedBoxSize* computedBoxSizes = aComputedBoxSizes;
|
|
|
|
PRInt32 count = 0;
|
|
|
|
PRInt32 validCount = 0;
|
|
|
|
|
2000-05-15 04:12:31 +00:00
|
|
|
while (boxSizes)
|
2000-03-31 07:02:06 +00:00
|
|
|
{
|
2000-04-05 06:41:27 +00:00
|
|
|
|
2000-05-15 04:12:31 +00:00
|
|
|
NS_ASSERTION((boxSizes->min <= boxSizes->pref && boxSizes->pref <= boxSizes->max),"bad pref, min, max size");
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-05-16 20:46:08 +00:00
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
// ignore collapsed children
|
2000-05-16 20:46:08 +00:00
|
|
|
// if (boxSizes->collapsed)
|
|
|
|
// {
|
|
|
|
// computedBoxSizes->valid = PR_TRUE;
|
|
|
|
// computedBoxSizes->size = boxSizes->pref;
|
|
|
|
// validCount++;
|
|
|
|
// boxSizes->flex = 0;
|
|
|
|
// }// else {
|
|
|
|
|
2000-05-15 04:12:31 +00:00
|
|
|
if (computedBoxSizes->valid) {
|
2000-03-31 07:02:06 +00:00
|
|
|
sizeRemaining -= computedBoxSizes->size;
|
|
|
|
validCount++;
|
|
|
|
} else {
|
2000-05-15 04:12:31 +00:00
|
|
|
if (boxSizes->flex == 0)
|
|
|
|
{
|
|
|
|
computedBoxSizes->valid = PR_TRUE;
|
|
|
|
computedBoxSizes->size = boxSizes->pref;
|
|
|
|
validCount++;
|
|
|
|
}
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-05-15 04:12:31 +00:00
|
|
|
springConstantsRemaining += boxSizes->flex;
|
|
|
|
sizeRemaining -= boxSizes->pref;
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
2000-06-02 22:15:09 +00:00
|
|
|
|
|
|
|
sizeRemaining -= (boxSizes->left + boxSizes->right);
|
|
|
|
|
2000-05-16 20:46:08 +00:00
|
|
|
//}
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-04-05 06:41:27 +00:00
|
|
|
boxSizes = boxSizes->next;
|
|
|
|
|
2000-06-02 22:15:09 +00:00
|
|
|
if (boxSizes && !computedBoxSizes->next)
|
2000-04-05 23:46:48 +00:00
|
|
|
computedBoxSizes->next = new (aState) nsComputedBoxSize();
|
2000-04-05 06:41:27 +00:00
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
computedBoxSizes = computedBoxSizes->next;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// everything accounted for?
|
|
|
|
if (validCount < count)
|
|
|
|
{
|
|
|
|
// ----- Ok we are give a size to fit into so stretch or squeeze to fit
|
|
|
|
// ----- Make sure we look at our min and max size
|
|
|
|
PRBool limit = PR_TRUE;
|
|
|
|
for (int pass=1; PR_TRUE == limit; pass++)
|
|
|
|
{
|
|
|
|
limit = PR_FALSE;
|
|
|
|
boxSizes = aBoxSizes;
|
|
|
|
computedBoxSizes = aComputedBoxSizes;
|
|
|
|
|
2000-05-15 04:12:31 +00:00
|
|
|
while (boxSizes) {
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
// ignore collapsed springs
|
|
|
|
|
2000-05-16 20:46:08 +00:00
|
|
|
// if (!boxSizes->collapsed) {
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
nscoord pref = 0;
|
|
|
|
nscoord max = NS_INTRINSICSIZE;
|
|
|
|
nscoord min = 0;
|
|
|
|
nscoord flex = 0;
|
|
|
|
|
2000-05-15 04:12:31 +00:00
|
|
|
pref = boxSizes->pref;
|
|
|
|
min = boxSizes->min;
|
|
|
|
max = boxSizes->max;
|
|
|
|
flex = boxSizes->flex;
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
// ----- look at our min and max limits make sure we aren't too small or too big -----
|
2000-05-15 04:12:31 +00:00
|
|
|
if (!computedBoxSizes->valid) {
|
2000-06-02 22:15:09 +00:00
|
|
|
PRInt32 newSize = pref + sizeRemaining*flex/springConstantsRemaining; //NSToCoordRound(float((sizeRemaining*flex)/springConstantsRemaining));
|
2000-05-22 23:23:04 +00:00
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
if (newSize<=min) {
|
2000-05-15 04:12:31 +00:00
|
|
|
computedBoxSizes->size = min;
|
|
|
|
computedBoxSizes->valid = PR_TRUE;
|
2000-03-31 07:02:06 +00:00
|
|
|
springConstantsRemaining -= flex;
|
|
|
|
sizeRemaining += pref;
|
|
|
|
sizeRemaining -= min;
|
|
|
|
limit = PR_TRUE;
|
|
|
|
} else if (newSize>=max) {
|
2000-05-15 04:12:31 +00:00
|
|
|
computedBoxSizes->size = max;
|
|
|
|
computedBoxSizes->valid = PR_TRUE;
|
2000-03-31 07:02:06 +00:00
|
|
|
springConstantsRemaining -= flex;
|
|
|
|
sizeRemaining += pref;
|
|
|
|
sizeRemaining -= max;
|
|
|
|
limit = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
2000-05-16 20:46:08 +00:00
|
|
|
// }
|
2000-03-31 07:02:06 +00:00
|
|
|
boxSizes = boxSizes->next;
|
|
|
|
computedBoxSizes = computedBoxSizes->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---- once we have removed and min and max issues just stretch us out in the remaining space
|
|
|
|
// ---- or shrink us. Depends on the size remaining and the spring constants
|
2000-06-02 22:15:09 +00:00
|
|
|
nscoord oldsize = aGivenSize;
|
2000-03-31 07:02:06 +00:00
|
|
|
aGivenSize = 0;
|
|
|
|
boxSizes = aBoxSizes;
|
|
|
|
computedBoxSizes = aComputedBoxSizes;
|
|
|
|
|
2000-05-15 04:12:31 +00:00
|
|
|
while (boxSizes) {
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
// ignore collapsed springs
|
2000-05-16 20:46:08 +00:00
|
|
|
// if (!(boxSizes && boxSizes->collapsed)) {
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
nscoord pref = 0;
|
|
|
|
nscoord flex = 0;
|
2000-05-15 04:12:31 +00:00
|
|
|
pref = boxSizes->pref;
|
|
|
|
flex = boxSizes->flex;
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-05-15 04:12:31 +00:00
|
|
|
if (!computedBoxSizes->valid) {
|
2000-06-02 22:15:09 +00:00
|
|
|
computedBoxSizes->size = pref + flex*sizeRemaining/springConstantsRemaining; //NSToCoordFloor(float((flex*sizeRemaining)/springConstantsRemaining));
|
2000-05-15 04:12:31 +00:00
|
|
|
computedBoxSizes->valid = PR_TRUE;
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
2000-05-15 04:12:31 +00:00
|
|
|
|
2000-06-02 22:15:09 +00:00
|
|
|
aGivenSize += (boxSizes->left + boxSizes->right);
|
2000-05-15 04:12:31 +00:00
|
|
|
aGivenSize += computedBoxSizes->size;
|
2000-06-02 22:15:09 +00:00
|
|
|
|
2000-05-16 20:46:08 +00:00
|
|
|
// }
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
boxSizes = boxSizes->next;
|
|
|
|
computedBoxSizes = computedBoxSizes->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsSprocketLayout::GetPrefSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSize)
|
|
|
|
{
|
2000-06-23 05:15:04 +00:00
|
|
|
PRBool isHorizontal = IsHorizontal(aBox);
|
|
|
|
|
|
|
|
nscoord biggestPref = 0;
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
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);
|
2000-06-23 05:15:04 +00:00
|
|
|
|
|
|
|
nsFrameState frameState = 0;
|
|
|
|
GetFrameState(aBox, frameState);
|
|
|
|
PRBool isEqual = frameState & NS_STATE_EQUAL_SIZE;
|
|
|
|
PRInt32 count = 0;
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
while (child)
|
|
|
|
{
|
|
|
|
// ignore collapsed children
|
2000-06-23 05:15:04 +00:00
|
|
|
PRBool isCollapsed = PR_FALSE;
|
|
|
|
child->IsCollapsed(aState, isCollapsed);
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-06-23 05:15:04 +00:00
|
|
|
if (!isCollapsed)
|
|
|
|
{
|
2000-03-31 07:02:06 +00:00
|
|
|
nsSize pref(0,0);
|
|
|
|
child->GetPrefSize(aState, pref);
|
|
|
|
AddMargin(child, pref);
|
2000-06-23 05:15:04 +00:00
|
|
|
|
|
|
|
if (isEqual) {
|
|
|
|
if (isHorizontal)
|
|
|
|
{
|
|
|
|
if (pref.width > biggestPref)
|
|
|
|
biggestPref = pref.width;
|
|
|
|
} else {
|
|
|
|
if (pref.height > biggestPref)
|
|
|
|
biggestPref = pref.height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
AddLargestSize(aSize, pref, isHorizontal);
|
2000-06-23 05:15:04 +00:00
|
|
|
count++;
|
|
|
|
}
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
child->GetNextBox(&child);
|
|
|
|
}
|
|
|
|
|
2000-06-23 05:15:04 +00:00
|
|
|
if (isEqual) {
|
|
|
|
if (isHorizontal)
|
|
|
|
aSize.width = biggestPref*count;
|
|
|
|
else
|
|
|
|
aSize.height = biggestPref*count;
|
|
|
|
}
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
// now add our border and padding and insets
|
|
|
|
AddBorderAndPadding(aBox, aSize);
|
|
|
|
AddInset(aBox, aSize);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsSprocketLayout::GetMinSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSize)
|
|
|
|
{
|
2000-06-23 05:15:04 +00:00
|
|
|
PRBool isHorizontal = IsHorizontal(aBox);
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-06-23 05:15:04 +00:00
|
|
|
nscoord biggestMin = 0;
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
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);
|
2000-06-23 05:15:04 +00:00
|
|
|
nsFrameState frameState = 0;
|
|
|
|
GetFrameState(aBox, frameState);
|
|
|
|
PRBool isEqual = frameState & NS_STATE_EQUAL_SIZE;
|
|
|
|
PRInt32 count = 0;
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
while (child)
|
|
|
|
{
|
|
|
|
// ignore collapsed children
|
2000-06-23 05:15:04 +00:00
|
|
|
PRBool isCollapsed = PR_FALSE;
|
|
|
|
aBox->IsCollapsed(aState, isCollapsed);
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-06-23 05:15:04 +00:00
|
|
|
if (!isCollapsed)
|
|
|
|
{
|
2000-03-31 07:02:06 +00:00
|
|
|
nsSize min(0,0);
|
|
|
|
nsSize pref(0,0);
|
|
|
|
nscoord flex = 0;
|
|
|
|
|
|
|
|
child->GetMinSize(aState, min);
|
|
|
|
child->GetFlex(aState, flex);
|
|
|
|
|
|
|
|
// if the child is not flexible then
|
|
|
|
// its min size is its pref size.
|
|
|
|
if (flex == 0) {
|
|
|
|
child->GetPrefSize(aState, pref);
|
|
|
|
if (isHorizontal)
|
|
|
|
min.width = pref.width;
|
|
|
|
else
|
|
|
|
min.height = pref.height;
|
|
|
|
}
|
|
|
|
|
2000-06-23 05:15:04 +00:00
|
|
|
if (isEqual) {
|
|
|
|
if (isHorizontal)
|
|
|
|
{
|
|
|
|
if (min.width > biggestMin)
|
|
|
|
biggestMin = min.width;
|
|
|
|
} else {
|
|
|
|
if (min.height > biggestMin)
|
|
|
|
biggestMin = min.height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
AddMargin(child, min);
|
|
|
|
AddLargestSize(aSize, min, isHorizontal);
|
2000-06-23 05:15:04 +00:00
|
|
|
count++;
|
|
|
|
}
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
child->GetNextBox(&child);
|
|
|
|
}
|
|
|
|
|
2000-06-23 05:15:04 +00:00
|
|
|
|
|
|
|
if (isEqual) {
|
|
|
|
if (isHorizontal)
|
|
|
|
aSize.width = biggestMin*count;
|
|
|
|
else
|
|
|
|
aSize.height = biggestMin*count;
|
|
|
|
}
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
// now add our border and padding and insets
|
|
|
|
AddBorderAndPadding(aBox, aSize);
|
|
|
|
AddInset(aBox,aSize);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsSprocketLayout::GetMaxSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSize)
|
|
|
|
{
|
|
|
|
|
|
|
|
PRBool isHorizontal = IsHorizontal(aBox);
|
|
|
|
|
2000-06-23 05:15:04 +00:00
|
|
|
nscoord smallestMax = NS_INTRINSICSIZE;
|
2000-03-31 07:02:06 +00:00
|
|
|
|
|
|
|
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);
|
2000-06-23 05:15:04 +00:00
|
|
|
nsFrameState frameState = 0;
|
|
|
|
GetFrameState(aBox, frameState);
|
|
|
|
PRBool isEqual = frameState & NS_STATE_EQUAL_SIZE;
|
|
|
|
PRInt32 count = 0;
|
|
|
|
|
2000-03-31 07:02:06 +00:00
|
|
|
while (child)
|
|
|
|
{
|
|
|
|
// ignore collapsed children
|
2000-06-23 05:15:04 +00:00
|
|
|
PRBool isCollapsed = PR_FALSE;
|
|
|
|
aBox->IsCollapsed(aState, isCollapsed);
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-06-23 05:15:04 +00:00
|
|
|
if (!isCollapsed)
|
|
|
|
{
|
2000-03-31 07:02:06 +00:00
|
|
|
// 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);
|
|
|
|
AddSmallestSize(aSize, max, isHorizontal);
|
|
|
|
|
2000-06-23 05:15:04 +00:00
|
|
|
if (isEqual) {
|
|
|
|
if (isHorizontal)
|
|
|
|
{
|
|
|
|
if (max.width < smallestMax)
|
|
|
|
smallestMax = max.width;
|
|
|
|
} else {
|
|
|
|
if (max.height < smallestMax)
|
|
|
|
smallestMax = max.height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
child->GetNextBox(&child);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isEqual) {
|
|
|
|
if (isHorizontal) {
|
|
|
|
if (smallestMax != NS_INTRINSICSIZE)
|
|
|
|
aSize.width = smallestMax*count;
|
|
|
|
else
|
|
|
|
aSize.width = NS_INTRINSICSIZE;
|
|
|
|
} else {
|
|
|
|
if (smallestMax != NS_INTRINSICSIZE)
|
|
|
|
aSize.height = smallestMax*count;
|
|
|
|
else
|
|
|
|
aSize.height = NS_INTRINSICSIZE;
|
|
|
|
}
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// now add our border and padding and insets
|
|
|
|
AddBorderAndPadding(aBox, aSize);
|
|
|
|
AddInset(aBox, aSize);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsSprocketLayout::GetAscent(nsIBox* aBox, nsBoxLayoutState& aState, nscoord& aAscent)
|
|
|
|
{
|
|
|
|
|
|
|
|
PRBool isHorizontal = IsHorizontal(aBox);
|
|
|
|
|
|
|
|
aAscent = 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)
|
|
|
|
{
|
|
|
|
// ignore collapsed children
|
2000-05-16 20:46:08 +00:00
|
|
|
//PRBool isCollapsed = PR_FALSE;
|
|
|
|
//aBox->IsCollapsed(aState, isCollapsed);
|
2000-03-31 07:02:06 +00:00
|
|
|
|
2000-05-16 20:46:08 +00:00
|
|
|
//if (!isCollapsed)
|
|
|
|
//{
|
2000-03-31 07:02:06 +00:00
|
|
|
// if completely redefined don't even ask our child for its size.
|
|
|
|
nscoord ascent = 0;
|
|
|
|
child->GetAscent(aState, ascent);
|
|
|
|
|
|
|
|
nsMargin margin;
|
|
|
|
child->GetMargin(margin);
|
|
|
|
ascent += margin.top + margin.bottom;
|
|
|
|
|
|
|
|
if (isHorizontal)
|
|
|
|
{
|
|
|
|
if (ascent > aAscent)
|
|
|
|
aAscent = ascent;
|
|
|
|
} else {
|
|
|
|
if (aAscent == 0)
|
|
|
|
aAscent = ascent;
|
|
|
|
}
|
2000-05-16 20:46:08 +00:00
|
|
|
//}
|
2000-03-31 07:02:06 +00:00
|
|
|
child->GetNextBox(&child);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsSprocketLayout::GetFlex(nsIBox* aBox, nsBoxLayoutState& aState, nscoord& aFlex)
|
|
|
|
{
|
|
|
|
return aBox->GetFlex(aState, aFlex);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2000-04-26 04:00:29 +00:00
|
|
|
nsSprocketLayout::IsCollapsed(nsIBox* aBox, nsBoxLayoutState& aState, PRBool& aIsCollapsed)
|
2000-03-31 07:02:06 +00:00
|
|
|
{
|
2000-04-26 04:00:29 +00:00
|
|
|
return aBox->IsCollapsed(aState, aIsCollapsed);
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSprocketLayout::SetLargestSize(nsSize& aSize1, const nsSize& aSize2, PRBool aIsHorizontal)
|
|
|
|
{
|
|
|
|
if (aIsHorizontal)
|
|
|
|
{
|
|
|
|
if (aSize1.height < aSize2.height)
|
|
|
|
aSize1.height = aSize2.height;
|
|
|
|
} else {
|
|
|
|
if (aSize1.width < aSize2.width)
|
|
|
|
aSize1.width = aSize2.width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSprocketLayout::SetSmallestSize(nsSize& aSize1, const nsSize& aSize2, PRBool aIsHorizontal)
|
|
|
|
{
|
|
|
|
if (aIsHorizontal)
|
|
|
|
{
|
|
|
|
if (aSize1.height > aSize2.height)
|
|
|
|
aSize1.height = aSize2.height;
|
|
|
|
} else {
|
|
|
|
if (aSize1.width > aSize2.width)
|
|
|
|
aSize1.width = aSize2.width;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSprocketLayout::AddLargestSize(nsSize& aSize, const nsSize& aSizeToAdd, PRBool aIsHorizontal)
|
|
|
|
{
|
|
|
|
if (aIsHorizontal)
|
|
|
|
AddCoord(aSize.width, aSizeToAdd.width);
|
|
|
|
else
|
|
|
|
AddCoord(aSize.height, aSizeToAdd.height);
|
|
|
|
|
|
|
|
SetLargestSize(aSize, aSizeToAdd, aIsHorizontal);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsSprocketLayout::AddCoord(nscoord& aCoord, nscoord aCoordToAdd)
|
|
|
|
{
|
|
|
|
if (aCoord != NS_INTRINSICSIZE)
|
|
|
|
{
|
|
|
|
if (aCoordToAdd == NS_INTRINSICSIZE)
|
|
|
|
aCoord = aCoordToAdd;
|
|
|
|
else
|
|
|
|
aCoord += aCoordToAdd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
|
|
nsSprocketLayout::AddSmallestSize(nsSize& aSize, const nsSize& aSizeToAdd, PRBool aIsHorizontal)
|
|
|
|
{
|
|
|
|
if (aIsHorizontal)
|
|
|
|
AddCoord(aSize.width, aSizeToAdd.width);
|
|
|
|
else
|
|
|
|
AddCoord(aSize.height, aSizeToAdd.height);
|
|
|
|
|
|
|
|
SetSmallestSize(aSize, aSizeToAdd, aIsHorizontal);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsSprocketLayout::GetDefaultFlex(PRInt32& aFlex)
|
|
|
|
{
|
|
|
|
aFlex = 0;
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-04-05 08:20:24 +00:00
|
|
|
nsBoxSize::Add(const nsSize& minSize,
|
|
|
|
const nsSize& prefSize,
|
|
|
|
const nsSize& maxSize,
|
|
|
|
nscoord aAscent,
|
|
|
|
nscoord aFlex,
|
2000-03-31 07:02:06 +00:00
|
|
|
PRBool aIsHorizontal)
|
|
|
|
{
|
|
|
|
nscoord pref2;
|
|
|
|
nscoord min2;
|
|
|
|
nscoord max2;
|
|
|
|
|
|
|
|
if (aIsHorizontal) {
|
|
|
|
pref2 = prefSize.width;
|
|
|
|
min2 = minSize.width;
|
|
|
|
max2 = maxSize.width;
|
|
|
|
} else {
|
|
|
|
pref2 = prefSize.height;
|
|
|
|
min2 = minSize.height;
|
|
|
|
max2 = maxSize.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (min2 > min)
|
|
|
|
min = min2;
|
|
|
|
|
|
|
|
if (pref2 > pref)
|
|
|
|
pref = pref2;
|
|
|
|
|
|
|
|
if (max2 < max)
|
|
|
|
max = max2;
|
2000-04-05 08:20:24 +00:00
|
|
|
|
|
|
|
flex = aFlex;
|
2000-04-05 23:46:48 +00:00
|
|
|
|
|
|
|
if (!aIsHorizontal) {
|
|
|
|
if (aAscent > ascent)
|
|
|
|
ascent = aAscent;
|
|
|
|
}
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsBoxSize::Add(const nsMargin& aMargin, PRBool aIsHorizontal)
|
|
|
|
{
|
|
|
|
if (aIsHorizontal) {
|
|
|
|
left += aMargin.left;
|
|
|
|
right += aMargin.right;
|
2000-06-02 22:15:09 +00:00
|
|
|
pref -= (aMargin.left + aMargin.right);
|
2000-03-31 07:02:06 +00:00
|
|
|
} else {
|
|
|
|
left += aMargin.top;
|
|
|
|
right += aMargin.bottom;
|
2000-06-02 22:15:09 +00:00
|
|
|
pref -= (aMargin.top + aMargin.bottom);
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
2000-06-02 22:15:09 +00:00
|
|
|
|
|
|
|
if (pref < min)
|
|
|
|
min = pref;
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsComputedBoxSize::nsComputedBoxSize()
|
2000-04-03 03:55:38 +00:00
|
|
|
{
|
|
|
|
Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsComputedBoxSize::Clear()
|
2000-03-31 07:02:06 +00:00
|
|
|
{
|
|
|
|
resized = PR_FALSE;
|
|
|
|
valid = PR_FALSE;
|
|
|
|
size = 0;
|
|
|
|
next = nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsBoxSize::nsBoxSize()
|
2000-04-03 03:55:38 +00:00
|
|
|
{
|
|
|
|
Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsBoxSize::Clear()
|
2000-03-31 07:02:06 +00:00
|
|
|
{
|
|
|
|
pref = 0;
|
|
|
|
min = 0;
|
|
|
|
max = NS_INTRINSICSIZE;
|
2000-06-23 05:15:04 +00:00
|
|
|
collapsed = PR_FALSE;
|
2000-03-31 07:02:06 +00:00
|
|
|
ascent = 0;
|
|
|
|
left = 0;
|
|
|
|
right = 0;
|
|
|
|
flex = 0;
|
|
|
|
next = nsnull;
|
2000-04-11 23:55:15 +00:00
|
|
|
bogus = PR_FALSE;
|
2000-03-31 07:02:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void*
|
2000-04-05 23:46:48 +00:00
|
|
|
nsBoxSize::operator new(size_t sz, nsBoxLayoutState& aState)
|
2000-03-31 07:02:06 +00:00
|
|
|
{
|
|
|
|
void* mem = 0;
|
|
|
|
aState.AllocateStackMemory(sz,&mem);
|
|
|
|
return mem;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2000-04-05 23:46:48 +00:00
|
|
|
nsBoxSize::operator delete(void* aPtr, size_t sz)
|
2000-03-31 07:02:06 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void*
|
2000-04-05 23:46:48 +00:00
|
|
|
nsComputedBoxSize::operator new(size_t sz, nsBoxLayoutState& aState)
|
2000-03-31 07:02:06 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
void* mem = 0;
|
|
|
|
aState.AllocateStackMemory(sz,&mem);
|
|
|
|
return mem;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-04-05 23:46:48 +00:00
|
|
|
nsComputedBoxSize::operator delete(void* aPtr, size_t sz)
|
2000-03-31 07:02:06 +00:00
|
|
|
{
|
|
|
|
}
|