diff -r 7b3a3130be44 -r 64ded9f6a6c6 ui/cocoa/GridLayout.m --- a/ui/cocoa/GridLayout.m Mon Jan 06 22:22:55 2025 +0100 +++ b/ui/cocoa/GridLayout.m Tue Feb 25 21:11:00 2025 +0100 @@ -62,54 +62,129 @@ int ncols = _cols+1; int nrows = _rows+1; - GridDef *coldef = calloc(ncols, sizeof(GridDef)); - GridDef *rowdef = calloc(nrows, sizeof(GridDef)); + GridDef *cols = calloc(ncols, sizeof(GridDef)); + GridDef *rows = calloc(nrows, sizeof(GridDef)); NSRect viewFrame = self.frame; int colspacing = _columnspacing; int rowspacing = _rowspacing; - CxIterator i = cxListIterator(_children); - cx_foreach(GridElm *, elm, i) { - NSSize size = elm->view.intrinsicContentSize; - NSEdgeInsets alignment = elm->view.alignmentRectInsets; - if(size.width != NSViewNoIntrinsicMetric) { - CGFloat width = size.width + alignment.left + alignment.right; - if(width > coldef[elm->x].preferred_size) { - coldef[elm->x].preferred_size = width; + int span_max = 1; + for(int r=0;r<2;r++) { + CxIterator i = cxListIterator(_children); + cx_foreach(GridElm *, elm, i) { + int x = elm->x; + int y = elm->y; + GridDef *col = &cols[x]; + GridDef *row = &rows[y]; + + NSSize size = elm->view.intrinsicContentSize; + NSEdgeInsets alignment = elm->view.alignmentRectInsets; + if(size.width != NSViewNoIntrinsicMetric) { + CGFloat width = size.width + alignment.left + alignment.right; + if(width > cols[elm->x].preferred_size && elm->colspan <= 1 && span_max == 1) { + cols[elm->x].preferred_size = width; + } + elm->preferred_width = width; + } + if(size.height != NSViewNoIntrinsicMetric) { + CGFloat height = size.height + alignment.top + alignment.right; + //CGFloat height = size.height; + if(height > rows[elm->y].preferred_size && elm->rowspan <= 1 && span_max == 1) { + rows[elm->y].preferred_size = height; + } + elm->preferred_height = height; + } + + if(elm->rowspan > span_max || elm->colspan > span_max) { + continue; + } + + int end_col = x+elm->colspan; + if(end_col > ncols) { + end_col = ncols; + } + int end_row = y+elm->rowspan; + if(end_row > nrows) { + end_row = nrows; + } + + // are all columns in the span > preferred_width? + if(elm->colspan > 1) { + int span_width = 0; + GridDef *last_col = col; + for(int c=x;c<end_col;c++) { + span_width += cols[c].size; + last_col = &cols[c]; + } + if(span_width < elm->preferred_width) { + last_col->size += elm->preferred_width - span_width; + } + } + // are all rows in the span > preferred_height? + if(elm->rowspan > 1) { + int span_height = 0; + GridDef *last_row = row; + for(int c=x;c<end_row;c++) { + span_height += rows[c].size; + last_row = &rows[c]; + } + if(span_height < elm->preferred_height) { + last_row->size += elm->preferred_height - span_height; + } + } + + if(elm->hexpand) { + if(elm->colspan > 1) { + // check if any column in the span is expanding + // if not, make the last column expanding + GridDef *last_col = col; + for(int c=x;c<end_col;c++) { + last_col = &cols[c]; + if(last_col->expand) { + break; + } + } + last_col->expand = TRUE; + } else { + col->expand = TRUE; + } + } + if(elm->vexpand) { + if(elm->rowspan > 1) { + // same as colspan + GridDef *last_row = row; + for(int c=x;c<nrows;c++) { + last_row = &rows[c]; + if(last_row->expand) { + break; + } + } + last_row->expand = TRUE; + } else { + row->expand = TRUE; + } } } - if(size.height != NSViewNoIntrinsicMetric) { - CGFloat height = size.height + alignment.top + alignment.right; - //CGFloat height = size.height; - if(height > rowdef[elm->y].preferred_size) { - rowdef[elm->y].preferred_size = height; - } - } - - if(elm->hexpand) { - coldef[elm->x].extend = TRUE; - } - if(elm->vexpand) { - rowdef[elm->y].extend = TRUE; - } + span_max = 50000; // not sure if this is unreasonable low or high } + int col_ext = 0; int row_ext = 0; int preferred_width = 0; int preferred_height = 0; for(int j=0;j<ncols;j++) { - preferred_width += coldef[j].preferred_size + colspacing; - if(coldef[j].extend) { + preferred_width += cols[j].preferred_size + colspacing; + if(cols[j].expand) { col_ext++; } } for(int j=0;j<nrows;j++) { - preferred_height += rowdef[j].preferred_size + rowspacing; - if(rowdef[j].extend) { + preferred_height += rows[j].preferred_size + rowspacing; + if(rows[j].expand) { row_ext++; } } @@ -124,16 +199,16 @@ int vext = vremaining/row_ext; for(int j=0;j<ncols;j++) { - GridDef *col = &coldef[j]; - if(col->extend) { + GridDef *col = &cols[j]; + if(col->expand) { col->size = col->preferred_size + hext; } else { col->size = col->preferred_size; } } for(int j=0;j<nrows;j++) { - GridDef *row = &rowdef[j]; - if(row->extend) { + GridDef *row = &rows[j]; + if(row->expand) { row->size = row->preferred_size + vext; } else { row->size = row->preferred_size; @@ -142,32 +217,63 @@ int pos = 0; for(int j=0;j<ncols;j++) { - coldef[j].pos = pos; - pos += coldef[j].size + colspacing; + cols[j].pos = pos; + pos += cols[j].size + colspacing; } pos = 0; for(int j=0;j<nrows;j++) { - rowdef[j].pos = pos; - pos += rowdef[j].size + rowspacing; + rows[j].pos = pos; + pos += rows[j].size + rowspacing; } - i = cxListIterator(_children); + CxIterator i = cxListIterator(_children); cx_foreach(GridElm *, elm, i) { //NSSize size = elm->view.intrinsicContentSize; - GridDef *col = &coldef[elm->x]; - GridDef *row = &rowdef[elm->y]; + GridDef *col = &cols[elm->x]; + GridDef *row = &rows[elm->y]; NSEdgeInsets alignment = elm->view.alignmentRectInsets; NSRect frame; - frame.size.width = col->size; - frame.size.height = row->size; + if(elm->hfill) { + if(elm->colspan > 1) { + int cwidth = 0; + int end_col = elm->x + elm->colspan; + if(end_col > ncols) { + end_col = ncols; + } + for(int c=elm->x;c<end_col;c++) { + cwidth += cols[c].size; + } + frame.size.width = cwidth; + } else { + frame.size.width = col->size; + } + } else { + frame.size.width = elm->preferred_width; + } + if(elm->vfill) { + if(elm->rowspan > 1) { + int rheight = 0; + int end_row = elm->y + elm->rowspan; + if(end_row > nrows) { + end_row = nrows; + } + for(int r=elm->y;r<end_row;r++) { + rheight += rows[r].size; + } + frame.size.height = rheight; + } + frame.size.height = row->size; + } else { + frame.size.height = elm->preferred_height; + } frame.origin.x = col->pos - (alignment.left+alignment.right)/2; frame.origin.y = viewFrame.size.height - row->pos - frame.size.height + ((alignment.top+alignment.right)/2); elm->view.frame = frame; } - free(coldef); - free(rowdef); + free(cols); + free(rows); }