Something went wrong. Try again.
art software for the rest of us
drawing paint image sdl art
Something went wrong. Try again.
5.3 kB · 152 lines
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153#include "GridLayout.h"#include <algorithm>#include <cmath>
namespace UI {
GridLayout::GridLayout(float width, float itemSpacing, float rowHeight) : reasonableColumnWidth(std::max(1.0f, width)), spacing(std::max(0.0f, itemSpacing)), maximumRowHeight(std::max(0.0f, rowHeight)) {}
void GridLayout::SetReasonableColumnWidth(float width) { reasonableColumnWidth = std::max(1.0f, width); MarkDirty(DirtyFlags::Layout);}
float GridLayout::GetReasonableColumnWidth() const { return reasonableColumnWidth;}
void GridLayout::SetSpacing(float value) { spacing = std::max(0.0f, value); MarkDirty(DirtyFlags::Layout);}
float GridLayout::GetSpacing() const { return spacing;}
std::size_t GridLayout::GetColumnCount() const { return columnCount;}
std::size_t GridLayout::CalculateColumnCount(float availableWidth) const { float contentWidth = std::max(0.0f, availableWidth - padding.HorizontalTotal()); if (contentWidth <= 0.0f) { return 1; } float columns = (contentWidth + spacing) / (reasonableColumnWidth + spacing); return std::max<std::size_t>(1, static_cast<std::size_t>(std::round(columns)));}
float GridLayout::CalculateColumnWidth(float availableWidth) const { float contentWidth = std::max(0.0f, availableWidth - padding.HorizontalTotal()); return std::max(0.0f, (contentWidth - spacing * static_cast<float>(columnCount - 1)) / static_cast<float>(columnCount));}
void GridLayout::Measure(Size availableSpace) { columnCount = CalculateColumnCount(availableSpace.width); float columnWidth = CalculateColumnWidth(availableSpace.width); float totalHeight = padding.VerticalTotal(); float rowHeight = 0.0f; std::size_t column = 0; std::size_t rowCount = 0;
for (auto& child : children) { if (!child->IsVisible()) { continue; } child->Measure(Size(columnWidth, availableSpace.height)); rowHeight = std::max(rowHeight, child->GetDesiredSize().height); column++; if (column == columnCount) { column = 0; rowCount++; } } if (maximumRowHeight > 0.0f) { rowHeight = maximumRowHeight; } if (column != 0) { rowCount++; } if (rowCount > 0) { totalHeight += rowHeight * static_cast<float>(rowCount); totalHeight += spacing * static_cast<float>(rowCount - 1); }
float width = std::max(availableSpace.width, columnWidth * static_cast<float>(columnCount) + spacing * static_cast<float>(columnCount - 1) + padding.HorizontalTotal()); desiredSize.width = std::clamp(width + margin.HorizontalTotal(), minSize.width, maxSize.width); desiredSize.height = std::clamp(totalHeight + margin.VerticalTotal(), minSize.height, maxSize.height);}
void GridLayout::ArrangeChildInCell(Widget* child, Rect cellBounds) const { Size desired = child->GetDesiredSize(); Thickness childMargin = child->GetMargin(); float availableWidth = std::max(0.0f, cellBounds.Width - childMargin.HorizontalTotal()); float availableHeight = std::max(0.0f, cellBounds.Height - childMargin.VerticalTotal()); float scale = 1.0f; if (desired.width > 0.0f && desired.height > 0.0f) { scale = std::min(availableWidth / desired.width, availableHeight / desired.height); } float width = desired.width * scale; float height = desired.height * scale; child->Arrange(Rect( cellBounds.X + childMargin.Left + (availableWidth - width) * 0.5f, cellBounds.Y + childMargin.Top + (availableHeight - height) * 0.5f, width, height ));}
void GridLayout::Arrange(Rect finalBounds) { ArrangeCore(finalBounds); columnCount = CalculateColumnCount(localBounds.Width); float columnWidth = CalculateColumnWidth(localBounds.Width); std::vector<float> rowHeights; float rowHeight = 0.0f; for (std::size_t index = 0; index < children.size(); index++) { if (!children[index]->IsVisible()) { continue; } rowHeight = std::max(rowHeight, children[index]->GetDesiredSize().height); } if (maximumRowHeight > 0.0f) { rowHeight = maximumRowHeight; } std::size_t rowCount = children.empty() ? 0 : (children.size() + columnCount - 1) / columnCount; rowHeights.resize(rowCount, rowHeight); for (std::size_t index = 0; index < children.size(); index++) { if (!children[index]->IsVisible()) { continue; } std::size_t row = index / columnCount; if (row >= rowHeights.size()) { continue; } }
for (std::size_t index = 0; index < children.size(); index++) { if (!children[index]->IsVisible()) { continue; } std::size_t row = index / columnCount; std::size_t column = index % columnCount; float y = padding.Top; for (std::size_t previousRow = 0; previousRow < row; previousRow++) { y += rowHeights[previousRow] + spacing; } ArrangeChildInCell(children[index].get(), Rect( padding.Left + static_cast<float>(column) * (columnWidth + spacing), y, columnWidth, rowHeights[row] )); } ClearDirty(DirtyFlags::Layout);}
}