layout/xul/grid/nsGridRowLeafLayout.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/xul/grid/nsGridRowLeafLayout.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,329 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +//
    1.10 +// Eric Vaughan
    1.11 +// Netscape Communications
    1.12 +//
    1.13 +// See documentation in associated header file
    1.14 +//
    1.15 +
    1.16 +#include "nsGridRowLeafLayout.h"
    1.17 +#include "nsGridRowGroupLayout.h"
    1.18 +#include "nsGridRow.h"
    1.19 +#include "nsBoxLayoutState.h"
    1.20 +#include "nsBox.h"
    1.21 +#include "nsIScrollableFrame.h"
    1.22 +#include "nsBoxFrame.h"
    1.23 +#include "nsGridLayout2.h"
    1.24 +#include <algorithm>
    1.25 +
    1.26 +already_AddRefed<nsBoxLayout> NS_NewGridRowLeafLayout()
    1.27 +{
    1.28 +  nsRefPtr<nsBoxLayout> layout = new nsGridRowLeafLayout();
    1.29 +  return layout.forget();
    1.30 +} 
    1.31 +
    1.32 +nsGridRowLeafLayout::nsGridRowLeafLayout():nsGridRowLayout()
    1.33 +{
    1.34 +}
    1.35 +
    1.36 +nsGridRowLeafLayout::~nsGridRowLeafLayout()
    1.37 +{
    1.38 +}
    1.39 +
    1.40 +nsSize
    1.41 +nsGridRowLeafLayout::GetPrefSize(nsIFrame* aBox, nsBoxLayoutState& aState)
    1.42 +{
    1.43 +  int32_t index = 0;
    1.44 +  nsGrid* grid = GetGrid(aBox, &index);
    1.45 +  bool isHorizontal = IsHorizontal(aBox);
    1.46 +
    1.47 +  // If we are not in a grid. Then we just work like a box. But if we are in a grid
    1.48 +  // ask the grid for our size.
    1.49 +  if (!grid) {
    1.50 +    return nsGridRowLayout::GetPrefSize(aBox, aState); 
    1.51 +  }
    1.52 +  else {
    1.53 +    return grid->GetPrefRowSize(aState, index, isHorizontal);
    1.54 +    //AddBorderAndPadding(aBox, pref);
    1.55 +  }
    1.56 +}
    1.57 +
    1.58 +nsSize
    1.59 +nsGridRowLeafLayout::GetMinSize(nsIFrame* aBox, nsBoxLayoutState& aState)
    1.60 +{
    1.61 +  int32_t index = 0;
    1.62 +  nsGrid* grid = GetGrid(aBox, &index);
    1.63 +  bool isHorizontal = IsHorizontal(aBox);
    1.64 +
    1.65 +  if (!grid)
    1.66 +    return nsGridRowLayout::GetMinSize(aBox, aState); 
    1.67 +  else {
    1.68 +    nsSize minSize = grid->GetMinRowSize(aState, index, isHorizontal);
    1.69 +    AddBorderAndPadding(aBox, minSize);
    1.70 +    return minSize;
    1.71 +  }
    1.72 +}
    1.73 +
    1.74 +nsSize
    1.75 +nsGridRowLeafLayout::GetMaxSize(nsIFrame* aBox, nsBoxLayoutState& aState)
    1.76 +{
    1.77 +  int32_t index = 0;
    1.78 +  nsGrid* grid = GetGrid(aBox, &index);
    1.79 +  bool isHorizontal = IsHorizontal(aBox);
    1.80 +
    1.81 +  if (!grid)
    1.82 +    return nsGridRowLayout::GetMaxSize(aBox, aState); 
    1.83 +  else {
    1.84 +    nsSize maxSize;
    1.85 +    maxSize = grid->GetMaxRowSize(aState, index, isHorizontal);
    1.86 +    AddBorderAndPadding(aBox, maxSize);
    1.87 +    return maxSize;
    1.88 +  }
    1.89 +}
    1.90 +
    1.91 +/** If a child is added or removed or changes size
    1.92 +  */
    1.93 +void
    1.94 +nsGridRowLeafLayout::ChildAddedOrRemoved(nsIFrame* aBox, nsBoxLayoutState& aState)
    1.95 +{
    1.96 +  int32_t index = 0;
    1.97 +  nsGrid* grid = GetGrid(aBox, &index);
    1.98 +  bool isHorizontal = IsHorizontal(aBox);
    1.99 +
   1.100 +  if (grid)
   1.101 +    grid->CellAddedOrRemoved(aState, index, isHorizontal);
   1.102 +}
   1.103 +
   1.104 +void
   1.105 +nsGridRowLeafLayout::PopulateBoxSizes(nsIFrame* aBox, nsBoxLayoutState& aState, nsBoxSize*& aBoxSizes, nscoord& aMinSize, nscoord& aMaxSize, int32_t& aFlexes)
   1.106 +{
   1.107 +  int32_t index = 0;
   1.108 +  nsGrid* grid = GetGrid(aBox, &index);
   1.109 +  bool isHorizontal = IsHorizontal(aBox);
   1.110 +
   1.111 +  // Our base class SprocketLayout is giving us a chance to change the box sizes before layout
   1.112 +  // If we are a row lets change the sizes to match our columns. If we are a column then do the opposite
   1.113 +  // and make them match or rows.
   1.114 +  if (grid) {
   1.115 +    nsGridRow* column;
   1.116 +    int32_t count = grid->GetColumnCount(isHorizontal); 
   1.117 +    nsBoxSize* start = nullptr;
   1.118 +    nsBoxSize* last = nullptr;
   1.119 +    nsBoxSize* current = nullptr;
   1.120 +    nsIFrame* child = aBox->GetChildBox();
   1.121 +    for (int i=0; i < count; i++)
   1.122 +    {
   1.123 +      column = grid->GetColumnAt(i,isHorizontal); 
   1.124 +
   1.125 +      // make sure the value was computed before we use it.
   1.126 +      // !isHorizontal is passed in to invert the behavior of these methods.
   1.127 +      nscoord pref =
   1.128 +        grid->GetPrefRowHeight(aState, i, !isHorizontal); // GetPrefColumnWidth
   1.129 +      nscoord min = 
   1.130 +        grid->GetMinRowHeight(aState, i, !isHorizontal);  // GetMinColumnWidth
   1.131 +      nscoord max = 
   1.132 +        grid->GetMaxRowHeight(aState, i, !isHorizontal);  // GetMaxColumnWidth
   1.133 +      nscoord flex =
   1.134 +        grid->GetRowFlex(aState, i, !isHorizontal);       // GetColumnFlex
   1.135 +      nscoord left  = 0;
   1.136 +      nscoord right  = 0;
   1.137 +      grid->GetRowOffsets(aState, i, left, right, !isHorizontal); // GetColumnOffsets
   1.138 +      nsIFrame* box = column->GetBox();
   1.139 +      bool collapsed = false;
   1.140 +      nscoord topMargin = column->mTopMargin;
   1.141 +      nscoord bottomMargin = column->mBottomMargin;
   1.142 +
   1.143 +      if (box) 
   1.144 +        collapsed = box->IsCollapsed();
   1.145 +
   1.146 +      pref = pref - (left + right);
   1.147 +      if (pref < 0)
   1.148 +        pref = 0;
   1.149 +
   1.150 +      // if this is the first or last column. Take into account that
   1.151 +      // our row could have a border that could affect our left or right
   1.152 +      // padding from our columns. If the row has padding subtract it.
   1.153 +      // would should always be able to garentee that our margin is smaller
   1.154 +      // or equal to our left or right
   1.155 +      int32_t firstIndex = 0;
   1.156 +      int32_t lastIndex = 0;
   1.157 +      nsGridRow* firstRow = nullptr;
   1.158 +      nsGridRow* lastRow = nullptr;
   1.159 +      grid->GetFirstAndLastRow(aState, firstIndex, lastIndex, firstRow, lastRow, !isHorizontal);
   1.160 +
   1.161 +      if (i == firstIndex || i == lastIndex) {
   1.162 +        nsMargin offset = GetTotalMargin(aBox, isHorizontal);
   1.163 +
   1.164 +        nsMargin border(0,0,0,0);
   1.165 +        // can't call GetBorderPadding we will get into recursion
   1.166 +        aBox->GetBorder(border);
   1.167 +        offset += border;
   1.168 +        aBox->GetPadding(border);
   1.169 +        offset += border;
   1.170 +
   1.171 +        // subtract from out left and right
   1.172 +        if (i == firstIndex) 
   1.173 +        {
   1.174 +          if (isHorizontal)
   1.175 +           left -= offset.left;
   1.176 +          else
   1.177 +           left -= offset.top;
   1.178 +        }
   1.179 +
   1.180 +        if (i == lastIndex)
   1.181 +        {
   1.182 +          if (isHorizontal)
   1.183 +           right -= offset.right;
   1.184 +          else
   1.185 +           right -= offset.bottom;
   1.186 +        }
   1.187 +      }
   1.188 +    
   1.189 +      // initialize the box size here 
   1.190 +      max = std::max(min, max);
   1.191 +      pref = nsBox::BoundsCheck(min, pref, max);
   1.192 +   
   1.193 +      current = new (aState) nsBoxSize();
   1.194 +      current->pref = pref;
   1.195 +      current->min = min;
   1.196 +      current->max = max;
   1.197 +      current->flex = flex;
   1.198 +      current->bogus = column->mIsBogus;
   1.199 +      current->left = left + topMargin;
   1.200 +      current->right = right + bottomMargin;
   1.201 +      current->collapsed = collapsed;
   1.202 +
   1.203 +      if (!start) {
   1.204 +        start = current;
   1.205 +        last = start;
   1.206 +      } else {
   1.207 +        last->next = current;
   1.208 +        last = current;
   1.209 +      }
   1.210 +
   1.211 +      if (child && !column->mIsBogus)
   1.212 +        child = child->GetNextBox();
   1.213 +
   1.214 +    }
   1.215 +    aBoxSizes = start;
   1.216 +  }
   1.217 +
   1.218 +  nsSprocketLayout::PopulateBoxSizes(aBox, aState, aBoxSizes, aMinSize, aMaxSize, aFlexes);
   1.219 +}
   1.220 +
   1.221 +void
   1.222 +nsGridRowLeafLayout::ComputeChildSizes(nsIFrame* aBox,
   1.223 +                           nsBoxLayoutState& aState, 
   1.224 +                           nscoord& aGivenSize, 
   1.225 +                           nsBoxSize* aBoxSizes, 
   1.226 +                           nsComputedBoxSize*& aComputedBoxSizes)
   1.227 +{ 
   1.228 +  // see if we are in a scrollable frame. If we are then there could be scrollbars present
   1.229 +  // if so we need to subtract them out to make sure our columns line up.
   1.230 +  if (aBox) {
   1.231 +    bool isHorizontal = aBox->IsHorizontal();
   1.232 +
   1.233 +    // go up the parent chain looking for scrollframes
   1.234 +    nscoord diff = 0;
   1.235 +    nsIFrame* parentBox;
   1.236 +    (void)GetParentGridPart(aBox, &parentBox);
   1.237 +    while (parentBox) {
   1.238 +      nsIFrame* scrollbox = nsGrid::GetScrollBox(parentBox);
   1.239 +      nsIScrollableFrame *scrollable = do_QueryFrame(scrollbox);
   1.240 +      if (scrollable) {
   1.241 +        // Don't call GetActualScrollbarSizes here because it's not safe
   1.242 +        // to call that while we're reflowing the contents of the scrollframe,
   1.243 +        // which we are here.
   1.244 +        nsMargin scrollbarSizes = scrollable->GetDesiredScrollbarSizes(&aState);
   1.245 +        uint32_t visible = scrollable->GetScrollbarVisibility();
   1.246 +
   1.247 +        if (isHorizontal && (visible & nsIScrollableFrame::VERTICAL)) {
   1.248 +          diff += scrollbarSizes.left + scrollbarSizes.right;
   1.249 +        } else if (!isHorizontal && (visible & nsIScrollableFrame::HORIZONTAL)) {
   1.250 +          diff += scrollbarSizes.top + scrollbarSizes.bottom;
   1.251 +        }
   1.252 +      }
   1.253 +
   1.254 +      (void)GetParentGridPart(parentBox, &parentBox);
   1.255 +    }
   1.256 +
   1.257 +    if (diff > 0) {
   1.258 +      aGivenSize += diff;
   1.259 +
   1.260 +      nsSprocketLayout::ComputeChildSizes(aBox, aState, aGivenSize, aBoxSizes, aComputedBoxSizes);
   1.261 +
   1.262 +      aGivenSize -= diff;
   1.263 +
   1.264 +      nsComputedBoxSize* s    = aComputedBoxSizes;
   1.265 +      nsComputedBoxSize* last = aComputedBoxSizes;
   1.266 +      while(s)
   1.267 +      {
   1.268 +        last = s;
   1.269 +        s = s->next;
   1.270 +      }
   1.271 +  
   1.272 +      if (last) 
   1.273 +        last->size -= diff;                         
   1.274 +
   1.275 +      return;
   1.276 +    }
   1.277 +  }
   1.278 +      
   1.279 +  nsSprocketLayout::ComputeChildSizes(aBox, aState, aGivenSize, aBoxSizes, aComputedBoxSizes);
   1.280 +
   1.281 +}
   1.282 +
   1.283 +NS_IMETHODIMP
   1.284 +nsGridRowLeafLayout::Layout(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState)
   1.285 +{
   1.286 +  return nsGridRowLayout::Layout(aBox, aBoxLayoutState);
   1.287 +}
   1.288 +
   1.289 +void
   1.290 +nsGridRowLeafLayout::DirtyRows(nsIFrame* aBox, nsBoxLayoutState& aState)
   1.291 +{
   1.292 +  if (aBox) {
   1.293 +    // mark us dirty
   1.294 +    // XXXldb We probably don't want to walk up the ancestor chain
   1.295 +    // calling MarkIntrinsicWidthsDirty for every row.
   1.296 +    aState.PresShell()->FrameNeedsReflow(aBox, nsIPresShell::eTreeChange,
   1.297 +                                         NS_FRAME_IS_DIRTY);
   1.298 +  }
   1.299 +}
   1.300 +
   1.301 +void
   1.302 +nsGridRowLeafLayout::CountRowsColumns(nsIFrame* aBox, int32_t& aRowCount, int32_t& aComputedColumnCount)
   1.303 +{
   1.304 +  if (aBox) {
   1.305 +    nsIFrame* child = aBox->GetChildBox();
   1.306 +
   1.307 +    // count the children
   1.308 +    int32_t columnCount = 0;
   1.309 +    while(child) {
   1.310 +      child = child->GetNextBox();
   1.311 +      columnCount++;
   1.312 +    }
   1.313 +
   1.314 +    // if our count is greater than the current column count
   1.315 +    if (columnCount > aComputedColumnCount) 
   1.316 +      aComputedColumnCount = columnCount;
   1.317 +
   1.318 +    aRowCount++;
   1.319 +  }
   1.320 +}
   1.321 +
   1.322 +int32_t
   1.323 +nsGridRowLeafLayout::BuildRows(nsIFrame* aBox, nsGridRow* aRows)
   1.324 +{
   1.325 +  if (aBox) {
   1.326 +      aRows[0].Init(aBox, false);
   1.327 +      return 1;
   1.328 +  }
   1.329 +
   1.330 +  return 0;
   1.331 +}
   1.332 +

mercurial