Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/xul/grid/nsGridRowLeafLayout.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
//
8
// Eric Vaughan
9
// Netscape Communications
10
//
11
// See documentation in associated header file
12
//
13
14
#include "nsGridRowLeafLayout.h"
15
#include "nsGridRowGroupLayout.h"
16
#include "nsGridRow.h"
17
#include "nsBoxLayoutState.h"
18
#include "nsBox.h"
19
#include "nsIScrollableFrame.h"
20
#include "nsBoxFrame.h"
21
#include "nsGridLayout2.h"
22
#include <algorithm>
23
24
already_AddRefed<nsBoxLayout> NS_NewGridRowLeafLayout()
25
0
{
26
0
  RefPtr<nsBoxLayout> layout = new nsGridRowLeafLayout();
27
0
  return layout.forget();
28
0
}
29
30
nsGridRowLeafLayout::nsGridRowLeafLayout():nsGridRowLayout()
31
0
{
32
0
}
33
34
nsGridRowLeafLayout::~nsGridRowLeafLayout()
35
{
36
}
37
38
nsSize
39
nsGridRowLeafLayout::GetXULPrefSize(nsIFrame* aBox, nsBoxLayoutState& aState)
40
0
{
41
0
  int32_t index = 0;
42
0
  nsGrid* grid = GetGrid(aBox, &index);
43
0
  bool isHorizontal = IsXULHorizontal(aBox);
44
0
45
0
  // If we are not in a grid. Then we just work like a box. But if we are in a grid
46
0
  // ask the grid for our size.
47
0
  if (!grid) {
48
0
    return nsGridRowLayout::GetXULPrefSize(aBox, aState);
49
0
  }
50
0
  else {
51
0
    return grid->GetPrefRowSize(aState, index, isHorizontal);
52
0
    //AddBorderAndPadding(aBox, pref);
53
0
  }
54
0
}
55
56
nsSize
57
nsGridRowLeafLayout::GetXULMinSize(nsIFrame* aBox, nsBoxLayoutState& aState)
58
0
{
59
0
  int32_t index = 0;
60
0
  nsGrid* grid = GetGrid(aBox, &index);
61
0
  bool isHorizontal = IsXULHorizontal(aBox);
62
0
63
0
  if (!grid)
64
0
    return nsGridRowLayout::GetXULMinSize(aBox, aState);
65
0
  else {
66
0
    nsSize minSize = grid->GetMinRowSize(aState, index, isHorizontal);
67
0
    AddBorderAndPadding(aBox, minSize);
68
0
    return minSize;
69
0
  }
70
0
}
71
72
nsSize
73
nsGridRowLeafLayout::GetXULMaxSize(nsIFrame* aBox, nsBoxLayoutState& aState)
74
0
{
75
0
  int32_t index = 0;
76
0
  nsGrid* grid = GetGrid(aBox, &index);
77
0
  bool isHorizontal = IsXULHorizontal(aBox);
78
0
79
0
  if (!grid)
80
0
    return nsGridRowLayout::GetXULMaxSize(aBox, aState);
81
0
  else {
82
0
    nsSize maxSize;
83
0
    maxSize = grid->GetMaxRowSize(aState, index, isHorizontal);
84
0
    AddBorderAndPadding(aBox, maxSize);
85
0
    return maxSize;
86
0
  }
87
0
}
88
89
/** If a child is added or removed or changes size
90
  */
91
void
92
nsGridRowLeafLayout::ChildAddedOrRemoved(nsIFrame* aBox, nsBoxLayoutState& aState)
93
0
{
94
0
  int32_t index = 0;
95
0
  nsGrid* grid = GetGrid(aBox, &index);
96
0
  bool isHorizontal = IsXULHorizontal(aBox);
97
0
98
0
  if (grid)
99
0
    grid->CellAddedOrRemoved(aState, index, isHorizontal);
100
0
}
101
102
void
103
nsGridRowLeafLayout::PopulateBoxSizes(nsIFrame* aBox, nsBoxLayoutState& aState, nsBoxSize*& aBoxSizes, nscoord& aMinSize, nscoord& aMaxSize, int32_t& aFlexes)
104
0
{
105
0
  int32_t index = 0;
106
0
  nsGrid* grid = GetGrid(aBox, &index);
107
0
  bool isHorizontal = IsXULHorizontal(aBox);
108
0
109
0
  // Our base class SprocketLayout is giving us a chance to change the box sizes before layout
110
0
  // If we are a row lets change the sizes to match our columns. If we are a column then do the opposite
111
0
  // and make them match or rows.
112
0
  if (grid) {
113
0
    nsGridRow* column;
114
0
    int32_t count = grid->GetColumnCount(isHorizontal);
115
0
    nsBoxSize* start = nullptr;
116
0
    nsBoxSize* last = nullptr;
117
0
    nsBoxSize* current = nullptr;
118
0
    nsIFrame* child = nsBox::GetChildXULBox(aBox);
119
0
    for (int i=0; i < count; i++)
120
0
    {
121
0
      column = grid->GetColumnAt(i,isHorizontal);
122
0
123
0
      // make sure the value was computed before we use it.
124
0
      // !isHorizontal is passed in to invert the behavior of these methods.
125
0
      nscoord pref =
126
0
        grid->GetPrefRowHeight(aState, i, !isHorizontal); // GetPrefColumnWidth
127
0
      nscoord min =
128
0
        grid->GetMinRowHeight(aState, i, !isHorizontal);  // GetMinColumnWidth
129
0
      nscoord max =
130
0
        grid->GetMaxRowHeight(aState, i, !isHorizontal);  // GetMaxColumnWidth
131
0
      nscoord flex = grid->GetRowFlex(i, !isHorizontal);  // GetColumnFlex
132
0
      nscoord left  = 0;
133
0
      nscoord right  = 0;
134
0
      grid->GetRowOffsets(i, left, right, !isHorizontal); // GetColumnOffsets
135
0
      nsIFrame* box = column->GetBox();
136
0
      bool collapsed = false;
137
0
      nscoord topMargin = column->mTopMargin;
138
0
      nscoord bottomMargin = column->mBottomMargin;
139
0
140
0
      if (box)
141
0
        collapsed = box->IsXULCollapsed();
142
0
143
0
      pref = pref - (left + right);
144
0
      if (pref < 0)
145
0
        pref = 0;
146
0
147
0
      // if this is the first or last column. Take into account that
148
0
      // our row could have a border that could affect our left or right
149
0
      // padding from our columns. If the row has padding subtract it.
150
0
      // would should always be able to garentee that our margin is smaller
151
0
      // or equal to our left or right
152
0
      int32_t firstIndex = 0;
153
0
      int32_t lastIndex = 0;
154
0
      nsGridRow* firstRow = nullptr;
155
0
      nsGridRow* lastRow = nullptr;
156
0
      grid->GetFirstAndLastRow(firstIndex, lastIndex, firstRow, lastRow, !isHorizontal);
157
0
158
0
      if (i == firstIndex || i == lastIndex) {
159
0
        nsMargin offset = GetTotalMargin(aBox, isHorizontal);
160
0
161
0
        nsMargin border(0,0,0,0);
162
0
        // can't call GetBorderPadding we will get into recursion
163
0
        aBox->GetXULBorder(border);
164
0
        offset += border;
165
0
        aBox->GetXULPadding(border);
166
0
        offset += border;
167
0
168
0
        // subtract from out left and right
169
0
        if (i == firstIndex)
170
0
        {
171
0
          if (isHorizontal)
172
0
           left -= offset.left;
173
0
          else
174
0
           left -= offset.top;
175
0
        }
176
0
177
0
        if (i == lastIndex)
178
0
        {
179
0
          if (isHorizontal)
180
0
           right -= offset.right;
181
0
          else
182
0
           right -= offset.bottom;
183
0
        }
184
0
      }
185
0
186
0
      // initialize the box size here
187
0
      max = std::max(min, max);
188
0
      pref = nsBox::BoundsCheck(min, pref, max);
189
0
190
0
      current = new (aState) nsBoxSize();
191
0
      current->pref = pref;
192
0
      current->min = min;
193
0
      current->max = max;
194
0
      current->flex = flex;
195
0
      current->bogus = column->mIsBogus;
196
0
      current->left = left + topMargin;
197
0
      current->right = right + bottomMargin;
198
0
      current->collapsed = collapsed;
199
0
200
0
      if (!start) {
201
0
        start = current;
202
0
        last = start;
203
0
      } else {
204
0
        last->next = current;
205
0
        last = current;
206
0
      }
207
0
208
0
      if (child && !column->mIsBogus)
209
0
        child = nsBox::GetNextXULBox(child);
210
0
211
0
    }
212
0
    aBoxSizes = start;
213
0
  }
214
0
215
0
  nsSprocketLayout::PopulateBoxSizes(aBox, aState, aBoxSizes, aMinSize, aMaxSize, aFlexes);
216
0
}
217
218
void
219
nsGridRowLeafLayout::ComputeChildSizes(nsIFrame* aBox,
220
                           nsBoxLayoutState& aState,
221
                           nscoord& aGivenSize,
222
                           nsBoxSize* aBoxSizes,
223
                           nsComputedBoxSize*& aComputedBoxSizes)
224
0
{
225
0
  // see if we are in a scrollable frame. If we are then there could be scrollbars present
226
0
  // if so we need to subtract them out to make sure our columns line up.
227
0
  if (aBox) {
228
0
    bool isHorizontal = aBox->IsXULHorizontal();
229
0
230
0
    // go up the parent chain looking for scrollframes
231
0
    nscoord diff = 0;
232
0
    nsIFrame* parentBox;
233
0
    (void)GetParentGridPart(aBox, &parentBox);
234
0
    while (parentBox) {
235
0
      nsIFrame* scrollbox = nsGrid::GetScrollBox(parentBox);
236
0
      nsIScrollableFrame *scrollable = do_QueryFrame(scrollbox);
237
0
      if (scrollable) {
238
0
        // Don't call GetActualScrollbarSizes here because it's not safe
239
0
        // to call that while we're reflowing the contents of the scrollframe,
240
0
        // which we are here.
241
0
        nsMargin scrollbarSizes = scrollable->GetDesiredScrollbarSizes(&aState);
242
0
        uint32_t visible = scrollable->GetScrollbarVisibility();
243
0
244
0
        if (isHorizontal && (visible & nsIScrollableFrame::VERTICAL)) {
245
0
          diff += scrollbarSizes.left + scrollbarSizes.right;
246
0
        } else if (!isHorizontal && (visible & nsIScrollableFrame::HORIZONTAL)) {
247
0
          diff += scrollbarSizes.top + scrollbarSizes.bottom;
248
0
        }
249
0
      }
250
0
251
0
      (void)GetParentGridPart(parentBox, &parentBox);
252
0
    }
253
0
254
0
    if (diff > 0) {
255
0
      aGivenSize += diff;
256
0
257
0
      nsSprocketLayout::ComputeChildSizes(aBox, aState, aGivenSize, aBoxSizes, aComputedBoxSizes);
258
0
259
0
      aGivenSize -= diff;
260
0
261
0
      nsComputedBoxSize* s    = aComputedBoxSizes;
262
0
      nsComputedBoxSize* last = aComputedBoxSizes;
263
0
      while(s)
264
0
      {
265
0
        last = s;
266
0
        s = s->next;
267
0
      }
268
0
269
0
      if (last)
270
0
        last->size -= diff;
271
0
272
0
      return;
273
0
    }
274
0
  }
275
0
276
0
  nsSprocketLayout::ComputeChildSizes(aBox, aState, aGivenSize, aBoxSizes, aComputedBoxSizes);
277
0
278
0
}
279
280
NS_IMETHODIMP
281
nsGridRowLeafLayout::XULLayout(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState)
282
0
{
283
0
  return nsGridRowLayout::XULLayout(aBox, aBoxLayoutState);
284
0
}
285
286
void
287
nsGridRowLeafLayout::DirtyRows(nsIFrame* aBox, nsBoxLayoutState& aState)
288
0
{
289
0
  if (aBox) {
290
0
    // mark us dirty
291
0
    // XXXldb We probably don't want to walk up the ancestor chain
292
0
    // calling MarkIntrinsicISizesDirty for every row.
293
0
    aState.PresShell()->FrameNeedsReflow(aBox, nsIPresShell::eTreeChange,
294
0
                                         NS_FRAME_IS_DIRTY);
295
0
  }
296
0
}
297
298
void
299
nsGridRowLeafLayout::CountRowsColumns(nsIFrame* aBox, int32_t& aRowCount, int32_t& aComputedColumnCount)
300
0
{
301
0
  if (aBox) {
302
0
    nsIFrame* child = nsBox::GetChildXULBox(aBox);
303
0
304
0
    // count the children
305
0
    int32_t columnCount = 0;
306
0
    while(child) {
307
0
      child = nsBox::GetNextXULBox(child);
308
0
      columnCount++;
309
0
    }
310
0
311
0
    // if our count is greater than the current column count
312
0
    if (columnCount > aComputedColumnCount)
313
0
      aComputedColumnCount = columnCount;
314
0
315
0
    aRowCount++;
316
0
  }
317
0
}
318
319
int32_t
320
nsGridRowLeafLayout::BuildRows(nsIFrame* aBox, nsGridRow* aRows)
321
0
{
322
0
  if (aBox) {
323
0
      aRows[0].Init(aBox, false);
324
0
      return 1;
325
0
  }
326
0
327
0
  return 0;
328
0
}
329