/* -*- 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 "nsTempleLayout.h" #include "nsIBox.h" #include "nsCOMPtr.h" #include "nsIScrollableFrame.h" nsresult NS_NewTempleLayout( nsIPresShell* aPresShell, nsCOMPtr& aNewLayout) { aNewLayout = new nsTempleLayout(aPresShell); return NS_OK; } nsTempleLayout::nsTempleLayout(nsIPresShell* aPresShell):nsMonumentLayout(aPresShell), mMonuments(nsnull) { } NS_IMETHODIMP nsTempleLayout::CastToTemple(nsTempleLayout** aTemple) { *aTemple = this; return NS_OK; } NS_IMETHODIMP nsTempleLayout::EnscriptionChanged(nsBoxLayoutState& aState, PRInt32 aIndex) { // if a cell changes size. if (mMonuments) { nsBoxSizeList* size = mMonuments->GetAt(aIndex); if (size) size->Desecrate(aState); } return NS_OK; } NS_IMETHODIMP nsTempleLayout::GetMonumentList(nsIBox* aBox, nsBoxLayoutState& aState, nsBoxSizeList** aList) { if (mMonuments) { *aList = mMonuments; return NS_OK; } // run through our children. // ask each child for its monument list // append the list to our list nsIBox* firstChild = nsnull; aBox->GetChildBox(&firstChild); nsBoxSizeList* current = nsnull; nsCOMPtr monument; nsMonumentIterator it(firstChild); nsIBox* box = nsnull; while(it.GetNextMonument(getter_AddRefs(monument))) { it.GetBox(&box); current = mMonuments; nsBoxSizeList* node = nsnull; monument->GetMonumentList(box, aState, &node); while(node) { if (!mMonuments) { mMonuments = new nsBoxSizeListImpl(firstChild); current = mMonuments; } current->Append(aState, node); node = node->GetAdjacent(); if (node && !current->GetAdjacent()) { nsBoxSizeList* newOne = new nsBoxSizeListImpl(box); current->SetAdjacent(aState, newOne); current = newOne; } else { current = current->GetAdjacent(); } } } *aList = mMonuments; return NS_OK; } NS_IMETHODIMP nsTempleLayout::BuildBoxSizeList(nsIBox* aBox, nsBoxLayoutState& aState, nsBoxSize*& aFirst, nsBoxSize*& aLast, PRBool aIsHorizontal) { // ok we need to build a nsBoxSize for each obelisk in this temple. We will then return the list of them. // We are just returning a flattened list that we will use to layout our each cell. nsIBox* box = nsnull; aBox->GetChildBox(&box); aFirst = nsnull; aLast = nsnull; nsBoxSize* first; nsBoxSize* last; PRInt32 count = 0; nsCOMPtr layout; nsLayoutIterator it(box); while(it.GetNextLayout(getter_AddRefs(layout))) { it.GetBox(&box); if (layout) { nsresult rv = NS_OK; nsCOMPtr monument = do_QueryInterface(layout, &rv); if (monument) monument->BuildBoxSizeList(box, aState, first, last, aIsHorizontal); else { nsMonumentLayout::BuildBoxSizeList(box, aState, first, last, aIsHorizontal); first->bogus = PR_TRUE; } if (count == 0) aFirst = first; else if (aLast) (aLast)->next = first; aLast = last; } count++; } // ok now we might have a margin or border. If we do then we need to take that into account. One example // might be if we are oriented vertically making us a "columns" and we contain a horizontal obelisk "row". // Now say we have a left border of 10px. Well if we just layed things out then the whole row would be pushed over and // the columns would not not line up. So we must take the space from somewhere. So if its on the left we take from the first // child (which is leftmost) and if its on the right we take from the last child (which is rightmost). So for our example we // need to subtract 10px from the first child. // so get the border and padding and add them up. nsMargin borderPadding(0,0,0,0); aBox->GetBorderAndPadding(borderPadding); nsMargin margin(0,0,0,0); aBox->GetMargin(margin); // add the margins up nsMargin leftMargin(borderPadding.left + margin.left, borderPadding.top + margin.top, 0, 0); nsMargin rightMargin(0,0, borderPadding.right + margin.right, borderPadding.bottom + margin.bottom); // Subtract them out. PRBool isHorizontal = PR_FALSE; aBox->GetOrientation(isHorizontal); if (aFirst) aFirst->Add(leftMargin,isHorizontal); if (aLast) aLast->Add(rightMargin,isHorizontal); return NS_OK; } NS_IMETHODIMP nsTempleLayout::ChildrenInserted(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aPrevBox, nsIBox* aChildList) { DesecrateMonuments(aBox, aState); return NS_OK; } NS_IMETHODIMP nsTempleLayout::ChildrenAppended(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList) { DesecrateMonuments(aBox, aState); return NS_OK; } NS_IMETHODIMP nsTempleLayout::ChildrenRemoved(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList) { DesecrateMonuments(aBox, aState); return NS_OK; } NS_IMETHODIMP nsTempleLayout::DesecrateMonuments(nsIBox* aBox, nsBoxLayoutState& aState) { nsCOMPtr parent; nsCOMPtr parentBox; GetParentMonument(aBox, parentBox, getter_AddRefs(parent)); if (parent) parent->DesecrateMonuments(parentBox, aState); if (mMonuments) { nsBoxSizeList* tmp = mMonuments; mMonuments->Release(aState); mMonuments = nsnull; } return NS_OK; } // redefined because the normal GetMinSize in sprocket looks at flex // if the child is not flexible then its min size is its pref size. // but in this case its up to the column. The column's flex is the // flex thats used. NS_IMETHODIMP nsTempleLayout::GetMinSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSize) { return nsSprocketLayout::GetMinSize(aBox, aState, aSize); }