ui/win32/grid.c

changeset 827
eae5b817aa47
parent 818
8185cd761897
child 841
651cf2c59dd9
equal deleted inserted replaced
826:e596cfc1ca46 827:eae5b817aa47
29 #include "grid.h" 29 #include "grid.h"
30 30
31 #include "../../ucx/cx/array_list.h" 31 #include "../../ucx/cx/array_list.h"
32 #include "../common/context.h" 32 #include "../common/context.h"
33 33
34 UiGridLayout* ui_grid_container(UiObject *obj, HWND control, short padding, short columnspacing, short rowspacing) { 34 #include <stdio.h>
35 UiGridLayout *grid = cxZalloc(obj->ctx->allocator, sizeof(UiGridLayout)); 35 #include <stdlib.h>
36 grid->hwnd = control; 36
37 grid->widgets = cxArrayListCreate(obj->ctx->allocator, NULL, sizeof(GridElm), 32); 37 UiGridLayout* ui_grid_layout_create(const CxAllocator *a, short columnspacing, short rowspacing) {
38 grid->padding = padding; 38 UiGridLayout *grid = cxZalloc(a, sizeof(UiGridLayout));
39 grid->widgets = cxArrayListCreate(a, NULL, sizeof(GridElm), 32);
39 grid->columnspacing = columnspacing; 40 grid->columnspacing = columnspacing;
40 grid->rowspacing = rowspacing; 41 grid->rowspacing = rowspacing;
41 return grid; 42 return grid;
42 } 43 }
43 44
46 short x, 47 short x,
47 short y, 48 short y,
48 W32Widget *widget, 49 W32Widget *widget,
49 GridLayoutInfo *layout) 50 GridLayoutInfo *layout)
50 { 51 {
52 // add the widget
51 GridElm elm; 53 GridElm elm;
52 elm.widget = widget; 54 elm.widget = widget;
53 elm.x = x; 55 elm.gridx = x;
54 elm.y = y; 56 elm.gridy = y;
55 elm.layout = *layout; 57 elm.layout = *layout;
56 cxListAdd(grid->widgets, elm); 58 cxListAdd(grid->widgets, &elm);
59
60 // adjust max col/row count
61 if (x > grid->max_column) {
62 grid->max_column = x;
63 }
64 if (y > grid->max_row) {
65 grid->max_row = y;
66 }
57 } 67 }
58 68
59 void ui_grid_layout(UiGridLayout *grid) { 69 void ui_grid_layout(UiGridLayout *grid, int width, int height) {
60 // TODO 70 int ncols = grid->max_column+1;
71 int nrows = grid->max_row+1;
72
73 GridDef *cols = calloc(ncols, sizeof(GridDef));
74 GridDef *rows = calloc(nrows, sizeof(GridDef));
75
76 int colspacing = grid->columnspacing;
77 int rowspacing = grid->rowspacing;
78
79 int span_max = 1;
80 for(int r=0;r<2;r++) {
81 CxIterator i = cxListIterator(grid->widgets);
82 cx_foreach(GridElm *, elm, i) {
83 int x = elm->gridx;
84 int y = elm->gridy;
85 GridDef *col = &cols[x];
86 GridDef *row = &rows[y];
87
88 W32Size size = w32_widget_get_preferred_size(elm->widget);
89 elm->layout.preferred_width = size.width;
90 elm->layout.preferred_height = size.height;
91
92 int elm_width = size.width + elm->layout.margin.left + elm->layout.margin.right;
93 if(elm_width > cols[elm->gridx].preferred_size && elm->layout.colspan <= 1 && span_max == 1) {
94 cols[elm->gridx].preferred_size = elm_width;
95 }
96 int elm_height = size.height + elm->layout.margin.top + elm->layout.margin.bottom;
97 if(elm_height > rows[elm->gridy].preferred_size && elm->layout.rowspan <= 1 && span_max == 1) {
98 rows[elm->gridy].preferred_size = elm_height;
99 }
100
101 if(elm->layout.rowspan > span_max || elm->layout.colspan > span_max) {
102 continue;
103 }
104
105 int end_col = x+elm->layout.colspan;
106 if(end_col > ncols) {
107 end_col = ncols;
108 }
109 int end_row = y+elm->layout.rowspan;
110 if(end_row > nrows) {
111 end_row = nrows;
112 }
113
114 // are all columns in the span > preferred_width?
115 if(elm->layout.colspan > 1) {
116 int span_width = 0;
117 GridDef *last_col = col;
118 for(int c=x;c<end_col;c++) {
119 span_width += cols[c].size;
120 last_col = &cols[c];
121 }
122 if(span_width < elm->layout.preferred_width) {
123 last_col->size += elm->layout.preferred_width - span_width;
124 }
125 }
126
127 // are all rows in the span > preferred_height?
128 if(elm->layout.rowspan > 1) {
129 int span_height = 0;
130 GridDef *last_row = row;
131 for(int c=x;c<end_row;c++) {
132 span_height += rows[c].size;
133 last_row = &rows[c];
134 }
135 if(span_height < elm->layout.preferred_height) {
136 last_row->size += elm->layout.preferred_height - span_height;
137 }
138 }
139
140 if(elm->layout.hexpand) {
141 if(elm->layout.colspan > 1) {
142 // check if any column in the span is expanding
143 // if not, make the last column expanding
144 GridDef *last_col = col;
145 for(int c=x;c<end_col;c++) {
146 last_col = &cols[c];
147 if(last_col->expand) {
148 break;
149 }
150 }
151 last_col->expand = TRUE;
152 } else {
153 col->expand = TRUE;
154 }
155 }
156 if(elm->layout.vexpand) {
157 if(elm->layout.rowspan > 1) {
158 // same as colspan
159 GridDef *last_row = row;
160 for(int c=x;c<nrows;c++) {
161 last_row = &rows[c];
162 if(last_row->expand) {
163 break;
164 }
165 }
166 last_row->expand = TRUE;
167 } else {
168 row->expand = TRUE;
169 }
170 }
171 }
172 span_max = 50000; // not sure if this is unreasonable low or high
173 }
174
175 int col_ext = 0;
176 int row_ext = 0;
177
178 int preferred_width = 0;
179 int preferred_height = 0;
180 for(int j=0;j<ncols;j++) {
181 preferred_width += cols[j].preferred_size;
182 if(cols[j].expand) {
183 col_ext++;
184 }
185 }
186 for(int j=0;j<nrows;j++) {
187 preferred_height += rows[j].preferred_size;
188 if(rows[j].expand) {
189 row_ext++;
190 }
191 }
192 if(ncols > 0) {
193 preferred_width += (ncols-1) * colspacing;
194 }
195 if(nrows > 0) {
196 preferred_height += (nrows-1) * rowspacing;
197 }
198
199 grid->preferred_width = preferred_width;
200 grid->preferred_height = preferred_height;
201
202 int hremaining = width - preferred_width;
203 int vremaining = height - preferred_height;
204 int hext = col_ext > 0 ? hremaining/col_ext : 0;
205 int vext = row_ext > 0 ? vremaining/row_ext : 0;
206
207 for(int j=0;j<ncols;j++) {
208 GridDef *col = &cols[j];
209 if(col->expand) {
210 col->size = col->preferred_size + hext;
211 } else {
212 col->size = col->preferred_size;
213 }
214 }
215 for(int j=0;j<nrows;j++) {
216 GridDef *row = &rows[j];
217 if(row->expand) {
218 row->size = row->preferred_size + vext;
219 } else {
220 row->size = row->preferred_size;
221 }
222 }
223
224 int pos = 0;
225 for(int j=0;j<ncols;j++) {
226 cols[j].pos = pos;
227 pos += cols[j].size + colspacing;
228 }
229 pos = 0;
230 for(int j=0;j<nrows;j++) {
231 rows[j].pos = pos;
232 pos += rows[j].size + rowspacing;
233 }
234
235 CxIterator i = cxListIterator(grid->widgets);
236 cx_foreach(GridElm *, elm, i) {
237 GridDef *col = &cols[elm->gridx];
238 GridDef *row = &rows[elm->gridy];
239
240 int child_width = 0;
241 int child_height = 0;
242 int child_x = 0;
243 int child_y = 0;
244 if(elm->layout.hfill) {
245 if(elm->layout.colspan > 1) {
246 int cwidth = 0;
247 int end_col = elm->gridx + elm->layout.colspan;
248 if(end_col > ncols) {
249 end_col = ncols;
250 }
251 int real_span = 0;
252 for(int c=elm->gridx;c<end_col;c++) {
253 cwidth += cols[c].size;
254 real_span++;
255 }
256 if(real_span > 0) {
257 cwidth += (real_span-1) * colspacing;
258 }
259 child_width = cwidth;
260 } else {
261 child_width = col->size;
262 }
263 } else {
264 child_width = elm->layout.preferred_width;
265 }
266 child_width -= elm->layout.margin.left + elm->layout.margin.right;
267
268 if(elm->layout.vfill) {
269 if(elm->layout.rowspan > 1) {
270 int rheight = 0;
271 int end_row = elm->gridy + elm->layout.rowspan;
272 if(end_row > nrows) {
273 end_row = nrows;
274 }
275 int real_span = 0;
276 for(int r=elm->gridy;r<end_row;r++) {
277 rheight += rows[r].size;
278 real_span++;
279 }
280 if(real_span > 0) {
281 rheight += (real_span-1) * rowspacing;
282 }
283 child_height = rheight;
284 }
285 child_height = row->size;
286 } else {
287 child_height = elm->layout.preferred_height;
288 }
289
290 child_x = col->pos + elm->layout.margin.left;
291 child_y = row->pos + elm->layout.margin.top;
292 SetWindowPos(elm->widget->hwnd, NULL, child_x, child_y, child_width, child_height, SWP_NOZORDER);
293 }
294
295 free(cols);
296 free(rows);
61 } 297 }

mercurial