ui/win32/grid.c

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

mercurial