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