mirror of
				https://github.com/nicbarker/clay.git
				synced 2025-11-03 16:16:18 +00:00 
			
		
		
		
	[Core] Improve & streamline grow / shrink handling (#296)
This commit is contained in:
		
							parent
							
								
									b5b086af13
								
							
						
					
					
						commit
						02bce89d17
					
				
										
											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…
	
		Reference in a new issue