implement grid colspan/rowspan (Cocoa)

7 weeks ago

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Thu, 23 Jan 2025 21:08:43 +0100 (7 weeks ago)
changeset 449
7681d538deaf
parent 448
629ac70913aa
child 450
99b5d52096b5
child 454
57a2c6c04966

implement grid colspan/rowspan (Cocoa)

make/xcode/toolkit/toolkit/main.m file | annotate | diff | comparison | revisions
ui/cocoa/GridLayout.m file | annotate | diff | comparison | revisions
--- a/make/xcode/toolkit/toolkit/main.m	Wed Jan 22 22:06:10 2025 +0100
+++ b/make/xcode/toolkit/toolkit/main.m	Thu Jan 23 21:08:43 2025 +0100
@@ -45,6 +45,10 @@
     ui_button(obj, .label = "Button X4", .hfill = 1);
     ui_newline(obj);
     ui_button(obj, .label = "Button X5", .hfill = 0);
+    ui_button(obj, .label = "Button X5.1", .hfill = 1);
+    ui_button(obj, .label = "Button X5.6", .rowspan = 2);
+    ui_newline(obj);
+    ui_button(obj, .label = "Button X6", .hfill = 1, .colspan = 2);
     
     
     ui_show(obj);
--- a/ui/cocoa/GridLayout.m	Wed Jan 22 22:06:10 2025 +0100
+++ b/ui/cocoa/GridLayout.m	Thu Jan 23 21:08:43 2025 +0100
@@ -70,34 +70,107 @@
     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 > cols[elm->x].preferred_size) {
-                cols[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;
             }
-            elm->preferred_width = width;
+            
+            // 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 > rows[elm->y].preferred_size) {
-                rows[elm->y].preferred_size = height;
-            }
-            elm->preferred_height = height;
-        }
-        
-        if(elm->hexpand) {
-            cols[elm->x].expand = TRUE;
-        }
-        if(elm->vexpand) {
-            rows[elm->y].expand = TRUE;
-        }
+        span_max = 50000; // not sure if this is unreasonable low or high
     }
     
+    
     int col_ext = 0;
     int row_ext = 0;
     
@@ -153,7 +226,7 @@
         pos += rows[j].size + rowspacing;
     }
     
-    i = cxListIterator(_children);
+    CxIterator i = cxListIterator(_children);
     cx_foreach(GridElm *, elm, i) {
         //NSSize size = elm->view.intrinsicContentSize;
         GridDef *col = &cols[elm->x];
@@ -162,11 +235,34 @@
         NSEdgeInsets alignment = elm->view.alignmentRectInsets;
         NSRect frame;
         if(elm->hfill) {
-            frame.size.width = col->size;
+            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;

mercurial