14#include <range/v3/all.hpp>
15#include "AWordWrappingEngine.h"
16#include "AUI/Util/AFraction.h"
18template<
typename Container>
19void AWordWrappingEngine<Container>::performLayout(
const glm::ivec2& offset,
const glm::ivec2& size) {
20 if (mEntries.empty()) {
26 struct StandardEntry {
27 aui::no_escape<Entry> entry;
28 int occupiedHorizontalSpace;
31 static constexpr auto UNDEFINED_POSITION_MARKER = std::numeric_limits<int>::min();
32 struct FloatingEntry {
33 aui::no_escape<Entry> entry;
34 int occupiedHorizontalSpace;
38 void setPosition(glm::ivec2 p) {
40 if (p.x == UNDEFINED_POSITION_MARKER || p.y == UNDEFINED_POSITION_MARKER) {
43 entry->setPosition(p);
50 typename decltype(inflatedEntriesByRows)
::iterator currentRow;
51 size_t currentRowWidth = 0;
52 int currentRowHeight = 0;
53 int currentY = offset.y;
63 for (
auto& i : leftFloat) {
64 currentRowWidth += i.occupiedHorizontalSpace;
66 for (
auto& i : rightFloat) {
67 currentRowWidth += i.occupiedHorizontalSpace;
69 inflatedEntriesByRows.push_back({});
70 currentRow = inflatedEntriesByRows.end() - 1;
73 auto flushRow = [&](
bool last) {
74 const int currentYWithLineHeightApplied = currentY + (mLineHeight - 1.f) / 2.f * currentRowHeight;
76 for (FloatingEntry& i: *floating | ranges::views::reverse) {
77 if (i.position.y != UNDEFINED_POSITION_MARKER) {
80 i.position.y = currentYWithLineHeightApplied;
81 i.setPosition(i.position);
87 case ATextAlign::JUSTIFY: {
89 int actualRowWidth = 0;
93 for (
auto& i: leftFloat) leftPadding += i.occupiedHorizontalSpace;
94 for (
auto& i: rightFloat) rightPadding += i.occupiedHorizontalSpace;
96 if (!currentRow->empty()) {
97 if (currentRow->last().entry->escapesEdges()) {
98 for (
auto it = currentRow->begin(); it != currentRow->end() - 1; ++it) {
99 actualRowWidth += it->occupiedHorizontalSpace;
102 for (
auto& i: *currentRow) actualRowWidth += i.occupiedHorizontalSpace;
106 int freeSpace = size.x - leftPadding - rightPadding;
108 AFraction spacing(freeSpace - actualRowWidth, (glm::max)(
int(currentRow->size()) - 1, 1));
110 currentX = offset.x + leftPadding;
112 for (
auto& i: *currentRow) {
113 i.entry->setPosition({currentX + (spacing * index).toInt(), currentYWithLineHeightApplied});
114 currentX += i.occupiedHorizontalSpace;
121 case ATextAlign::LEFT:
122 for (
auto& i: leftFloat) {
123 currentX += i.occupiedHorizontalSpace;
125 for (
auto& i: *currentRow) {
126 i.entry->setPosition({currentX + offset.x, currentYWithLineHeightApplied});
127 currentX += i.occupiedHorizontalSpace;
131 case ATextAlign::CENTER: {
132 int actualRowWidth = 0;
134 int rightPadding = 0;
136 for (
auto& i: leftFloat) leftPadding += i.occupiedHorizontalSpace;
137 for (
auto& i: rightFloat) rightPadding += i.occupiedHorizontalSpace;
138 if (!currentRow->empty()) {
139 if (currentRow->last().entry->escapesEdges()) {
140 for (
auto it = currentRow->begin(); it != currentRow->end() - 1; ++it) {
141 actualRowWidth += it->occupiedHorizontalSpace;
144 for (
auto& i: *currentRow) actualRowWidth += i.occupiedHorizontalSpace;
148 currentX = leftPadding + (size.x - leftPadding - rightPadding - actualRowWidth) / 2;
149 for (
auto& i: *currentRow) {
150 i.entry->setPosition({currentX + offset.x, currentYWithLineHeightApplied});
151 currentX += i.occupiedHorizontalSpace;
156 case ATextAlign::RIGHT:
158 int actualRowWidth = 0;
159 for (
auto& i : *currentRow) actualRowWidth += i.occupiedHorizontalSpace;
160 for (
auto& i : rightFloat) actualRowWidth += i.occupiedHorizontalSpace;
161 currentX = size.x - actualRowWidth;
162 for (
auto& i : *currentRow) {
163 i.entry->setPosition({currentX + offset.x, currentYWithLineHeightApplied});
164 currentX += i.occupiedHorizontalSpace;
173 for (
auto currentItem = mEntries.begin(); currentItem != mEntries.end(); ++currentItem) {
174 auto currentItemSize = (*currentItem)->getSize();
175 bool forcesNextLine = (*currentItem)->forcesNextLine();
176 bool escapesEdges = (*currentItem)->escapesEdges();
179 if (forcesNextLine || (currentRowWidth + currentItemSize.x > size.x && !escapesEdges)) {
181 if (!currentRow->empty() || forcesNextLine) {
185 for (
auto it = fl.begin(); it != fl.end();) {
186 it->remainingHeight -= currentRowHeight;
187 if (it->remainingHeight <= 0) {
197 removeRedundantItems(leftFloat);
198 removeRedundantItems(rightFloat);
200 currentY += int(
float(currentRowHeight) * mLineHeight);
201 currentRowHeight = 0;
206 if (mTextAlign == ATextAlign::JUSTIFY && (*currentItem)->escapesEdges()) {
207 currentItemSize.x = 0;
211 switch ((*currentItem)->getFloat()) {
213 int position = ranges::accumulate(leftFloat, 0, std::plus<>{}, &FloatingEntry::occupiedHorizontalSpace);
214 leftFloat.push_back({*currentItem, currentItemSize.x, currentItemSize.y});
215 leftFloat.last().setPosition({position, UNDEFINED_POSITION_MARKER });
220 rightFloat.push_back({*currentItem, currentItemSize.x, currentItemSize.y});
221 int position = ranges::accumulate(rightFloat, offset.x + size.x, std::minus<>{}, &FloatingEntry::occupiedHorizontalSpace);
222 rightFloat.last().setPosition({position, UNDEFINED_POSITION_MARKER });
227 currentRow->push_back({*currentItem, currentItemSize.x});
228 currentRowHeight = glm::max(currentRowHeight, currentItemSize.y);
232 currentRowWidth += currentItemSize.x;
236 auto floatingMax = [&] {
237 auto r = ranges::views::concat(leftFloat, rightFloat);
241 return ranges::max(r | ranges::views::transform([](
const FloatingEntry& e) {
return e.position.y + e.remainingHeight; }));
244 mHeight = std::max(currentY +
int(
float(currentRowHeight) * mLineHeight), floatingMax) - offset.y;
Definition AFraction.h:20
A std::vector with AUI extensions.
Definition AVector.h:39
@ RIGHT
Definition AFloat.h:35
@ LEFT
Definition AFloat.h:29
@ NONE
Definition AFloat.h:23