1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #define _GNU_SOURCE
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include "Grid.h"
39
40 #include <X11/Xlib.h>
41
42
43
44 static XtActionsRec actionslist[] = {
45 {
"getfocus",grid_getfocus},
46 {
"loosefocus",grid_loosefocus},
47 {
"NULL",
NULL}
48 };
49
50
51 static char defaultTranslations[] =
"\
52 <EnterWindow>: getfocus()\n\
53 <LeaveWindow>: loosefocus()\n";
54
55
56
57 static XtResource constraints[] =
58 {
59 {
60 gridColumn,
61 gridColumn,
62 XmRDimension,
63 sizeof (Dimension),
64 XtOffsetOf( GridConstraintRec,
65 grid.x),
66 XmRImmediate,
67 (XtPointer)
0
68 },
69 {
70 gridRow,
71 gridRow,
72 XmRDimension,
73 sizeof (Dimension),
74 XtOffsetOf( GridConstraintRec,
75 grid.y),
76 XmRImmediate,
77 (XtPointer)
0
78 },
79 {
80 gridColspan,
81 gridColspan,
82 XmRDimension,
83 sizeof (Dimension),
84 XtOffsetOf( GridConstraintRec,
85 grid.colspan),
86 XmRImmediate,
87 (XtPointer)
0
88 },
89 {
90 gridRowspan,
91 gridRowspan,
92 XmRDimension,
93 sizeof (Dimension),
94 XtOffsetOf( GridConstraintRec,
95 grid.rowspan),
96 XmRImmediate,
97 (XtPointer)
0
98 },
99 {
100 gridMarginLeft,
101 gridMarginLeft,
102 XmRDimension,
103 sizeof (Dimension),
104 XtOffsetOf( GridConstraintRec,
105 grid.margin_left),
106 XmRImmediate,
107 (XtPointer)
0
108 },
109 {
110 gridMarginRight,
111 gridMarginRight,
112 XmRDimension,
113 sizeof (Dimension),
114 XtOffsetOf( GridConstraintRec,
115 grid.margin_right),
116 XmRImmediate,
117 (XtPointer)
0
118 },
119 {
120 gridMarginTop,
121 gridMarginTop,
122 XmRDimension,
123 sizeof (Dimension),
124 XtOffsetOf( GridConstraintRec,
125 grid.margin_top),
126 XmRImmediate,
127 (XtPointer)
0
128 },
129 {
130 gridMarginBottom,
131 gridMarginBottom,
132 XmRDimension,
133 sizeof (Dimension),
134 XtOffsetOf( GridConstraintRec,
135 grid.margin_bottom),
136 XmRImmediate,
137 (XtPointer)
0
138 },
139 {
140 gridHExpand,
141 gridHExpand,
142 XmRBoolean,
143 sizeof (Boolean),
144 XtOffsetOf( GridConstraintRec,
145 grid.hexpand),
146 XmRImmediate,
147 (XtPointer)
0
148 },
149 {
150 gridVExpand,
151 gridVExpand,
152 XmRBoolean,
153 sizeof (Boolean),
154 XtOffsetOf( GridConstraintRec,
155 grid.vexpand),
156 XmRImmediate,
157 (XtPointer)
0
158 },
159 {
160 gridHFill,
161 gridHFill,
162 XmRBoolean,
163 sizeof (Boolean),
164 XtOffsetOf( GridConstraintRec,
165 grid.hfill),
166 XmRImmediate,
167 (XtPointer)
0
168 },
169 {
170 gridVFill,
171 gridVFill,
172 XmRBoolean,
173 sizeof (Boolean),
174 XtOffsetOf( GridConstraintRec,
175 grid.vfill),
176 XmRImmediate,
177 (XtPointer)
0
178 }
179
180 };
181
182
183
184 GridClassRec gridClassRec = {
185
186 {
187
188 (WidgetClass)&xmManagerClassRec,
189 "Grid",
190 sizeof(GridRec),
191 grid_class_initialize,
192 NULL,
193 FALSE,
194 (XtInitProc)grid_initialize,
195 NULL,
196 grid_realize,
197 actionslist,
198 XtNumber(actionslist),
199 NULL,
200 0,
201 NULLQUARK,
202 True,
203 True,
204 True,
205 False,
206 (XtWidgetProc)grid_destroy,
207 (XtWidgetProc)grid_resize,
208 (XtExposeProc)grid_expose,
209 grid_set_values,
210 NULL,
211 XtInheritSetValuesAlmost,
212 NULL,
213 (XtAcceptFocusProc)grid_acceptfocus,
214 XtVersion,
215 NULL,
216
217 defaultTranslations,
218 XtInheritQueryGeometry,
219 NULL,
220 NULL,
221 },
222
223 {
224 GridGeometryManager,
225 GridChangeManaged,
226 XtInheritInsertChild,
227 XtInheritDeleteChild,
228 NULL,
229 },
230
231 {
232 constraints,
233 XtNumber(constraints),
234 sizeof(GridConstraintRec),
235 grid_constraint_init,
236 NULL,
237 ConstraintSetValues,
238 NULL,
239 },
240
241
242 {
243 NULL,
244 NULL,
245 0,
246 NULL,
247 0,
248 NULL,
249 NULL
250 },
251
252
253 {
254 0
255 }
256 };
257
258 WidgetClass gridClass = (WidgetClass)&gridClassRec;
259
260
261 void grid_class_initialize(Widget request, Widget new, ArgList args, Cardinal *num_args) {
262
263 }
264 void grid_initialize(Widget request, Widget new, ArgList args, Cardinal num_args) {
265 MyWidget mn = (MyWidget)new;
266
267 mn->mywidget.max_col =
0;
268 mn->mywidget.max_row =
0;
269
270 }
271 void grid_realize(MyWidget w,XtValueMask *valueMask,XSetWindowAttributes *attributes) {
272 XtMakeResizeRequest((Widget)w,
400,
400,
NULL,
NULL);
273 (coreClassRec.core_class.realize)((Widget)w, valueMask, attributes);
274 grid_place_children(w);
275 }
276
277
278 void grid_destroy(MyWidget widget) {
279
280 }
281 void grid_resize(MyWidget widget) {
282 grid_place_children(widget);
283 }
284
285 void grid_expose(MyWidget widget, XEvent *event, Region region) {
286
287 }
288
289
290 Boolean grid_set_values(Widget old, Widget request, Widget neww, ArgList args, Cardinal *num_args) {
291 return False;
292 }
293
294 Boolean grid_acceptfocus(Widget w, Time *t) {
295
296 }
297
298 void grid_getfocus(MyWidget myw, XEvent *event, String *params, Cardinal *nparam) {
299
300 }
301
302 void grid_loosefocus(MyWidget myw, XEvent *event, String *params, Cardinal *nparam) {
303
304 }
305
306
307
308 XtGeometryResult GridGeometryManager(Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *reply) {
309 GridRec *grid = (GridRec*)XtParent(widget);
310 GridConstraintRec *constraints = widget->core.constraints;
311
312 if((request->request_mode & CWWidth) == CWWidth) {
313 widget->core.width = request->width;
314 constraints->grid.pref_width = request->width;
315 }
316 if((request->request_mode & CWHeight) == CWHeight) {
317 widget->core.height = request->height;
318 constraints->grid.pref_height = request->height;
319 }
320 grid_place_children((MyWidget)XtParent(widget));
321 return XtGeometryYes;
322 }
323
324 void GridChangeManaged(Widget widget) {
325
326 }
327
328 Boolean ConstraintSetValues(Widget old, Widget request, Widget neww, ArgList args, Cardinal *num_args) {
329 GridConstraintRec *constraints = neww->core.constraints;
330 MyWidget grid = (MyWidget)XtParent(neww);
331 if(constraints->grid.x > grid->mywidget.max_col) {
332 grid->mywidget.max_col = constraints->grid.x;
333 }
334 if(constraints->grid.y > grid->mywidget.max_row) {
335 grid->mywidget.max_row = constraints->grid.y;
336 }
337 }
338
339
340 void grid_constraint_init(
341 Widget request,
342 Widget neww,
343 ArgList args,
344 Cardinal* num_args
345 )
346 {
347 GridConstraintRec *constraints = neww->core.constraints;
348
349 MyWidget grid = (MyWidget)XtParent(neww);
350 if(constraints->grid.x > grid->mywidget.max_col) {
351 grid->mywidget.max_col = constraints->grid.x;
352 }
353 if(constraints->grid.y > grid->mywidget.max_row) {
354 grid->mywidget.max_row = constraints->grid.y;
355 }
356 constraints->grid.pref_width = neww->core.width;
357 constraints->grid.pref_height = neww->core.height;
358 }
359
360 void grid_place_children(MyWidget w) {
361 int ncols = w->mywidget.max_col+
1;
362 int nrows = w->mywidget.max_row+
1;
363 GridDef *cols = calloc(ncols,
sizeof(GridDef));
364 GridDef *rows = calloc(nrows,
sizeof(GridDef));
365 int num_cols_expanding =
0;
366 int num_rows_expanding =
0;
367 int req_width =
0;
368 int req_height =
0;
369
370
371
372
373 int span_max =
1;
374 for(
int r=
0;r<
2;r++) {
375 for(
int i=
0;i<w->composite.num_children;i++) {
376 Widget child = w->composite.children[i];
377 GridConstraintRec *constraints = child->core.constraints;
378
379 if(constraints->grid.colspan > span_max || constraints->grid.rowspan > span_max) {
380 continue;
381 }
382
383 int x = constraints->grid.x;
384 int y = constraints->grid.y;
385
386
387 if(x >= ncols) {
388 fprintf(stderr,
"Error: widget x out of bounds\n");
389 continue;
390 }
391 if(y >= nrows) {
392 fprintf(stderr,
"Error: widget y out of bounds\n");
393 continue;
394 }
395 GridDef *col = &cols[x];
396 GridDef *row = &rows[y];
397
398 if(constraints->grid.hexpand) {
399 if(constraints->grid.colspan >
1) {
400
401
402 GridDef *last_col = col;
403 for(
int c=x;c<ncols;c++) {
404 last_col = &cols[c];
405 if(last_col->expand) {
406 break;
407 }
408 }
409 last_col->expand =
TRUE;
410 }
else {
411 col->expand =
TRUE;
412 }
413 }
414 if(constraints->grid.vexpand) {
415 if(constraints->grid.rowspan >
1) {
416 GridDef *last_row = row;
417 for(
int c=x;c<nrows;c++) {
418 last_row = &rows[c];
419 if(last_row->expand) {
420 break;
421 }
422 }
423 last_row->expand =
TRUE;
424 }
else {
425 row->expand =
TRUE;
426 }
427 }
428
429
430 if(constraints->grid.colspan >
1) {
431
432 Dimension span_width = col->size;
433 GridDef *last_col = col;
434 for(
int s=x+
1;s<ncols;s++) {
435 last_col = &cols[s];
436 span_width = last_col->size;
437
438 }
439 int diff = constraints->grid.pref_width - span_width;
440 if(diff >
0) {
441 last_col->size += diff;
442 }
443 }
else if(constraints->grid.pref_width > col->size) {
444 col->size = constraints->grid.pref_width;
445 }
446
447 if(constraints->grid.rowspan >
1) {
448 Dimension span_height = row->size;
449 GridDef *last_row = row;
450 for(
int s=x+
1;s<nrows;s++) {
451 last_row = &rows[s];
452 span_height = last_row->size;
453
454 }
455 int diff = constraints->grid.pref_height - span_height;
456 if(diff >
0) {
457 last_row->size += diff;
458 }
459 }
else if(constraints->grid.pref_height > row->size) {
460 row->size = constraints->grid.pref_height;
461 }
462 }
463 span_max =
50000;
464 }
465
466
467 for(
int i=
0;i<ncols;i++) {
468 if(cols[i].expand) {
469 num_cols_expanding++;
470 }
471 req_width += cols[i].size;
472 }
473 for(
int i=
0;i<nrows;i++) {
474 if(rows[i].expand) {
475 num_rows_expanding++;
476 }
477 req_height += rows[i].size;
478 }
479
480 if(req_width >
0 && req_height >
0) {
481 Widget parent = w->core.parent;
482 Dimension rwidth = req_width;
483 Dimension rheight = req_height;
484 if(rwidth < w->core.width) {
485
486 }
487 if(rheight < w->core.height) {
488
489 }
490
491 if(!w->mywidget.sizerequest) {
492 Dimension actual_width, actual_height;
493 w->mywidget.sizerequest =
TRUE;
494 XtMakeResizeRequest((Widget)w, req_width, req_height, &actual_width, &actual_height);
495 w->mywidget.sizerequest =
FALSE;
496
497 }
498
499
500
501 }
502
503 int hexpand =
0;
504 int width_diff = (
int)w->core.width - req_width;
505 int hexpand2 =
0;
506 if(width_diff >
0 && num_cols_expanding >
0) {
507 hexpand = width_diff / num_cols_expanding;
508 hexpand2 = width_diff-hexpand*num_cols_expanding;
509 }
510 int x =
0;
511 for(
int i=
0;i<ncols;i++) {
512 cols[i].pos = x;
513 if(cols[i].expand) {
514 cols[i].size += hexpand + hexpand2;
515 }
516 x += cols[i].size;
517
518 hexpand2 =
0;
519 }
520
521 int vexpand =
0;
522 int height_diff = (
int)w->core.height - req_height;
523 int vexpand2 =
0;
524 if(height_diff >
0 && num_rows_expanding >
0) {
525 vexpand = height_diff / num_rows_expanding;
526 vexpand2 = height_diff-vexpand*num_rows_expanding;
527 }
528 int y =
0;
529 for(
int i=
0;i<nrows;i++) {
530 rows[i].pos = y;
531 if(rows[i].expand) {
532 rows[i].size += vexpand + vexpand2;
533 }
534 y += rows[i].size;
535
536 vexpand2 =
0;
537 }
538
539 for(
int i=
0;i<w->composite.num_children;i++) {
540 Widget child = w->composite.children[i];
541 GridConstraintRec *constraints = child->core.constraints;
542 GridDef c = cols[constraints->grid.x];
543 GridDef r = rows[constraints->grid.y];
544 int x = c.pos;
545 int y = r.pos;
546 int width = constraints->grid.pref_width;
547 int height = constraints->grid.pref_height;
548 if(constraints->grid.hfill) {
549 if(constraints->grid.colspan >
1) {
550 Dimension cwidth =
0;
551 for(
int j=
0;j<constraints->grid.colspan;j++) {
552 if(constraints->grid.x+j < ncols) {
553 cwidth += cols[constraints->grid.x+j].size;
554 }
555 }
556 width = cwidth;
557 }
else {
558 width = c.size;
559 }
560 }
561 if(constraints->grid.vfill) {
562 if(constraints->grid.rowspan >
1) {
563 Dimension cheight =
0;
564 for(
int j=
0;j<constraints->grid.rowspan;j++) {
565 if(constraints->grid.y+j < nrows) {
566 cheight += rows[constraints->grid.y+j].size;
567 }
568 }
569 height = cheight;
570 }
else {
571 height = r.size;
572 }
573 }
574
575 XtConfigureWidget(child, x, y, width, height, child->core.border_width);
576
577 }
578
579 free(cols);
580 free(rows);
581 }
582
583