123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- /* -*- 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;
- }
|