layout/xul/grid/nsGridRowLeafLayout.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

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

mercurial