diff options
Diffstat (limited to 'layout/xul/grid/nsGridRowLeafLayout.cpp')
-rw-r--r-- | layout/xul/grid/nsGridRowLeafLayout.cpp | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/layout/xul/grid/nsGridRowLeafLayout.cpp b/layout/xul/grid/nsGridRowLeafLayout.cpp new file mode 100644 index 000000000..2a089af0c --- /dev/null +++ b/layout/xul/grid/nsGridRowLeafLayout.cpp @@ -0,0 +1,328 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// +// Eric Vaughan +// Netscape Communications +// +// See documentation in associated header file +// + +#include "nsGridRowLeafLayout.h" +#include "nsGridRowGroupLayout.h" +#include "nsGridRow.h" +#include "nsBoxLayoutState.h" +#include "nsBox.h" +#include "nsIScrollableFrame.h" +#include "nsBoxFrame.h" +#include "nsGridLayout2.h" +#include <algorithm> + +already_AddRefed<nsBoxLayout> NS_NewGridRowLeafLayout() +{ + RefPtr<nsBoxLayout> layout = new nsGridRowLeafLayout(); + return layout.forget(); +} + +nsGridRowLeafLayout::nsGridRowLeafLayout():nsGridRowLayout() +{ +} + +nsGridRowLeafLayout::~nsGridRowLeafLayout() +{ +} + +nsSize +nsGridRowLeafLayout::GetXULPrefSize(nsIFrame* aBox, nsBoxLayoutState& aState) +{ + int32_t index = 0; + nsGrid* grid = GetGrid(aBox, &index); + bool isHorizontal = IsXULHorizontal(aBox); + + // If we are not in a grid. Then we just work like a box. But if we are in a grid + // ask the grid for our size. + if (!grid) { + return nsGridRowLayout::GetXULPrefSize(aBox, aState); + } + else { + return grid->GetPrefRowSize(aState, index, isHorizontal); + //AddBorderAndPadding(aBox, pref); + } +} + +nsSize +nsGridRowLeafLayout::GetXULMinSize(nsIFrame* aBox, nsBoxLayoutState& aState) +{ + int32_t index = 0; + nsGrid* grid = GetGrid(aBox, &index); + bool isHorizontal = IsXULHorizontal(aBox); + + if (!grid) + return nsGridRowLayout::GetXULMinSize(aBox, aState); + else { + nsSize minSize = grid->GetMinRowSize(aState, index, isHorizontal); + AddBorderAndPadding(aBox, minSize); + return minSize; + } +} + +nsSize +nsGridRowLeafLayout::GetXULMaxSize(nsIFrame* aBox, nsBoxLayoutState& aState) +{ + int32_t index = 0; + nsGrid* grid = GetGrid(aBox, &index); + bool isHorizontal = IsXULHorizontal(aBox); + + if (!grid) + return nsGridRowLayout::GetXULMaxSize(aBox, aState); + else { + nsSize maxSize; + maxSize = grid->GetMaxRowSize(aState, index, isHorizontal); + AddBorderAndPadding(aBox, maxSize); + return maxSize; + } +} + +/** If a child is added or removed or changes size + */ +void +nsGridRowLeafLayout::ChildAddedOrRemoved(nsIFrame* aBox, nsBoxLayoutState& aState) +{ + int32_t index = 0; + nsGrid* grid = GetGrid(aBox, &index); + bool isHorizontal = IsXULHorizontal(aBox); + + if (grid) + grid->CellAddedOrRemoved(aState, index, isHorizontal); +} + +void +nsGridRowLeafLayout::PopulateBoxSizes(nsIFrame* aBox, nsBoxLayoutState& aState, nsBoxSize*& aBoxSizes, nscoord& aMinSize, nscoord& aMaxSize, int32_t& aFlexes) +{ + int32_t index = 0; + nsGrid* grid = GetGrid(aBox, &index); + bool isHorizontal = IsXULHorizontal(aBox); + + // Our base class SprocketLayout is giving us a chance to change the box sizes before layout + // If we are a row lets change the sizes to match our columns. If we are a column then do the opposite + // and make them match or rows. + if (grid) { + nsGridRow* column; + int32_t count = grid->GetColumnCount(isHorizontal); + nsBoxSize* start = nullptr; + nsBoxSize* last = nullptr; + nsBoxSize* current = nullptr; + nsIFrame* child = nsBox::GetChildXULBox(aBox); + for (int i=0; i < count; i++) + { + column = grid->GetColumnAt(i,isHorizontal); + + // make sure the value was computed before we use it. + // !isHorizontal is passed in to invert the behavior of these methods. + nscoord pref = + grid->GetPrefRowHeight(aState, i, !isHorizontal); // GetPrefColumnWidth + nscoord min = + grid->GetMinRowHeight(aState, i, !isHorizontal); // GetMinColumnWidth + nscoord max = + grid->GetMaxRowHeight(aState, i, !isHorizontal); // GetMaxColumnWidth + nscoord flex = grid->GetRowFlex(i, !isHorizontal); // GetColumnFlex + nscoord left = 0; + nscoord right = 0; + grid->GetRowOffsets(i, left, right, !isHorizontal); // GetColumnOffsets + nsIFrame* box = column->GetBox(); + bool collapsed = false; + nscoord topMargin = column->mTopMargin; + nscoord bottomMargin = column->mBottomMargin; + + if (box) + collapsed = box->IsXULCollapsed(); + + pref = pref - (left + right); + if (pref < 0) + pref = 0; + + // if this is the first or last column. Take into account that + // our row could have a border that could affect our left or right + // padding from our columns. If the row has padding subtract it. + // would should always be able to garentee that our margin is smaller + // or equal to our left or right + int32_t firstIndex = 0; + int32_t lastIndex = 0; + nsGridRow* firstRow = nullptr; + nsGridRow* lastRow = nullptr; + grid->GetFirstAndLastRow(firstIndex, lastIndex, firstRow, lastRow, !isHorizontal); + + if (i == firstIndex || i == lastIndex) { + nsMargin offset = GetTotalMargin(aBox, isHorizontal); + + nsMargin border(0,0,0,0); + // can't call GetBorderPadding we will get into recursion + aBox->GetXULBorder(border); + offset += border; + aBox->GetXULPadding(border); + offset += border; + + // subtract from out left and right + if (i == firstIndex) + { + if (isHorizontal) + left -= offset.left; + else + left -= offset.top; + } + + if (i == lastIndex) + { + if (isHorizontal) + right -= offset.right; + else + right -= offset.bottom; + } + } + + // initialize the box size here + max = std::max(min, max); + pref = nsBox::BoundsCheck(min, pref, max); + + current = new (aState) nsBoxSize(); + current->pref = pref; + current->min = min; + current->max = max; + current->flex = flex; + current->bogus = column->mIsBogus; + current->left = left + topMargin; + current->right = right + bottomMargin; + current->collapsed = collapsed; + + if (!start) { + start = current; + last = start; + } else { + last->next = current; + last = current; + } + + if (child && !column->mIsBogus) + child = nsBox::GetNextXULBox(child); + + } + aBoxSizes = start; + } + + nsSprocketLayout::PopulateBoxSizes(aBox, aState, aBoxSizes, aMinSize, aMaxSize, aFlexes); +} + +void +nsGridRowLeafLayout::ComputeChildSizes(nsIFrame* aBox, + nsBoxLayoutState& aState, + nscoord& aGivenSize, + nsBoxSize* aBoxSizes, + nsComputedBoxSize*& aComputedBoxSizes) +{ + // see if we are in a scrollable frame. If we are then there could be scrollbars present + // if so we need to subtract them out to make sure our columns line up. + if (aBox) { + bool isHorizontal = aBox->IsXULHorizontal(); + + // go up the parent chain looking for scrollframes + nscoord diff = 0; + nsIFrame* parentBox; + (void)GetParentGridPart(aBox, &parentBox); + while (parentBox) { + nsIFrame* scrollbox = nsGrid::GetScrollBox(parentBox); + nsIScrollableFrame *scrollable = do_QueryFrame(scrollbox); + if (scrollable) { + // Don't call GetActualScrollbarSizes here because it's not safe + // to call that while we're reflowing the contents of the scrollframe, + // which we are here. + nsMargin scrollbarSizes = scrollable->GetDesiredScrollbarSizes(&aState); + uint32_t visible = scrollable->GetScrollbarVisibility(); + + if (isHorizontal && (visible & nsIScrollableFrame::VERTICAL)) { + diff += scrollbarSizes.left + scrollbarSizes.right; + } else if (!isHorizontal && (visible & nsIScrollableFrame::HORIZONTAL)) { + diff += scrollbarSizes.top + scrollbarSizes.bottom; + } + } + + (void)GetParentGridPart(parentBox, &parentBox); + } + + if (diff > 0) { + aGivenSize += diff; + + nsSprocketLayout::ComputeChildSizes(aBox, aState, aGivenSize, aBoxSizes, aComputedBoxSizes); + + aGivenSize -= diff; + + nsComputedBoxSize* s = aComputedBoxSizes; + nsComputedBoxSize* last = aComputedBoxSizes; + while(s) + { + last = s; + s = s->next; + } + + if (last) + last->size -= diff; + + return; + } + } + + nsSprocketLayout::ComputeChildSizes(aBox, aState, aGivenSize, aBoxSizes, aComputedBoxSizes); + +} + +NS_IMETHODIMP +nsGridRowLeafLayout::XULLayout(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) +{ + return nsGridRowLayout::XULLayout(aBox, aBoxLayoutState); +} + +void +nsGridRowLeafLayout::DirtyRows(nsIFrame* aBox, nsBoxLayoutState& aState) +{ + if (aBox) { + // mark us dirty + // XXXldb We probably don't want to walk up the ancestor chain + // calling MarkIntrinsicISizesDirty for every row. + aState.PresShell()->FrameNeedsReflow(aBox, nsIPresShell::eTreeChange, + NS_FRAME_IS_DIRTY); + } +} + +void +nsGridRowLeafLayout::CountRowsColumns(nsIFrame* aBox, int32_t& aRowCount, int32_t& aComputedColumnCount) +{ + if (aBox) { + nsIFrame* child = nsBox::GetChildXULBox(aBox); + + // count the children + int32_t columnCount = 0; + while(child) { + child = nsBox::GetNextXULBox(child); + columnCount++; + } + + // if our count is greater than the current column count + if (columnCount > aComputedColumnCount) + aComputedColumnCount = columnCount; + + aRowCount++; + } +} + +int32_t +nsGridRowLeafLayout::BuildRows(nsIFrame* aBox, nsGridRow* aRows) +{ + if (aBox) { + aRows[0].Init(aBox, false); + return 1; + } + + return 0; +} + |