michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: // michael@0: // Eric Vaughan michael@0: // Netscape Communications michael@0: // michael@0: // See documentation in associated header file michael@0: // michael@0: michael@0: #include "nsGridRowLayout.h" michael@0: #include "nsBoxLayoutState.h" michael@0: #include "nsIScrollableFrame.h" michael@0: #include "nsBox.h" michael@0: #include "nsStackLayout.h" michael@0: #include "nsGrid.h" michael@0: michael@0: nsGridRowLayout::nsGridRowLayout():nsSprocketLayout() michael@0: { michael@0: } michael@0: michael@0: void michael@0: nsGridRowLayout::ChildrenInserted(nsIFrame* aBox, nsBoxLayoutState& aState, michael@0: nsIFrame* aPrevBox, michael@0: const nsFrameList::Slice& aNewChildren) michael@0: { michael@0: ChildAddedOrRemoved(aBox, aState); michael@0: } michael@0: michael@0: void michael@0: nsGridRowLayout::ChildrenAppended(nsIFrame* aBox, nsBoxLayoutState& aState, michael@0: const nsFrameList::Slice& aNewChildren) michael@0: { michael@0: ChildAddedOrRemoved(aBox, aState); michael@0: } michael@0: michael@0: void michael@0: nsGridRowLayout::ChildrenRemoved(nsIFrame* aBox, nsBoxLayoutState& aState, nsIFrame* aChildList) michael@0: { michael@0: ChildAddedOrRemoved(aBox, aState); michael@0: } michael@0: michael@0: void michael@0: nsGridRowLayout::ChildrenSet(nsIFrame* aBox, nsBoxLayoutState& aState, nsIFrame* aChildList) michael@0: { michael@0: ChildAddedOrRemoved(aBox, aState); michael@0: } michael@0: michael@0: nsIGridPart* michael@0: nsGridRowLayout::GetParentGridPart(nsIFrame* aBox, nsIFrame** aParentBox) michael@0: { michael@0: // go up and find our parent gridRow. Skip and non gridRow michael@0: // parents. michael@0: *aParentBox = nullptr; michael@0: michael@0: // walk up through any scrollboxes michael@0: aBox = nsGrid::GetScrollBox(aBox); michael@0: michael@0: // get the parent michael@0: if (aBox) michael@0: aBox = aBox->GetParentBox(); michael@0: michael@0: if (aBox) michael@0: { michael@0: nsIGridPart* parentGridRow = nsGrid::GetPartFromBox(aBox); michael@0: if (parentGridRow && parentGridRow->CanContain(this)) { michael@0: *aParentBox = aBox; michael@0: return parentGridRow; michael@0: } michael@0: } michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: michael@0: nsGrid* michael@0: nsGridRowLayout::GetGrid(nsIFrame* aBox, int32_t* aIndex, nsGridRowLayout* aRequestor) michael@0: { michael@0: michael@0: if (aRequestor == nullptr) michael@0: { michael@0: nsIFrame* parentBox; // nsIFrame is implemented by nsIFrame and is not refcounted. michael@0: nsIGridPart* parent = GetParentGridPart(aBox, &parentBox); michael@0: if (parent) michael@0: return parent->GetGrid(parentBox, aIndex, this); michael@0: return nullptr; michael@0: } michael@0: michael@0: int32_t index = -1; michael@0: nsIFrame* child = aBox->GetChildBox(); michael@0: int32_t count = 0; michael@0: while(child) michael@0: { michael@0: // if there is a scrollframe walk inside it to its child michael@0: nsIFrame* childBox = nsGrid::GetScrolledBox(child); michael@0: michael@0: nsBoxLayout* layout = childBox->GetLayoutManager(); michael@0: nsIGridPart* gridRow = nsGrid::GetPartFromBox(childBox); michael@0: if (gridRow) michael@0: { michael@0: if (layout == aRequestor) { michael@0: index = count; michael@0: break; michael@0: } michael@0: count += gridRow->GetRowCount(); michael@0: } else michael@0: count++; michael@0: michael@0: child = child->GetNextBox(); michael@0: } michael@0: michael@0: // if we didn't find ourselves then the tree isn't properly formed yet michael@0: // this could happen during initial construction so lets just michael@0: // fail. michael@0: if (index == -1) { michael@0: *aIndex = -1; michael@0: return nullptr; michael@0: } michael@0: michael@0: (*aIndex) += index; michael@0: michael@0: nsIFrame* parentBox; // nsIFrame is implemented by nsIFrame and is not refcounted. michael@0: nsIGridPart* parent = GetParentGridPart(aBox, &parentBox); michael@0: if (parent) michael@0: return parent->GetGrid(parentBox, aIndex, this); michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: nsMargin michael@0: nsGridRowLayout::GetTotalMargin(nsIFrame* aBox, bool aIsHorizontal) michael@0: { michael@0: // get our parents margin michael@0: nsMargin margin(0,0,0,0); michael@0: nsIFrame* parent = nullptr; michael@0: nsIGridPart* part = GetParentGridPart(aBox, &parent); michael@0: if (part && parent) { michael@0: // if we are the first or last child walk upward and add margins. michael@0: michael@0: // make sure we check for a scrollbox michael@0: aBox = nsGrid::GetScrollBox(aBox); michael@0: michael@0: // see if we have a next to see if we are last michael@0: nsIFrame* next = aBox->GetNextBox(); michael@0: michael@0: // get the parent first child to see if we are first michael@0: nsIFrame* child = parent->GetChildBox(); michael@0: michael@0: margin = part->GetTotalMargin(parent, aIsHorizontal); michael@0: michael@0: // if first or last michael@0: if (child == aBox || next == nullptr) { michael@0: michael@0: // if it's not the first child remove the top margin michael@0: // we don't need it. michael@0: if (child != aBox) michael@0: { michael@0: if (aIsHorizontal) michael@0: margin.top = 0; michael@0: else michael@0: margin.left = 0; michael@0: } michael@0: michael@0: // if it's not the last child remove the bottom margin michael@0: // we don't need it. michael@0: if (next != nullptr) michael@0: { michael@0: if (aIsHorizontal) michael@0: margin.bottom = 0; michael@0: else michael@0: margin.right = 0; michael@0: } michael@0: michael@0: } michael@0: } michael@0: michael@0: // add ours to it. michael@0: nsMargin ourMargin; michael@0: aBox->GetMargin(ourMargin); michael@0: margin += ourMargin; michael@0: michael@0: return margin; michael@0: } michael@0: michael@0: NS_IMPL_ADDREF_INHERITED(nsGridRowLayout, nsBoxLayout) michael@0: NS_IMPL_RELEASE_INHERITED(nsGridRowLayout, nsBoxLayout) michael@0: michael@0: NS_INTERFACE_MAP_BEGIN(nsGridRowLayout) michael@0: NS_INTERFACE_MAP_ENTRY(nsIGridPart) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIGridPart) michael@0: NS_INTERFACE_MAP_END_INHERITING(nsBoxLayout)