From a0a9ab2319c7576ad6fb646c444e2ca4aa883c33 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Sep 2025 16:53:20 +0000 Subject: [PATCH 1/2] Initial plan From 04b10e714a96c6e0d65be0fa76d1abf61eac91c3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Sep 2025 17:04:58 +0000 Subject: [PATCH 2/2] Add grid cell size constraints for child element resizing Co-authored-by: gogillu <31105905+gogillu@users.noreply.github.com> --- .../designer-canvas/designer-canvas.ts | 32 ++++++++ src/app/services/layout-designer.ts | 79 +++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/src/app/components/designer-canvas/designer-canvas.ts b/src/app/components/designer-canvas/designer-canvas.ts index 5409dbc..9d6cdff 100644 --- a/src/app/components/designer-canvas/designer-canvas.ts +++ b/src/app/components/designer-canvas/designer-canvas.ts @@ -286,6 +286,38 @@ export class DesignerCanvasComponent implements OnInit { newHeight = this.MIN_SIZE; } + // Apply grid cell constraints if element is in a grid + if (this.resizeElement.parent && this.resizeElement.parent.type === ElementType.Grid) { + const gridElement = this.resizeElement.parent; + const gridElementRef = gridElement.domElement; + + if (gridElementRef) { + const maxDimensions = this.layoutDesigner.getGridChildMaxDimensions( + this.resizeElement, + gridElement, + gridElementRef + ); + + if (maxDimensions) { + // Constrain width to grid cell boundaries + if (newWidth > maxDimensions.maxWidth) { + if (this.resizeDirection.includes('w')) { + newX = this.startX + this.startWidth - maxDimensions.maxWidth; + } + newWidth = maxDimensions.maxWidth; + } + + // Constrain height to grid cell boundaries + if (newHeight > maxDimensions.maxHeight) { + if (this.resizeDirection.includes('n')) { + newY = this.startY + this.startHeight - maxDimensions.maxHeight; + } + newHeight = maxDimensions.maxHeight; + } + } + } + } + // Update element properties this.elementService.updateElementProperties(this.resizeElement, { x: newX, diff --git a/src/app/services/layout-designer.ts b/src/app/services/layout-designer.ts index 6506f4e..4e7e217 100644 --- a/src/app/services/layout-designer.ts +++ b/src/app/services/layout-designer.ts @@ -206,4 +206,83 @@ export class LayoutDesignerService { return Math.min(insertionIndex, stackElement.children.length); } + + /** + * Calculate the maximum allowed dimensions for a grid child element + * based on its grid position and span + */ + getGridChildMaxDimensions(childElement: MauiElement, gridElement: MauiElement, gridContainerElement: HTMLElement): { maxWidth: number, maxHeight: number } | null { + if (!this.getLayoutInfo(gridElement.type).supportsGridPositioning) { + return null; + } + + const gridDefinition = gridElement.properties.gridDefinition || { + rows: [{ height: { value: 1, type: 'Star' } }, { height: { value: 1, type: 'Star' } }], + columns: [{ width: { value: 1, type: 'Star' } }, { width: { value: 1, type: 'Star' } }] + }; + + const rect = gridContainerElement.getBoundingClientRect(); + const totalColumns = gridDefinition.columns.length; + const totalRows = gridDefinition.rows.length; + + // Get child's grid position and span + const column = childElement.properties.column || 0; + const row = childElement.properties.row || 0; + const columnSpan = childElement.properties.columnSpan || 1; + const rowSpan = childElement.properties.rowSpan || 1; + + // Calculate column widths + const columnWidths = this.calculateGridSizes(gridDefinition.columns.map(c => c.width), rect.width); + const rowHeights = this.calculateGridSizes(gridDefinition.rows.map(r => r.height), rect.height); + + // Calculate max width by summing up the widths of spanned columns + let maxWidth = 0; + for (let i = column; i < Math.min(column + columnSpan, totalColumns); i++) { + maxWidth += columnWidths[i]; + } + + // Calculate max height by summing up the heights of spanned rows + let maxHeight = 0; + for (let i = row; i < Math.min(row + rowSpan, totalRows); i++) { + maxHeight += rowHeights[i]; + } + + return { maxWidth, maxHeight }; + } + + /** + * Calculate actual sizes for grid columns/rows based on their definitions + */ + private calculateGridSizes(definitions: { value: number, type: string }[], totalSize: number): number[] { + const sizes: number[] = []; + let starCount = 0; + let fixedSize = 0; + + // First pass: calculate fixed sizes and count star units + definitions.forEach(def => { + if (def.type === 'Star') { + starCount += def.value; + } else if (def.type === 'Absolute') { + fixedSize += def.value; + } + // Auto sizing is complex and would need content measurement, treating as 1 star for now + }); + + // Calculate size per star unit + const remainingSize = Math.max(0, totalSize - fixedSize); + const starSize = starCount > 0 ? remainingSize / starCount : 0; + + // Second pass: assign actual sizes + definitions.forEach(def => { + if (def.type === 'Star') { + sizes.push(def.value * starSize); + } else if (def.type === 'Absolute') { + sizes.push(def.value); + } else { // Auto + sizes.push(starSize); // Fallback to 1 star unit + } + }); + + return sizes; + } }