mirror of
https://github.com/nicbarker/clay.git
synced 2026-02-06 12:48:49 +00:00
[Core] Improve & streamline grow / shrink handling (#296)
This commit is contained in:
parent
b5b086af13
commit
02bce89d17
7 changed files with 79 additions and 65 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
144
clay.h
144
clay.h
|
|
@ -2030,54 +2030,11 @@ void Clay__InitializePersistentMemory(Clay_Context* context) {
|
||||||
context->arenaResetOffset = arena->nextAllocation;
|
context->arenaResetOffset = arena->nextAllocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clay__CompressChildrenAlongAxis(bool xAxis, float totalSizeToDistribute, Clay__int32_tArray resizableContainerBuffer) {
|
const float CLAY__EPSILON = 0.01;
|
||||||
Clay_Context* context = Clay_GetCurrentContext();
|
|
||||||
Clay__int32_tArray largestContainers = context->openClipElementStack;
|
|
||||||
|
|
||||||
while (totalSizeToDistribute > 0.1) {
|
bool Clay__FloatEqual(float left, float right) {
|
||||||
largestContainers.length = 0;
|
float subtracted = left - right;
|
||||||
float largestSize = 0;
|
return subtracted < CLAY__EPSILON && subtracted > -CLAY__EPSILON;
|
||||||
float targetSize = 0;
|
|
||||||
for (int32_t i = 0; i < resizableContainerBuffer.length; ++i) {
|
|
||||||
Clay_LayoutElement *childElement = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&resizableContainerBuffer, i));
|
|
||||||
float childSize = xAxis ? childElement->dimensions.width : childElement->dimensions.height;
|
|
||||||
if ((childSize - largestSize) < 0.1 && (childSize - largestSize) > -0.1) {
|
|
||||||
Clay__int32_tArray_Add(&largestContainers, Clay__int32_tArray_GetValue(&resizableContainerBuffer, i));
|
|
||||||
} else if (childSize > largestSize) {
|
|
||||||
targetSize = largestSize;
|
|
||||||
largestSize = childSize;
|
|
||||||
largestContainers.length = 0;
|
|
||||||
Clay__int32_tArray_Add(&largestContainers, Clay__int32_tArray_GetValue(&resizableContainerBuffer, i));
|
|
||||||
}
|
|
||||||
else if (childSize > targetSize) {
|
|
||||||
targetSize = childSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (largestContainers.length == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
targetSize = CLAY__MAX(targetSize, (largestSize * largestContainers.length) - totalSizeToDistribute) / largestContainers.length;
|
|
||||||
|
|
||||||
for (int32_t childOffset = 0; childOffset < largestContainers.length; childOffset++) {
|
|
||||||
int32_t childIndex = Clay__int32_tArray_GetValue(&largestContainers, childOffset);
|
|
||||||
Clay_LayoutElement *childElement = Clay_LayoutElementArray_Get(&context->layoutElements, childIndex);
|
|
||||||
float *childSize = xAxis ? &childElement->dimensions.width : &childElement->dimensions.height;
|
|
||||||
float childMinSize = xAxis ? childElement->minDimensions.width : childElement->minDimensions.height;
|
|
||||||
float oldChildSize = *childSize;
|
|
||||||
*childSize = CLAY__MAX(childMinSize, targetSize);
|
|
||||||
totalSizeToDistribute -= (oldChildSize - *childSize);
|
|
||||||
if (*childSize == childMinSize) {
|
|
||||||
for (int32_t i = 0; i < resizableContainerBuffer.length; i++) {
|
|
||||||
if (Clay__int32_tArray_GetValue(&resizableContainerBuffer, i) == childIndex) {
|
|
||||||
Clay__int32_tArray_RemoveSwapback(&resizableContainerBuffer, i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clay__SizeContainersAlongAxis(bool xAxis) {
|
void Clay__SizeContainersAlongAxis(bool xAxis) {
|
||||||
|
|
@ -2115,7 +2072,7 @@ void Clay__SizeContainersAlongAxis(bool xAxis) {
|
||||||
int32_t growContainerCount = 0;
|
int32_t growContainerCount = 0;
|
||||||
float parentSize = xAxis ? parent->dimensions.width : parent->dimensions.height;
|
float parentSize = xAxis ? parent->dimensions.width : parent->dimensions.height;
|
||||||
float parentPadding = (float)(xAxis ? (parent->layoutConfig->padding.left + parent->layoutConfig->padding.right) : (parent->layoutConfig->padding.top + parent->layoutConfig->padding.bottom));
|
float parentPadding = (float)(xAxis ? (parent->layoutConfig->padding.left + parent->layoutConfig->padding.right) : (parent->layoutConfig->padding.top + parent->layoutConfig->padding.bottom));
|
||||||
float innerContentSize = 0, growContainerContentSize = 0, totalPaddingAndChildGaps = parentPadding;
|
float innerContentSize = 0, totalPaddingAndChildGaps = parentPadding;
|
||||||
bool sizingAlongAxis = (xAxis && parentStyleConfig->layoutDirection == CLAY_LEFT_TO_RIGHT) || (!xAxis && parentStyleConfig->layoutDirection == CLAY_TOP_TO_BOTTOM);
|
bool sizingAlongAxis = (xAxis && parentStyleConfig->layoutDirection == CLAY_LEFT_TO_RIGHT) || (!xAxis && parentStyleConfig->layoutDirection == CLAY_TOP_TO_BOTTOM);
|
||||||
resizableContainerBuffer.length = 0;
|
resizableContainerBuffer.length = 0;
|
||||||
float parentChildGap = parentStyleConfig->childGap;
|
float parentChildGap = parentStyleConfig->childGap;
|
||||||
|
|
@ -2141,7 +2098,6 @@ void Clay__SizeContainersAlongAxis(bool xAxis) {
|
||||||
if (sizingAlongAxis) {
|
if (sizingAlongAxis) {
|
||||||
innerContentSize += (childSizing.type == CLAY__SIZING_TYPE_PERCENT ? 0 : childSize);
|
innerContentSize += (childSizing.type == CLAY__SIZING_TYPE_PERCENT ? 0 : childSize);
|
||||||
if (childSizing.type == CLAY__SIZING_TYPE_GROW) {
|
if (childSizing.type == CLAY__SIZING_TYPE_GROW) {
|
||||||
growContainerContentSize += childSize;
|
|
||||||
growContainerCount++;
|
growContainerCount++;
|
||||||
}
|
}
|
||||||
if (childOffset > 0) {
|
if (childOffset > 0) {
|
||||||
|
|
@ -2180,25 +2136,83 @@ void Clay__SizeContainersAlongAxis(bool xAxis) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Scrolling containers preferentially compress before others
|
// Scrolling containers preferentially compress before others
|
||||||
Clay__CompressChildrenAlongAxis(xAxis, -sizeToDistribute, resizableContainerBuffer);
|
while (sizeToDistribute < -CLAY__EPSILON && resizableContainerBuffer.length > 0) {
|
||||||
|
float largest = 0;
|
||||||
|
float secondLargest = 0;
|
||||||
|
float widthToAdd = sizeToDistribute;
|
||||||
|
for (int childIndex = 0; childIndex < resizableContainerBuffer.length; childIndex++) {
|
||||||
|
Clay_LayoutElement *child = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&resizableContainerBuffer, childIndex));
|
||||||
|
float childSize = xAxis ? child->dimensions.width : child->dimensions.height;
|
||||||
|
if (Clay__FloatEqual(childSize, largest)) { continue; }
|
||||||
|
if (childSize > largest) {
|
||||||
|
secondLargest = largest;
|
||||||
|
largest = childSize;
|
||||||
|
}
|
||||||
|
if (childSize < largest) {
|
||||||
|
secondLargest = CLAY__MAX(secondLargest, childSize);
|
||||||
|
widthToAdd = secondLargest - largest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
widthToAdd = CLAY__MAX(widthToAdd, sizeToDistribute / resizableContainerBuffer.length);
|
||||||
|
|
||||||
|
for (int childIndex = 0; childIndex < resizableContainerBuffer.length; childIndex++) {
|
||||||
|
Clay_LayoutElement *child = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&resizableContainerBuffer, childIndex));
|
||||||
|
float *childSize = xAxis ? &child->dimensions.width : &child->dimensions.height;
|
||||||
|
float minSize = xAxis ? child->minDimensions.width : child->minDimensions.height;
|
||||||
|
float previousWidth = *childSize;
|
||||||
|
if (Clay__FloatEqual(*childSize, largest)) {
|
||||||
|
*childSize += widthToAdd;
|
||||||
|
if (*childSize <= minSize) {
|
||||||
|
*childSize = minSize;
|
||||||
|
Clay__int32_tArray_RemoveSwapback(&resizableContainerBuffer, childIndex--);
|
||||||
|
}
|
||||||
|
sizeToDistribute -= (*childSize - previousWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// The content is too small, allow SIZING_GROW containers to expand
|
// The content is too small, allow SIZING_GROW containers to expand
|
||||||
} else if (sizeToDistribute > 0 && growContainerCount > 0) {
|
} else if (sizeToDistribute > 0 && growContainerCount > 0) {
|
||||||
float targetSize = (sizeToDistribute + growContainerContentSize) / (float)growContainerCount;
|
for (int childIndex = 0; childIndex < resizableContainerBuffer.length; childIndex++) {
|
||||||
for (int32_t childOffset = 0; childOffset < resizableContainerBuffer.length; childOffset++) {
|
Clay_LayoutElement *child = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&resizableContainerBuffer, childIndex));
|
||||||
Clay_LayoutElement *childElement = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&resizableContainerBuffer, childOffset));
|
Clay__SizingType childSizing = xAxis ? child->layoutConfig->sizing.width.type : child->layoutConfig->sizing.height.type;
|
||||||
Clay_SizingAxis childSizing = xAxis ? childElement->layoutConfig->sizing.width : childElement->layoutConfig->sizing.height;
|
if (childSizing != CLAY__SIZING_TYPE_GROW) {
|
||||||
if (childSizing.type == CLAY__SIZING_TYPE_GROW) {
|
Clay__int32_tArray_RemoveSwapback(&resizableContainerBuffer, childIndex--);
|
||||||
float *childSize = xAxis ? &childElement->dimensions.width : &childElement->dimensions.height;
|
}
|
||||||
float *minSize = xAxis ? &childElement->minDimensions.width : &childElement->minDimensions.height;
|
}
|
||||||
if (targetSize < *minSize) {
|
while (sizeToDistribute > CLAY__EPSILON && resizableContainerBuffer.length > 0) {
|
||||||
growContainerContentSize -= *minSize;
|
float smallest = CLAY__MAXFLOAT;
|
||||||
Clay__int32_tArray_RemoveSwapback(&resizableContainerBuffer, childOffset);
|
float secondSmallest = CLAY__MAXFLOAT;
|
||||||
growContainerCount--;
|
float widthToAdd = sizeToDistribute;
|
||||||
targetSize = (sizeToDistribute + growContainerContentSize) / (float)growContainerCount;
|
for (int childIndex = 0; childIndex < resizableContainerBuffer.length; childIndex++) {
|
||||||
childOffset = -1;
|
Clay_LayoutElement *child = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&resizableContainerBuffer, childIndex));
|
||||||
continue;
|
float childSize = xAxis ? child->dimensions.width : child->dimensions.height;
|
||||||
|
if (Clay__FloatEqual(childSize, smallest)) { continue; }
|
||||||
|
if (childSize < smallest) {
|
||||||
|
secondSmallest = smallest;
|
||||||
|
smallest = childSize;
|
||||||
|
}
|
||||||
|
if (childSize > smallest) {
|
||||||
|
secondSmallest = CLAY__MIN(secondSmallest, childSize);
|
||||||
|
widthToAdd = secondSmallest - smallest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
widthToAdd = CLAY__MIN(widthToAdd, sizeToDistribute / resizableContainerBuffer.length);
|
||||||
|
|
||||||
|
for (int childIndex = 0; childIndex < resizableContainerBuffer.length; childIndex++) {
|
||||||
|
Clay_LayoutElement *child = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&resizableContainerBuffer, childIndex));
|
||||||
|
float *childSize = xAxis ? &child->dimensions.width : &child->dimensions.height;
|
||||||
|
float maxSize = xAxis ? child->layoutConfig->sizing.width.size.minMax.max : child->layoutConfig->sizing.height.size.minMax.max;
|
||||||
|
float previousWidth = *childSize;
|
||||||
|
if (Clay__FloatEqual(*childSize, smallest)) {
|
||||||
|
*childSize += widthToAdd;
|
||||||
|
if (*childSize >= maxSize) {
|
||||||
|
*childSize = maxSize;
|
||||||
|
Clay__int32_tArray_RemoveSwapback(&resizableContainerBuffer, childIndex--);
|
||||||
|
}
|
||||||
|
sizeToDistribute -= (*childSize - previousWidth);
|
||||||
}
|
}
|
||||||
*childSize = targetSize;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue