LMMS
Loading...
Searching...
No Matches
juce_FlexBox.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce
27{
28
30{
31 using Coord = double;
32
33 enum class Axis { main, cross };
34
36 : owner (fb), parentWidth (w), parentHeight (h), numItems (owner.items.size()),
37 isRowDirection (fb.flexDirection == FlexBox::Direction::row
38 || fb.flexDirection == FlexBox::Direction::rowReverse),
40 {
41 lineItems.calloc (numItems * numItems);
42 lineInfo.calloc (numItems);
43 }
44
65
71
74 const int numItems;
75 const bool isRowDirection;
77
78 int numberOfRows = 1;
80
84
85 ItemWithState& getItem (int x, int y) const noexcept { return *lineItems[y * numItems + x]; }
86
87 static bool isAuto (Coord value) noexcept { return value == FlexItem::autoValue; }
88 static bool isAssigned (Coord value) noexcept { return value != FlexItem::notAssigned; }
89 static Coord getValueOrZeroIfAuto (Coord value) noexcept { return isAuto (value) ? Coord() : value; }
90
91 //==============================================================================
92 bool isSingleLine() const { return owner.flexWrap == FlexBox::Wrap::noWrap; }
93
94 template <typename Value>
95 Value& pickForAxis (Axis axis, Value& x, Value& y) const
96 {
97 return (isRowDirection ? axis == Axis::main : axis == Axis::cross) ? x : y;
98 }
99
100 auto& getStartMargin (Axis axis, ItemWithState& item) const
101 {
102 return pickForAxis (axis, item.item->margin.left, item.item->margin.top);
103 }
104
105 auto& getEndMargin (Axis axis, ItemWithState& item) const
106 {
107 return pickForAxis (axis, item.item->margin.right, item.item->margin.bottom);
108 }
109
110 auto& getStartLockedMargin (Axis axis, ItemWithState& item) const
111 {
112 return pickForAxis (axis, item.lockedMarginLeft, item.lockedMarginTop);
113 }
114
115 auto& getEndLockedMargin (Axis axis, ItemWithState& item) const
116 {
117 return pickForAxis (axis, item.lockedMarginRight, item.lockedMarginBottom);
118 }
119
120 auto& getLockedSize (Axis axis, ItemWithState& item) const
121 {
122 return pickForAxis (axis, item.lockedWidth, item.lockedHeight);
123 }
124
125 auto& getPreferredSize (Axis axis, ItemWithState& item) const
126 {
127 return pickForAxis (axis, item.preferredWidth, item.preferredHeight);
128 }
129
131 {
132 return pickForAxis (axis, parentWidth, parentHeight);
133 }
134
135 auto& getItemSize (Axis axis, ItemWithState& item) const
136 {
137 return pickForAxis (axis, item.item->width, item.item->height);
138 }
139
140 auto& getMinSize (Axis axis, ItemWithState& item) const
141 {
142 return pickForAxis (axis, item.item->minWidth, item.item->minHeight);
143 }
144
145 auto& getMaxSize (Axis axis, ItemWithState& item) const
146 {
147 return pickForAxis (axis, item.item->maxWidth, item.item->maxHeight);
148 }
149
150 //==============================================================================
152 {
153 itemStates.ensureStorageAllocated (numItems);
154
155 for (auto& item : owner.items)
156 itemStates.add (item);
157
158 std::stable_sort (itemStates.begin(), itemStates.end(),
159 [] (const ItemWithState& i1, const ItemWithState& i2) { return i1.item->order < i2.item->order; });
160
161 for (auto& item : itemStates)
162 {
163 for (auto& axis : { Axis::main, Axis::cross })
164 getPreferredSize (axis, item) = computePreferredSize (axis, item);
165 }
166 }
167
169 {
170 if (isSingleLine()) // for single-line, all items go in line 1
171 {
172 lineInfo[0].numItems = numItems;
173 int i = 0;
174
175 for (auto& item : itemStates)
176 {
177 item.resetItemLockedSize();
178 lineItems[i++] = &item;
179 }
180 }
181 else // if multi-line, group the flexbox items into multiple lines
182 {
183 auto currentLength = containerLineLength;
184 int column = 0, row = 0;
185 bool firstRow = true;
186
187 for (auto& item : itemStates)
188 {
189 item.resetItemLockedSize();
190
191 const auto flexitemLength = getItemMainSize (item);
192
193 if (flexitemLength > currentLength)
194 {
195 if (! firstRow)
196 row++;
197
198 if (row >= numItems)
199 break;
200
201 column = 0;
202 currentLength = containerLineLength;
204 }
205
206 currentLength -= flexitemLength;
207 lineItems[row * numItems + column] = &item;
208 ++column;
209 lineInfo[row].numItems = jmax (lineInfo[row].numItems, column);
210 firstRow = false;
211 }
212 }
213 }
214
216 {
217 for (int row = 0; row < numberOfRows; ++row)
218 {
220
221 for (int maxLoops = numItems; --maxLoops >= 0;)
222 {
224
225 if (layoutRowItems (row))
226 break;
227 }
228 }
229 }
230
232 {
233 for (int row = 0; row < numberOfRows; ++row)
234 {
235 Coord allFlexGrow = 0;
236 const auto numColumns = lineInfo[row].numItems;
237 const auto remainingLength = containerLineLength - lineInfo[row].totalLength;
238
239 for (int column = 0; column < numColumns; ++column)
240 {
241 auto& item = getItem (column, row);
242
243 if (isAuto (getStartMargin (Axis::main, item))) ++allFlexGrow;
244 if (isAuto (getEndMargin (Axis::main, item))) ++allFlexGrow;
245 }
246
247 const auto changeUnitWidth = remainingLength / allFlexGrow;
248
249 if (changeUnitWidth > 0)
250 {
251 for (int column = 0; column < numColumns; ++column)
252 {
253 auto& item = getItem (column, row);
254
255 if (isAuto (getStartMargin (Axis::main, item)))
256 getStartLockedMargin (Axis::main, item) = changeUnitWidth;
257
258 if (isAuto (getEndMargin (Axis::main, item)))
259 getEndLockedMargin (Axis::main, item) = changeUnitWidth;
260 }
261 }
262 }
263 }
264
266 {
267 // https://www.w3.org/TR/css-flexbox-1/#algo-cross-line
268 // If the flex container is single-line and has a definite cross size, the cross size of the
269 // flex line is the flex container’s inner cross size.
270 if (isSingleLine())
271 {
272 lineInfo[0].crossSize = getContainerSize (Axis::cross);
273 }
274 else
275 {
276 for (int row = 0; row < numberOfRows; ++row)
277 {
278 Coord maxSize = 0;
279 const auto numColumns = lineInfo[row].numItems;
280
281 for (int column = 0; column < numColumns; ++column)
282 maxSize = jmax (maxSize, getItemCrossSize (getItem (column, row)));
283
284 lineInfo[row].crossSize = maxSize;
285 }
286 }
287 }
288
290 {
291 for (int row = 0; row < numberOfRows; ++row)
292 {
293 const auto numColumns = lineInfo[row].numItems;
294
295 for (int column = 0; column < numColumns; ++column)
296 {
297 auto& item = getItem (column, row);
298
299 if (isAssigned (item.item->maxHeight) && item.lockedHeight > item.item->maxHeight)
300 item.lockedHeight = item.item->maxHeight;
301
302 if (isAssigned (item.item->maxWidth) && item.lockedWidth > item.item->maxWidth)
303 item.lockedWidth = item.item->maxWidth;
304 }
305 }
306 }
307
309 {
311
312 if (owner.alignContent == FlexBox::AlignContent::flexStart)
313 {
314 for (int row = 0; row < numberOfRows; ++row)
315 for (int row2 = row; row2 < numberOfRows; ++row2)
316 lineInfo[row].lineY = row == 0 ? 0 : lineInfo[row - 1].lineY + lineInfo[row - 1].crossSize;
317 }
318 else if (owner.alignContent == FlexBox::AlignContent::flexEnd)
319 {
320 for (int row = 0; row < numberOfRows; ++row)
321 {
322 Coord crossHeights = 0;
323
324 for (int row2 = row; row2 < numberOfRows; ++row2)
325 crossHeights += lineInfo[row2].crossSize;
326
327 lineInfo[row].lineY = containerCrossLength - crossHeights;
328 }
329 }
330 else
331 {
332 Coord totalHeight = 0;
333
334 for (int row = 0; row < numberOfRows; ++row)
335 totalHeight += lineInfo[row].crossSize;
336
337 if (owner.alignContent == FlexBox::AlignContent::stretch)
338 {
339 const auto difference = jmax (Coord(), (containerCrossLength - totalHeight) / numberOfRows);
340
341 for (int row = 0; row < numberOfRows; ++row)
342 {
343 lineInfo[row].crossSize += difference;
344 lineInfo[row].lineY = row == 0 ? 0 : lineInfo[row - 1].lineY + lineInfo[row - 1].crossSize;
345 }
346 }
347 else if (owner.alignContent == FlexBox::AlignContent::center)
348 {
349 const auto additionalength = (containerCrossLength - totalHeight) / 2;
350
351 for (int row = 0; row < numberOfRows; ++row)
352 lineInfo[row].lineY = row == 0 ? additionalength : lineInfo[row - 1].lineY + lineInfo[row - 1].crossSize;
353 }
354 else if (owner.alignContent == FlexBox::AlignContent::spaceBetween)
355 {
356 const auto additionalength = numberOfRows <= 1 ? Coord() : jmax (Coord(), (containerCrossLength - totalHeight)
357 / static_cast<Coord> (numberOfRows - 1));
358 lineInfo[0].lineY = 0;
359
360 for (int row = 1; row < numberOfRows; ++row)
361 lineInfo[row].lineY += additionalength + lineInfo[row - 1].lineY + lineInfo[row - 1].crossSize;
362 }
363 else if (owner.alignContent == FlexBox::AlignContent::spaceAround)
364 {
365 const auto additionalength = numberOfRows <= 1 ? Coord() : jmax (Coord(), (containerCrossLength - totalHeight)
366 / static_cast<Coord> (2 + (2 * (numberOfRows - 1))));
367
368 lineInfo[0].lineY = additionalength;
369
370 for (int row = 1; row < numberOfRows; ++row)
371 lineInfo[row].lineY += (2 * additionalength) + lineInfo[row - 1].lineY + lineInfo[row - 1].crossSize;
372 }
373 }
374 }
375
377 {
378 for (int row = 0; row < numberOfRows; ++row)
379 {
380 const auto numColumns = lineInfo[row].numItems;
381 const auto crossSizeForLine = lineInfo[row].crossSize;
382
383 for (int column = 0; column < numColumns; ++column)
384 {
385 auto& item = getItem (column, row);
386
388 {
390 return (crossSizeForLine - getLockedSize (Axis::cross, item)) / 2;
391
392 if (isAuto (getStartMargin (Axis::cross, item)))
393 return crossSizeForLine - getLockedSize (Axis::cross, item) - getEndMargin (Axis::cross, item);
394
395 return getStartLockedMargin (Axis::cross, item);
396 }();
397 }
398 }
399 }
400
401 // Align all flex items along the cross-axis per align-self, if neither of the item’s cross-axis margins are auto.
403 {
404 for (int row = 0; row < numberOfRows; ++row)
405 {
406 const auto numColumns = lineInfo[row].numItems;
407 const auto lineSize = lineInfo[row].crossSize;
408
409 for (int column = 0; column < numColumns; ++column)
410 {
411 auto& item = getItem (column, row);
412
414 continue;
415
416 const auto alignment = [&]
417 {
418 switch (item.item->alignSelf)
419 {
425 }
426
427 return owner.alignItems;
428 }();
429
431 {
432 switch (alignment)
433 {
434 // https://www.w3.org/TR/css-flexbox-1/#valdef-align-items-flex-start
435 // The cross-start margin edge of the flex item is placed flush with the
436 // cross-start edge of the line.
438 return (Coord) getStartMargin (Axis::cross, item);
439
440 // https://www.w3.org/TR/css-flexbox-1/#valdef-align-items-flex-end
441 // The cross-end margin edge of the flex item is placed flush with the cross-end
442 // edge of the line.
444 return lineSize - getLockedSize (Axis::cross, item) - getEndMargin (Axis::cross, item);
445
446 // https://www.w3.org/TR/css-flexbox-1/#valdef-align-items-center
447 // The flex item’s margin box is centered in the cross axis within the line.
449 return getStartMargin (Axis::cross, item) + (lineSize - getLockedSize (Axis::cross, item) - getStartMargin (Axis::cross, item) - getEndMargin (Axis::cross, item)) / 2;
450
451 // https://www.w3.org/TR/css-flexbox-1/#valdef-align-items-stretch
453 return (Coord) getStartMargin (Axis::cross, item);
454 }
455
457 return 0.0;
458 }();
459
460 if (alignment == FlexBox::AlignItems::stretch)
461 {
462 auto newSize = isAssigned (getItemSize (Axis::cross, item)) ? computePreferredSize (Axis::cross, item)
463 : lineSize - getStartMargin (Axis::cross, item) - getEndMargin (Axis::cross, item);
464
465 if (isAssigned (getMaxSize (Axis::cross, item)))
466 newSize = jmin (newSize, (Coord) getMaxSize (Axis::cross, item));
467
468 if (isAssigned (getMinSize (Axis::cross, item)))
469 newSize = jmax (newSize, (Coord) getMinSize (Axis::cross, item));
470
471 getLockedSize (Axis::cross, item) = newSize;
472 }
473 }
474 }
475 }
476
478 {
479 Coord additionalMarginRight = 0, additionalMarginLeft = 0;
480
482
483 for (int row = 0; row < numberOfRows; ++row)
484 {
485 const auto numColumns = lineInfo[row].numItems;
486 Coord x = 0;
487
488 if (owner.justifyContent == FlexBox::JustifyContent::flexEnd)
489 {
490 x = containerLineLength - lineInfo[row].totalLength;
491 }
492 else if (owner.justifyContent == FlexBox::JustifyContent::center)
493 {
494 x = (containerLineLength - lineInfo[row].totalLength) / 2;
495 }
496 else if (owner.justifyContent == FlexBox::JustifyContent::spaceBetween)
497 {
498 additionalMarginRight
499 = jmax (Coord(), (containerLineLength - lineInfo[row].totalLength) / jmax (1, numColumns - 1));
500 }
501 else if (owner.justifyContent == FlexBox::JustifyContent::spaceAround)
502 {
503 additionalMarginLeft = additionalMarginRight
504 = jmax (Coord(), (containerLineLength - lineInfo[row].totalLength) / jmax (1, 2 * numColumns));
505 }
506
507 for (int column = 0; column < numColumns; ++column)
508 {
509 auto& item = getItem (column, row);
510
511 getStartLockedMargin (Axis::main, item) += additionalMarginLeft;
512 getEndLockedMargin (Axis::main, item) += additionalMarginRight;
513
514 item.item->currentBounds.setPosition (isRowDirection ? (float) (x + item.lockedMarginLeft)
515 : (float) item.lockedMarginLeft,
516 isRowDirection ? (float) item.lockedMarginTop
517 : (float) (x + item.lockedMarginTop));
518
519 x += getItemMainSize (item);
520 }
521 }
522 }
523
525 {
526 for (int row = 0; row < numberOfRows; ++row)
527 {
528 const auto lineY = lineInfo[row].lineY;
529 const auto numColumns = lineInfo[row].numItems;
530
531 for (int column = 0; column < numColumns; ++column)
532 {
533 auto& item = getItem (column, row);
534
535 if (isRowDirection)
536 item.item->currentBounds.setY ((float) (lineY + item.lockedMarginTop));
537 else
538 item.item->currentBounds.setX ((float) (lineY + item.lockedMarginLeft));
539
540 item.item->currentBounds.setSize ((float) item.lockedWidth,
541 (float) item.lockedHeight);
542 }
543 }
544
546 reverseWrap();
547 }
548
549private:
550 void resetRowItems (const int row) noexcept
551 {
552 const auto numColumns = lineInfo[row].numItems;
553
554 for (int column = 0; column < numColumns; ++column)
556 }
557
558 void resetUnlockedRowItems (const int row) noexcept
559 {
560 const auto numColumns = lineInfo[row].numItems;
561
562 for (int column = 0; column < numColumns; ++column)
563 {
564 auto& item = getItem (column, row);
565
566 if (! item.locked)
567 resetItem (item);
568 }
569 }
570
571 void resetItem (ItemWithState& item) noexcept
572 {
573 item.locked = false;
574
575 for (auto& axis : { Axis::main, Axis::cross })
576 getLockedSize (axis, item) = computePreferredSize (axis, item);
577 }
578
579 bool layoutRowItems (const int row) noexcept
580 {
581 const auto numColumns = lineInfo[row].numItems;
582 auto flexContainerLength = containerLineLength;
583 Coord totalItemsLength = 0, totalFlexGrow = 0, totalFlexShrink = 0;
584
585 for (int column = 0; column < numColumns; ++column)
586 {
587 const auto& item = getItem (column, row);
588
589 if (item.locked)
590 {
591 flexContainerLength -= getItemMainSize (item);
592 }
593 else
594 {
595 totalItemsLength += getItemMainSize (item);
596 totalFlexGrow += item.item->flexGrow;
597 totalFlexShrink += item.item->flexShrink;
598 }
599 }
600
601 Coord changeUnit = 0;
602 const auto difference = flexContainerLength - totalItemsLength;
603 const bool positiveFlexibility = difference > 0;
604
605 if (positiveFlexibility)
606 {
607 if (totalFlexGrow != 0.0)
608 changeUnit = difference / totalFlexGrow;
609 }
610 else
611 {
612 if (totalFlexShrink != 0.0)
613 changeUnit = difference / totalFlexShrink;
614 }
615
616 bool ok = true;
617
618 for (int column = 0; column < numColumns; ++column)
619 {
620 auto& item = getItem (column, row);
621
622 if (! item.locked)
623 if (! addToItemLength (item, (positiveFlexibility ? item.item->flexGrow
624 : item.item->flexShrink) * changeUnit, row))
625 ok = false;
626 }
627
628 return ok;
629 }
630
632 {
633 for (int row = 0; row < numberOfRows; ++row)
634 {
635 lineInfo[row].totalLength = 0;
636 const auto numColumns = lineInfo[row].numItems;
637
638 for (int column = 0; column < numColumns; ++column)
639 lineInfo[row].totalLength += getItemMainSize (getItem (column, row));
640 }
641 }
642
644 {
645 if (owner.flexDirection == FlexBox::Direction::rowReverse)
646 {
647 for (auto& item : owner.items)
648 item.currentBounds.setX ((float) (containerLineLength - item.currentBounds.getRight()));
649 }
650 else if (owner.flexDirection == FlexBox::Direction::columnReverse)
651 {
652 for (auto& item : owner.items)
653 item.currentBounds.setY ((float) (containerLineLength - item.currentBounds.getBottom()));
654 }
655 }
656
658 {
659 if (owner.flexWrap == FlexBox::Wrap::wrapReverse)
660 {
661 if (isRowDirection)
662 {
663 for (auto& item : owner.items)
664 item.currentBounds.setY ((float) (containerCrossLength - item.currentBounds.getBottom()));
665 }
666 else
667 {
668 for (auto& item : owner.items)
669 item.currentBounds.setX ((float) (containerCrossLength - item.currentBounds.getRight()));
670 }
671 }
672 }
673
674 Coord getItemMainSize (const ItemWithState& item) const noexcept
675 {
676 return isRowDirection ? item.lockedWidth + item.lockedMarginLeft + item.lockedMarginRight
677 : item.lockedHeight + item.lockedMarginTop + item.lockedMarginBottom;
678 }
679
680 Coord getItemCrossSize (const ItemWithState& item) const noexcept
681 {
682 return isRowDirection ? item.lockedHeight + item.lockedMarginTop + item.lockedMarginBottom
683 : item.lockedWidth + item.lockedMarginLeft + item.lockedMarginRight;
684 }
685
686 bool addToItemLength (ItemWithState& item, const Coord length, int row) const noexcept
687 {
688 bool ok = false;
689
690 const auto prefSize = computePreferredSize (Axis::main, item);
691
692 const auto pickForMainAxis = [this] (auto& a, auto& b) -> auto& { return pickForAxis (Axis::main, a, b); };
693
694 if (isAssigned (pickForMainAxis (item.item->maxWidth, item.item->maxHeight))
695 && pickForMainAxis (item.item->maxWidth, item.item->maxHeight) < prefSize + length)
696 {
697 pickForMainAxis (item.lockedWidth, item.lockedHeight) = pickForMainAxis (item.item->maxWidth, item.item->maxHeight);
698 item.locked = true;
699 }
700 else if (isAssigned (prefSize) && pickForMainAxis (item.item->minWidth, item.item->minHeight) > prefSize + length)
701 {
702 pickForMainAxis (item.lockedWidth, item.lockedHeight) = pickForMainAxis (item.item->minWidth, item.item->minHeight);
703 item.locked = true;
704 }
705 else
706 {
707 ok = true;
708 pickForMainAxis (item.lockedWidth, item.lockedHeight) = prefSize + length;
709 }
710
711 lineInfo[row].totalLength += pickForMainAxis (item.lockedWidth, item.lockedHeight)
712 + pickForMainAxis (item.lockedMarginLeft, item.lockedMarginTop)
713 + pickForMainAxis (item.lockedMarginRight, item.lockedMarginBottom);
714
715 return ok;
716 }
717
718 Coord computePreferredSize (Axis axis, ItemWithState& itemWithState) const noexcept
719 {
720 const auto& item = *itemWithState.item;
721
722 auto preferredSize = (item.flexBasis > 0 && axis == Axis::main) ? item.flexBasis
723 : (isAssigned (getItemSize (axis, itemWithState)) ? getItemSize (axis, itemWithState)
724 : getMinSize (axis, itemWithState));
725
726 const auto minSize = getMinSize (axis, itemWithState);
727
728 if (isAssigned (minSize) && preferredSize < minSize)
729 return minSize;
730
731 const auto maxSize = getMaxSize (axis, itemWithState);
732
733 if (isAssigned (maxSize) && maxSize < preferredSize)
734 return maxSize;
735
736 return preferredSize;
737 }
738};
739
740//==============================================================================
742
747
749{
750 if (! items.isEmpty())
751 {
752 FlexBoxLayoutCalculation layout (*this, targetArea.getWidth(), targetArea.getHeight());
753
754 layout.createStates();
755 layout.initialiseItems();
756 layout.resolveFlexibleLengths();
764 layout.layoutAllItems();
765
766 for (auto& item : items)
767 {
768 item.currentBounds += targetArea.getPosition();
769
770 if (auto* comp = item.associatedComponent)
771 comp->setBounds (Rectangle<int>::leftTopRightBottom ((int) item.currentBounds.getX(),
772 (int) item.currentBounds.getY(),
773 (int) item.currentBounds.getRight(),
774 (int) item.currentBounds.getBottom()));
775
776 if (auto* box = item.associatedFlexBox)
777 box->performLayout (item.currentBounds);
778 }
779 }
780}
781
783{
784 performLayout (targetArea.toFloat());
785}
786
787//==============================================================================
791FlexItem::FlexItem (float w, float h, FlexBox& fb) noexcept : FlexItem (w, h) { associatedFlexBox = &fb; }
794
797FlexItem::Margin::Margin (float t, float r, float b, float l) noexcept : left (l), right (r), top (t), bottom (b) {}
798
799//==============================================================================
800FlexItem FlexItem::withFlex (float newFlexGrow) const noexcept
801{
802 auto fi = *this;
803 fi.flexGrow = newFlexGrow;
804 return fi;
805}
806
807FlexItem FlexItem::withFlex (float newFlexGrow, float newFlexShrink) const noexcept
808{
809 auto fi = withFlex (newFlexGrow);
810 fi.flexShrink = newFlexShrink;
811 return fi;
812}
813
814FlexItem FlexItem::withFlex (float newFlexGrow, float newFlexShrink, float newFlexBasis) const noexcept
815{
816 auto fi = withFlex (newFlexGrow, newFlexShrink);
817 fi.flexBasis = newFlexBasis;
818 return fi;
819}
820
821FlexItem FlexItem::withWidth (float newWidth) const noexcept { auto fi = *this; fi.width = newWidth; return fi; }
822FlexItem FlexItem::withMinWidth (float newMinWidth) const noexcept { auto fi = *this; fi.minWidth = newMinWidth; return fi; }
823FlexItem FlexItem::withMaxWidth (float newMaxWidth) const noexcept { auto fi = *this; fi.maxWidth = newMaxWidth; return fi; }
824
825FlexItem FlexItem::withMinHeight (float newMinHeight) const noexcept { auto fi = *this; fi.minHeight = newMinHeight; return fi; }
826FlexItem FlexItem::withMaxHeight (float newMaxHeight) const noexcept { auto fi = *this; fi.maxHeight = newMaxHeight; return fi; }
827FlexItem FlexItem::withHeight (float newHeight) const noexcept { auto fi = *this; fi.height = newHeight; return fi; }
828
829FlexItem FlexItem::withMargin (Margin m) const noexcept { auto fi = *this; fi.margin = m; return fi; }
830FlexItem FlexItem::withOrder (int newOrder) const noexcept { auto fi = *this; fi.order = newOrder; return fi; }
831FlexItem FlexItem::withAlignSelf (AlignSelf a) const noexcept { auto fi = *this; fi.alignSelf = a; return fi; }
832
833//==============================================================================
834//==============================================================================
835#if JUCE_UNIT_TESTS
836
837class FlexBoxTests : public UnitTest
838{
839public:
840 FlexBoxTests() : UnitTest ("FlexBox", UnitTestCategories::gui) {}
841
842 void runTest() override
843 {
844 using AlignSelf = FlexItem::AlignSelf;
845 using Direction = FlexBox::Direction;
846
847 const Rectangle<float> rect (10.0f, 20.0f, 300.0f, 200.0f);
848 const auto doLayout = [&rect] (Direction direction, Array<FlexItem> items)
849 {
850 juce::FlexBox flex;
851 flex.flexDirection = direction;
852 flex.items = std::move (items);
853 flex.performLayout (rect);
854 return flex;
855 };
856
857 beginTest ("flex item with mostly auto properties");
858 {
859 const auto test = [this, &doLayout] (Direction direction, AlignSelf alignment, Rectangle<float> expectedBounds)
860 {
861 const auto flex = doLayout (direction, { juce::FlexItem{}.withAlignSelf (alignment) });
862 expect (flex.items.getFirst().currentBounds == expectedBounds);
863 };
864
865 test (Direction::row, AlignSelf::autoAlign, { rect.getX(), rect.getY(), 0.0f, rect.getHeight() });
866 test (Direction::row, AlignSelf::stretch, { rect.getX(), rect.getY(), 0.0f, rect.getHeight() });
867 test (Direction::row, AlignSelf::flexStart, { rect.getX(), rect.getY(), 0.0f, 0.0f });
868 test (Direction::row, AlignSelf::flexEnd, { rect.getX(), rect.getBottom(), 0.0f, 0.0f });
869 test (Direction::row, AlignSelf::center, { rect.getX(), rect.getCentreY(), 0.0f, 0.0f });
870
871 test (Direction::column, AlignSelf::autoAlign, { rect.getX(), rect.getY(), rect.getWidth(), 0.0f });
872 test (Direction::column, AlignSelf::stretch, { rect.getX(), rect.getY(), rect.getWidth(), 0.0f });
873 test (Direction::column, AlignSelf::flexStart, { rect.getX(), rect.getY(), 0.0f, 0.0f });
874 test (Direction::column, AlignSelf::flexEnd, { rect.getRight(), rect.getY(), 0.0f, 0.0f });
875 test (Direction::column, AlignSelf::center, { rect.getCentreX(), rect.getY(), 0.0f, 0.0f });
876 }
877
878 beginTest ("flex item with specified width and height");
879 {
880 constexpr auto w = 50.0f;
881 constexpr auto h = 60.0f;
882 const auto test = [&] (Direction direction, AlignSelf alignment, Rectangle<float> expectedBounds)
883 {
884 const auto flex = doLayout (direction, { juce::FlexItem().withAlignSelf (alignment)
885 .withWidth (w)
886 .withHeight (h) });
887 expect (flex.items.getFirst().currentBounds == expectedBounds);
888 };
889
890 test (Direction::row, AlignSelf::autoAlign, { rect.getX(), rect.getY(), w, h });
891 test (Direction::row, AlignSelf::stretch, { rect.getX(), rect.getY(), w, h });
892 test (Direction::row, AlignSelf::flexStart, { rect.getX(), rect.getY(), w, h });
893 test (Direction::row, AlignSelf::flexEnd, { rect.getX(), rect.getBottom() - h, w, h });
894 test (Direction::row, AlignSelf::center, { rect.getX(), rect.getY() + (rect.getHeight() - h) * 0.5f, w, h });
895
896 test (Direction::column, AlignSelf::autoAlign, { rect.getX(), rect.getY(), w, h });
897 test (Direction::column, AlignSelf::stretch, { rect.getX(), rect.getY(), w, h });
898 test (Direction::column, AlignSelf::flexStart, { rect.getX(), rect.getY(), w, h });
899 test (Direction::column, AlignSelf::flexEnd, { rect.getRight() - w, rect.getY(), w, h });
900 test (Direction::column, AlignSelf::center, { rect.getX() + (rect.getWidth() - w) * 0.5f, rect.getY(), w, h });
901 }
902
903 beginTest ("flex item with oversized width and height");
904 {
905 const auto w = rect.getWidth() * 2;
906 const auto h = rect.getHeight() * 2;
907 const auto test = [this, &doLayout, &w, &h] (Direction direction, AlignSelf alignment, Rectangle<float> expectedBounds)
908 {
909 const auto flex = doLayout (direction, { juce::FlexItem().withAlignSelf (alignment)
910 .withWidth (w)
911 .withHeight (h) });
912 expect (flex.items.getFirst().currentBounds == expectedBounds);
913 };
914
915 const Rectangle<float> baseRow (rect.getX(), rect.getY(), rect.getWidth(), h);
916 test (Direction::row, AlignSelf::autoAlign, baseRow);
917 test (Direction::row, AlignSelf::stretch, baseRow);
918 test (Direction::row, AlignSelf::flexStart, baseRow);
919 test (Direction::row, AlignSelf::flexEnd, baseRow.withBottomY (rect.getBottom()));
920 test (Direction::row, AlignSelf::center, baseRow.withCentre (rect.getCentre()));
921
922 const Rectangle<float> baseColumn (rect.getX(), rect.getY(), w, rect.getHeight());
923 test (Direction::column, AlignSelf::autoAlign, baseColumn);
924 test (Direction::column, AlignSelf::stretch, baseColumn);
925 test (Direction::column, AlignSelf::flexStart, baseColumn);
926 test (Direction::column, AlignSelf::flexEnd, baseColumn.withRightX (rect.getRight()));
927 test (Direction::column, AlignSelf::center, baseColumn.withCentre (rect.getCentre()));
928 }
929
930 beginTest ("flex item with minimum width and height");
931 {
932 constexpr auto w = 50.0f;
933 constexpr auto h = 60.0f;
934 const auto test = [&] (Direction direction, AlignSelf alignment, Rectangle<float> expectedBounds)
935 {
936 const auto flex = doLayout (direction, { juce::FlexItem().withAlignSelf (alignment)
937 .withMinWidth (w)
938 .withMinHeight (h) });
939 expect (flex.items.getFirst().currentBounds == expectedBounds);
940 };
941
942 test (Direction::row, AlignSelf::autoAlign, { rect.getX(), rect.getY(), w, rect.getHeight() });
943 test (Direction::row, AlignSelf::stretch, { rect.getX(), rect.getY(), w, rect.getHeight() });
944 test (Direction::row, AlignSelf::flexStart, { rect.getX(), rect.getY(), w, h });
945 test (Direction::row, AlignSelf::flexEnd, { rect.getX(), rect.getBottom() - h, w, h });
946 test (Direction::row, AlignSelf::center, { rect.getX(), rect.getY() + (rect.getHeight() - h) * 0.5f, w, h });
947
948 test (Direction::column, AlignSelf::autoAlign, { rect.getX(), rect.getY(), rect.getWidth(), h });
949 test (Direction::column, AlignSelf::stretch, { rect.getX(), rect.getY(), rect.getWidth(), h });
950 test (Direction::column, AlignSelf::flexStart, { rect.getX(), rect.getY(), w, h });
951 test (Direction::column, AlignSelf::flexEnd, { rect.getRight() - w, rect.getY(), w, h });
952 test (Direction::column, AlignSelf::center, { rect.getX() + (rect.getWidth() - w) * 0.5f, rect.getY(), w, h });
953 }
954
955 beginTest ("flex item with maximum width and height");
956 {
957 constexpr auto w = 50.0f;
958 constexpr auto h = 60.0f;
959 const auto test = [&] (Direction direction, AlignSelf alignment, Rectangle<float> expectedBounds)
960 {
961 const auto flex = doLayout (direction, { juce::FlexItem().withAlignSelf (alignment)
962 .withMaxWidth (w)
963 .withMaxHeight (h) });
964 expect (flex.items.getFirst().currentBounds == expectedBounds);
965 };
966
967 test (Direction::row, AlignSelf::autoAlign, { rect.getX(), rect.getY(), 0.0f, h });
968 test (Direction::row, AlignSelf::stretch, { rect.getX(), rect.getY(), 0.0f, h });
969 test (Direction::row, AlignSelf::flexStart, { rect.getX(), rect.getY(), 0.0f, 0.0f });
970 test (Direction::row, AlignSelf::flexEnd, { rect.getX(), rect.getBottom(), 0.0f, 0.0f });
971 test (Direction::row, AlignSelf::center, { rect.getX(), rect.getCentreY(), 0.0f, 0.0f });
972
973 test (Direction::column, AlignSelf::autoAlign, { rect.getX(), rect.getY(), w, 0.0f });
974 test (Direction::column, AlignSelf::stretch, { rect.getX(), rect.getY(), w, 0.0f });
975 test (Direction::column, AlignSelf::flexStart, { rect.getX(), rect.getY(), 0.0f, 0.0f });
976 test (Direction::column, AlignSelf::flexEnd, { rect.getRight(), rect.getY(), 0.0f, 0.0f });
977 test (Direction::column, AlignSelf::center, { rect.getCentreX(), rect.getY(), 0.0f, 0.0f });
978 }
979
980 beginTest ("flex item with specified flex");
981 {
982 const auto test = [this, &doLayout] (Direction direction, AlignSelf alignment, Rectangle<float> expectedBounds)
983 {
984 const auto flex = doLayout (direction, { juce::FlexItem().withAlignSelf (alignment).withFlex (1.0f) });
985 expect (flex.items.getFirst().currentBounds == expectedBounds);
986 };
987
988 test (Direction::row, AlignSelf::autoAlign, { rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight() });
989 test (Direction::row, AlignSelf::stretch, { rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight() });
990 test (Direction::row, AlignSelf::flexStart, { rect.getX(), rect.getY(), rect.getWidth(), 0.0f });
991 test (Direction::row, AlignSelf::flexEnd, { rect.getX(), rect.getBottom(), rect.getWidth(), 0.0f });
992 test (Direction::row, AlignSelf::center, { rect.getX(), rect.getCentreY(), rect.getWidth(), 0.0f });
993
994 test (Direction::column, AlignSelf::autoAlign, { rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight() });
995 test (Direction::column, AlignSelf::stretch, { rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight() });
996 test (Direction::column, AlignSelf::flexStart, { rect.getX(), rect.getY(), 0.0f, rect.getHeight() });
997 test (Direction::column, AlignSelf::flexEnd, { rect.getRight(), rect.getY(), 0.0f, rect.getHeight() });
998 test (Direction::column, AlignSelf::center, { rect.getCentreX(), rect.getY(), 0.0f, rect.getHeight() });
999 }
1000
1001 beginTest ("flex item with margin");
1002 {
1003 const FlexItem::Margin margin (10.0f, 20.0f, 30.0f, 40.0f);
1004
1005 const auto test = [this, &doLayout, &margin] (Direction direction, AlignSelf alignment, Rectangle<float> expectedBounds)
1006 {
1007 const auto flex = doLayout (direction, { juce::FlexItem().withAlignSelf (alignment).withMargin (margin) });
1008 expect (flex.items.getFirst().currentBounds == expectedBounds);
1009 };
1010
1011 const auto remainingHeight = rect.getHeight() - margin.top - margin.bottom;
1012 const auto remainingWidth = rect.getWidth() - margin.left - margin.right;
1013
1014 test (Direction::row, AlignSelf::autoAlign, { rect.getX() + margin.left, rect.getY() + margin.top, 0.0f, remainingHeight });
1015 test (Direction::row, AlignSelf::stretch, { rect.getX() + margin.left, rect.getY() + margin.top, 0.0f, remainingHeight });
1016 test (Direction::row, AlignSelf::flexStart, { rect.getX() + margin.left, rect.getY() + margin.top, 0.0f, 0.0f });
1017 test (Direction::row, AlignSelf::flexEnd, { rect.getX() + margin.left, rect.getBottom() - margin.bottom, 0.0f, 0.0f });
1018 test (Direction::row, AlignSelf::center, { rect.getX() + margin.left, rect.getY() + margin.top + remainingHeight * 0.5f, 0.0f, 0.0f });
1019
1020 test (Direction::column, AlignSelf::autoAlign, { rect.getX() + margin.left, rect.getY() + margin.top, remainingWidth, 0.0f });
1021 test (Direction::column, AlignSelf::stretch, { rect.getX() + margin.left, rect.getY() + margin.top, remainingWidth, 0.0f });
1022 test (Direction::column, AlignSelf::flexStart, { rect.getX() + margin.left, rect.getY() + margin.top, 0.0f, 0.0f });
1023 test (Direction::column, AlignSelf::flexEnd, { rect.getRight() - margin.right, rect.getY() + margin.top, 0.0f, 0.0f });
1024 test (Direction::column, AlignSelf::center, { rect.getX() + margin.left + remainingWidth * 0.5f, rect.getY() + margin.top, 0.0f, 0.0f });
1025 }
1026
1027 const AlignSelf alignments[] { AlignSelf::autoAlign,
1028 AlignSelf::stretch,
1029 AlignSelf::flexStart,
1030 AlignSelf::flexEnd,
1031 AlignSelf::center };
1032
1033 beginTest ("flex item with auto margin");
1034 {
1035 for (const auto& alignment : alignments)
1036 {
1037 for (const auto& direction : { Direction::row, Direction::column })
1038 {
1039 const auto flex = doLayout (direction, { juce::FlexItem().withAlignSelf (alignment)
1040 .withMargin ((float) FlexItem::autoValue) });
1041 expect (flex.items.getFirst().currentBounds == Rectangle<float> (rect.getCentre(), rect.getCentre()));
1042 }
1043 }
1044
1045 const auto testTop = [this, &doLayout] (Direction direction, AlignSelf alignment, Rectangle<float> expectedBounds)
1046 {
1047 const auto flex = doLayout (direction, { juce::FlexItem().withAlignSelf (alignment)
1048 .withMargin ({ (float) FlexItem::autoValue, 0.0f, 0.0f, 0.0f }) });
1049 expect (flex.items.getFirst().currentBounds == expectedBounds);
1050 };
1051
1052 for (const auto& alignment : alignments)
1053 testTop (Direction::row, alignment, { rect.getX(), rect.getBottom(), 0.0f, 0.0f });
1054
1055 testTop (Direction::column, AlignSelf::autoAlign, { rect.getX(), rect.getBottom(), rect.getWidth(), 0.0f });
1056 testTop (Direction::column, AlignSelf::stretch, { rect.getX(), rect.getBottom(), rect.getWidth(), 0.0f });
1057 testTop (Direction::column, AlignSelf::flexStart, { rect.getX(), rect.getBottom(), 0.0f, 0.0f });
1058 testTop (Direction::column, AlignSelf::flexEnd, { rect.getRight(), rect.getBottom(), 0.0f, 0.0f });
1059 testTop (Direction::column, AlignSelf::center, { rect.getCentreX(), rect.getBottom(), 0.0f, 0.0f });
1060
1061 const auto testBottom = [this, &doLayout] (Direction direction, AlignSelf alignment, Rectangle<float> expectedBounds)
1062 {
1063 const auto flex = doLayout (direction, { juce::FlexItem().withAlignSelf (alignment)
1064 .withMargin ({ 0.0f, 0.0f, (float) FlexItem::autoValue, 0.0f }) });
1065 expect (flex.items.getFirst().currentBounds == expectedBounds);
1066 };
1067
1068 for (const auto& alignment : alignments)
1069 testBottom (Direction::row, alignment, { rect.getX(), rect.getY(), 0.0f, 0.0f });
1070
1071 testBottom (Direction::column, AlignSelf::autoAlign, { rect.getX(), rect.getY(), rect.getWidth(), 0.0f });
1072 testBottom (Direction::column, AlignSelf::stretch, { rect.getX(), rect.getY(), rect.getWidth(), 0.0f });
1073 testBottom (Direction::column, AlignSelf::flexStart, { rect.getX(), rect.getY(), 0.0f, 0.0f });
1074 testBottom (Direction::column, AlignSelf::flexEnd, { rect.getRight(), rect.getY(), 0.0f, 0.0f });
1075 testBottom (Direction::column, AlignSelf::center, { rect.getCentreX(), rect.getY(), 0.0f, 0.0f });
1076
1077 const auto testLeft = [this, &doLayout] (Direction direction, AlignSelf alignment, Rectangle<float> expectedBounds)
1078 {
1079 const auto flex = doLayout (direction, { juce::FlexItem().withAlignSelf (alignment)
1080 .withMargin ({ 0.0f, 0.0f, 0.0f, (float) FlexItem::autoValue }) });
1081 expect (flex.items.getFirst().currentBounds == expectedBounds);
1082 };
1083
1084 testLeft (Direction::row, AlignSelf::autoAlign, { rect.getRight(), rect.getY(), 0.0f, rect.getHeight() });
1085 testLeft (Direction::row, AlignSelf::stretch, { rect.getRight(), rect.getY(), 0.0f, rect.getHeight() });
1086 testLeft (Direction::row, AlignSelf::flexStart, { rect.getRight(), rect.getY(), 0.0f, 0.0f });
1087 testLeft (Direction::row, AlignSelf::flexEnd, { rect.getRight(), rect.getBottom(), 0.0f, 0.0f });
1088 testLeft (Direction::row, AlignSelf::center, { rect.getRight(), rect.getCentreY(), 0.0f, 0.0f });
1089
1090 for (const auto& alignment : alignments)
1091 testLeft (Direction::column, alignment, { rect.getRight(), rect.getY(), 0.0f, 0.0f });
1092
1093 const auto testRight = [this, &doLayout] (Direction direction, AlignSelf alignment, Rectangle<float> expectedBounds)
1094 {
1095 const auto flex = doLayout (direction, { juce::FlexItem().withAlignSelf (alignment)
1096 .withMargin ({ 0.0f, (float) FlexItem::autoValue, 0.0f, 0.0f }) });
1097 expect (flex.items.getFirst().currentBounds == expectedBounds);
1098 };
1099
1100 testRight (Direction::row, AlignSelf::autoAlign, { rect.getX(), rect.getY(), 0.0f, rect.getHeight() });
1101 testRight (Direction::row, AlignSelf::stretch, { rect.getX(), rect.getY(), 0.0f, rect.getHeight() });
1102 testRight (Direction::row, AlignSelf::flexStart, { rect.getX(), rect.getY(), 0.0f, 0.0f });
1103 testRight (Direction::row, AlignSelf::flexEnd, { rect.getX(), rect.getBottom(), 0.0f, 0.0f });
1104 testRight (Direction::row, AlignSelf::center, { rect.getX(), rect.getCentreY(), 0.0f, 0.0f });
1105
1106 for (const auto& alignment : alignments)
1107 testRight (Direction::column, alignment, { rect.getX(), rect.getY(), 0.0f, 0.0f });
1108 }
1109
1110 beginTest ("in a multiline layout, items too large to fit on the main axis are given a line to themselves");
1111 {
1112 const auto spacer = 10.0f;
1113
1114 for (const auto alignment : alignments)
1115 {
1116 juce::FlexBox flex;
1117 flex.flexWrap = FlexBox::Wrap::wrap;
1118 flex.items = { FlexItem().withAlignSelf (alignment)
1119 .withWidth (spacer)
1120 .withHeight (spacer),
1121 FlexItem().withAlignSelf (alignment)
1122 .withWidth (rect.getWidth() * 2)
1123 .withHeight (rect.getHeight()),
1124 FlexItem().withAlignSelf (alignment)
1125 .withWidth (spacer)
1126 .withHeight (spacer) };
1127 flex.performLayout (rect);
1128
1129 expect (flex.items[0].currentBounds == Rectangle<float> (rect.getX(), rect.getY(), spacer, spacer));
1130 expect (flex.items[1].currentBounds == Rectangle<float> (rect.getX(), rect.getY() + spacer, rect.getWidth(), rect.getHeight()));
1131 expect (flex.items[2].currentBounds == Rectangle<float> (rect.getX(), rect.getBottom() + spacer, 10.0f, 10.0f));
1132 }
1133 }
1134 }
1135};
1136
1137static FlexBoxTests flexBoxTests;
1138
1139#endif
1140
1141} // namespace juce
Type jmin(const Type a, const Type b)
Definition MathsFunctions.h:60
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
Direction
Definition CarlaStyle.cpp:109
#define noexcept
Definition DistrhoDefines.h:72
uint8_t a
Definition Spc_Cpu.h:141
Definition Array.h:57
Definition juce_Array.h:56
Definition juce_Component.h:36
Definition juce_FlexBox.h:43
JustifyContent justifyContent
Definition juce_FlexBox.h:134
AlignContent
Definition juce_FlexBox.h:64
@ stretch
Definition juce_FlexBox.h:65
@ center
Definition juce_FlexBox.h:68
@ spaceBetween
Definition juce_FlexBox.h:69
@ flexEnd
Definition juce_FlexBox.h:67
@ spaceAround
Definition juce_FlexBox.h:70
@ flexStart
Definition juce_FlexBox.h:66
Wrap
Definition juce_FlexBox.h:56
@ noWrap
Definition juce_FlexBox.h:57
@ wrapReverse
Definition juce_FlexBox.h:59
Direction
Definition juce_FlexBox.h:47
@ rowReverse
Definition juce_FlexBox.h:49
@ columnReverse
Definition juce_FlexBox.h:51
JustifyContent
Definition juce_FlexBox.h:84
@ center
Definition juce_FlexBox.h:87
@ spaceBetween
Definition juce_FlexBox.h:88
@ flexEnd
Definition juce_FlexBox.h:86
@ spaceAround
Definition juce_FlexBox.h:89
FlexBox() noexcept=default
Wrap flexWrap
Definition juce_FlexBox.h:118
void performLayout(Rectangle< float > targetArea)
Definition juce_FlexBox.cpp:748
AlignItems
Definition juce_FlexBox.h:75
@ stretch
Definition juce_FlexBox.h:76
@ center
Definition juce_FlexBox.h:79
@ flexEnd
Definition juce_FlexBox.h:78
@ flexStart
Definition juce_FlexBox.h:77
Array< FlexItem > items
Definition juce_FlexBox.h:137
AlignItems alignItems
Definition juce_FlexBox.h:127
Direction flexDirection
Definition juce_FlexBox.h:113
AlignContent alignContent
Definition juce_FlexBox.h:124
Definition juce_FlexItem.h:37
float height
Definition juce_FlexItem.h:119
AlignSelf
Definition juce_FlexItem.h:95
@ stretch
Definition juce_FlexItem.h:100
@ center
Definition juce_FlexItem.h:99
@ flexEnd
Definition juce_FlexItem.h:98
@ flexStart
Definition juce_FlexItem.h:97
@ autoAlign
Definition juce_FlexItem.h:96
FlexItem() noexcept
Definition juce_FlexBox.cpp:788
FlexItem withHeight(float newHeight) const noexcept
Definition juce_FlexBox.cpp:827
FlexItem withWidth(float newWidth) const noexcept
Definition juce_FlexBox.cpp:821
float minWidth
Definition juce_FlexItem.h:116
float maxHeight
Definition juce_FlexItem.h:121
FlexItem withOrder(int newOrder) const noexcept
Definition juce_FlexBox.cpp:830
static const int autoValue
Definition juce_FlexItem.h:111
FlexItem withAlignSelf(AlignSelf newAlignSelf) const noexcept
Definition juce_FlexBox.cpp:831
FlexItem withMinWidth(float newMinWidth) const noexcept
Definition juce_FlexBox.cpp:822
FlexItem withMinHeight(float newMinHeight) const noexcept
Definition juce_FlexBox.cpp:825
float minHeight
Definition juce_FlexItem.h:120
FlexItem withMargin(Margin) const noexcept
Definition juce_FlexBox.cpp:829
FlexItem withMaxHeight(float newMaxHeight) const noexcept
Definition juce_FlexBox.cpp:826
float width
Definition juce_FlexItem.h:115
FlexBox * associatedFlexBox
Definition juce_FlexItem.h:68
Component * associatedComponent
Definition juce_FlexItem.h:65
float maxWidth
Definition juce_FlexItem.h:117
FlexItem withMaxWidth(float newMaxWidth) const noexcept
Definition juce_FlexBox.cpp:823
FlexItem withFlex(float newFlexGrow) const noexcept
Definition juce_FlexBox.cpp:800
Rectangle< float > currentBounds
Definition juce_FlexItem.h:62
Margin margin
Definition juce_FlexItem.h:137
static const int notAssigned
Definition juce_FlexItem.h:113
Definition juce_HeapBlock.h:87
Definition juce_Rectangle.h:67
Rectangle< float > toFloat() const noexcept
Definition juce_Rectangle.h:873
Point< ValueType > getPosition() const noexcept
Definition juce_Rectangle.h:161
static Rectangle leftTopRightBottom(ValueType left, ValueType top, ValueType right, ValueType bottom) noexcept
Definition juce_Rectangle.h:107
ValueType getHeight() const noexcept
Definition juce_Rectangle.h:136
ValueType getWidth() const noexcept
Definition juce_Rectangle.h:133
Definition juce_UnitTest.h:70
Definition juce_Value.h:51
UINT_D64 w
Definition inflate.c:942
int * l
Definition inflate.c:1579
unsigned * m
Definition inflate.c:1559
struct huft * t
Definition inflate.c:943
int y
Definition inflate.c:1588
unsigned v[N_MAX]
Definition inflate.c:1584
unsigned d
Definition inflate.c:940
register unsigned i
Definition inflate.c:1575
unsigned x[BMAX+1]
Definition inflate.c:1586
struct @113205115357366127300225113341150224053346037032::@137033172036070230260373056156374243321245367362 left
struct @113205115357366127300225113341150224053346037032::@137033172036070230260373056156374243321245367362 right
static PuglViewHint int value
Definition pugl.h:1708
#define jassertfalse
static int JUCE_CDECL comp(const void *a, const void *b)
Definition lsp.c:298
Definition juce_UnitTestCategories.h:27
Definition carla_juce.cpp:31
constexpr Type jmax(Type a, Type b)
Definition juce_MathsFunctions.h:94
@ column
Definition juce_AccessibilityRole.h:52
@ row
Definition juce_AccessibilityRole.h:53
GUI::ui_handle_t gui
Definition main.cpp:50
png_uint_32 length
Definition png.c:2247
static int test(SerdEnv *env, bool top_level, bool pretty_numbers)
Definition sratom_test.c:79
int main(int argc, char **argv)
Definition main.cpp:247
Definition jquant2.c:258
Definition juce_FlexBox.cpp:46
ItemWithState(FlexItem &source) noexcept
Definition juce_FlexBox.cpp:47
void resetItemLockedSize() noexcept
Definition juce_FlexBox.cpp:55
Coord lockedMarginRight
Definition juce_FlexBox.cpp:51
Coord lockedWidth
Definition juce_FlexBox.cpp:50
FlexItem * item
Definition juce_FlexBox.cpp:49
bool locked
Definition juce_FlexBox.cpp:53
Coord lockedMarginBottom
Definition juce_FlexBox.cpp:51
Coord preferredHeight
Definition juce_FlexBox.cpp:52
Coord preferredWidth
Definition juce_FlexBox.cpp:52
Coord lockedHeight
Definition juce_FlexBox.cpp:50
Coord lockedMarginLeft
Definition juce_FlexBox.cpp:51
Coord lockedMarginTop
Definition juce_FlexBox.cpp:51
Definition juce_FlexBox.cpp:67
Coord totalLength
Definition juce_FlexBox.cpp:69
Coord crossSize
Definition juce_FlexBox.cpp:69
int numItems
Definition juce_FlexBox.cpp:68
Coord lineY
Definition juce_FlexBox.cpp:69
Definition juce_FlexBox.cpp:30
auto & getPreferredSize(Axis axis, ItemWithState &item) const
Definition juce_FlexBox.cpp:125
const int numItems
Definition juce_FlexBox.cpp:74
void calculateCrossSizeOfAllItems() noexcept
Definition juce_FlexBox.cpp:289
auto & getItemSize(Axis axis, ItemWithState &item) const
Definition juce_FlexBox.cpp:135
void recalculateTotalItemLengthPerLineArray() noexcept
Definition juce_FlexBox.cpp:631
static bool isAssigned(Coord value) noexcept
Definition juce_FlexBox.cpp:88
const Coord containerLineLength
Definition juce_FlexBox.cpp:76
static bool isAuto(Coord value) noexcept
Definition juce_FlexBox.cpp:87
void resolveFlexibleLengths() noexcept
Definition juce_FlexBox.cpp:215
Axis
Definition juce_FlexBox.cpp:33
@ cross
Definition juce_FlexBox.cpp:33
@ main
Definition juce_FlexBox.cpp:33
void initialiseItems() noexcept
Definition juce_FlexBox.cpp:168
auto & getLockedSize(Axis axis, ItemWithState &item) const
Definition juce_FlexBox.cpp:120
HeapBlock< ItemWithState * > lineItems
Definition juce_FlexBox.cpp:81
auto & getMaxSize(Axis axis, ItemWithState &item) const
Definition juce_FlexBox.cpp:145
ItemWithState & getItem(int x, int y) const noexcept
Definition juce_FlexBox.cpp:85
void resetRowItems(const int row) noexcept
Definition juce_FlexBox.cpp:550
void resetUnlockedRowItems(const int row) noexcept
Definition juce_FlexBox.cpp:558
FlexBox & owner
Definition juce_FlexBox.cpp:72
void resetItem(ItemWithState &item) noexcept
Definition juce_FlexBox.cpp:571
double Coord
Definition juce_FlexBox.cpp:31
Coord getItemCrossSize(const ItemWithState &item) const noexcept
Definition juce_FlexBox.cpp:680
auto & getEndMargin(Axis axis, ItemWithState &item) const
Definition juce_FlexBox.cpp:105
void alignLinesPerAlignContent() noexcept
Definition juce_FlexBox.cpp:308
bool isSingleLine() const
Definition juce_FlexBox.cpp:92
Coord containerCrossLength
Definition juce_FlexBox.cpp:79
HeapBlock< RowInfo > lineInfo
Definition juce_FlexBox.cpp:82
void reverseLocations() noexcept
Definition juce_FlexBox.cpp:643
auto & getStartMargin(Axis axis, ItemWithState &item) const
Definition juce_FlexBox.cpp:100
void resolveAutoMarginsOnCrossAxis() noexcept
Definition juce_FlexBox.cpp:376
void layoutAllItems() noexcept
Definition juce_FlexBox.cpp:524
auto & getMinSize(Axis axis, ItemWithState &item) const
Definition juce_FlexBox.cpp:140
bool layoutRowItems(const int row) noexcept
Definition juce_FlexBox.cpp:579
void reverseWrap() noexcept
Definition juce_FlexBox.cpp:657
void alignItemsByJustifyContent() noexcept
Definition juce_FlexBox.cpp:477
Array< ItemWithState > itemStates
Definition juce_FlexBox.cpp:83
const bool isRowDirection
Definition juce_FlexBox.cpp:75
Coord getItemMainSize(const ItemWithState &item) const noexcept
Definition juce_FlexBox.cpp:674
void alignItemsInCrossAxisInLinesPerAlignSelf() noexcept
Definition juce_FlexBox.cpp:402
FlexBoxLayoutCalculation(FlexBox &fb, Coord w, Coord h)
Definition juce_FlexBox.cpp:35
void createStates()
Definition juce_FlexBox.cpp:151
Coord getContainerSize(Axis axis) const
Definition juce_FlexBox.cpp:130
const Coord parentHeight
Definition juce_FlexBox.cpp:73
bool addToItemLength(ItemWithState &item, const Coord length, int row) const noexcept
Definition juce_FlexBox.cpp:686
int numberOfRows
Definition juce_FlexBox.cpp:78
const Coord parentWidth
Definition juce_FlexBox.cpp:73
auto & getStartLockedMargin(Axis axis, ItemWithState &item) const
Definition juce_FlexBox.cpp:110
Value & pickForAxis(Axis axis, Value &x, Value &y) const
Definition juce_FlexBox.cpp:95
static Coord getValueOrZeroIfAuto(Coord value) noexcept
Definition juce_FlexBox.cpp:89
auto & getEndLockedMargin(Axis axis, ItemWithState &item) const
Definition juce_FlexBox.cpp:115
void resolveAutoMarginsOnMainAxis() noexcept
Definition juce_FlexBox.cpp:231
Coord computePreferredSize(Axis axis, ItemWithState &itemWithState) const noexcept
Definition juce_FlexBox.cpp:718
void calculateCrossSizesByLine() noexcept
Definition juce_FlexBox.cpp:265
Definition juce_FlexItem.h:125
Margin() noexcept
Definition juce_FlexBox.cpp:795
float right
Definition juce_FlexItem.h:131
float left
Definition juce_FlexItem.h:130
float bottom
Definition juce_FlexItem.h:133
float top
Definition juce_FlexItem.h:132
void Rectangle(HDC ctx, int l, int t, int r, int b)
Definition swell-gdi-generic.cpp:279
return c
Definition crypt.c:175
int r
Definition crypt.c:458
uch h[RAND_HEAD_LEN]
Definition crypt.c:459
b
Definition crypt.c:628
ulg size
Definition extract.c:2350