ui/motif/Grid.c

branch
newapi
changeset 406
0ebf9d7b23e8
child 407
8ea123dd89db
equal deleted inserted replaced
405:a7f18dda6baf 406:0ebf9d7b23e8
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2024 Olaf Wintermann. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
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 //static char defaultTranslations[] = "<BtnDown>: mousedown()\n";
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 //static XtResource constraints[] = {};
183
184 GridClassRec gridClassRec = {
185 // Core Class
186 {
187 //(WidgetClass)&constraintClassRec, // superclass
188 (WidgetClass)&xmManagerClassRec,
189 "Grid", // class_name
190 sizeof(GridRec), // widget_size
191 grid_class_initialize, // class_initialize
192 NULL, // class_part_initialize
193 FALSE, // class_inited
194 (XtInitProc)grid_initialize, // initialize
195 NULL, // initialize_hook
196 grid_realize, // realize
197 actionslist, // actions
198 XtNumber(actionslist), // num_actions
199 NULL, // resources
200 0, // num_resources
201 NULLQUARK, // xrm_class
202 True, // compress_motion
203 True, // compress_exposure
204 True, // compress_enterleave
205 False, // visible_interest
206 (XtWidgetProc)grid_destroy, // destroy
207 (XtWidgetProc)grid_resize, // resize
208 (XtExposeProc)grid_expose, // expose
209 grid_set_values, // set_values
210 NULL, // set_values_hook
211 XtInheritSetValuesAlmost, // set_values_almost
212 NULL, // get_values_hook
213 (XtAcceptFocusProc)grid_acceptfocus, // accept_focus
214 XtVersion, // version
215 NULL, // callback_offsets
216 //NULL, // tm_table
217 defaultTranslations,
218 XtInheritQueryGeometry, // query_geometry
219 NULL, // display_accelerator
220 NULL, // extension
221 },
222 // Composite Class
223 {
224 GridGeometryManager, /* geometry_manager */
225 GridChangeManaged, /* change_managed */
226 XtInheritInsertChild, /* insert_child */
227 XtInheritDeleteChild, /* delete_child */
228 NULL, /* extension */
229 },
230 // Constraint Class
231 {
232 constraints, /* resources */
233 XtNumber(constraints), /* num_resources */
234 sizeof(GridConstraintRec), /* constraint_size */
235 grid_constraint_init, /* initialize */
236 NULL, /* destroy */
237 ConstraintSetValues, /* set_values */
238 NULL, /* extension */
239 },
240 // XmManager Class
241 ///*
242 {
243 NULL,
244 NULL,
245 0,
246 NULL,
247 0,
248 NULL,
249 NULL
250 },
251 //*/
252 // MyWidget Class
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 //XtVaSetValues(widget, XmNwidth, request->width, XmNheight, request->height, NULL);
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 for(int i=0;i<w->composite.num_children;i++) {
371 Widget child = w->composite.children[i];
372 GridConstraintRec *constraints = child->core.constraints;
373 if(constraints->grid.x < ncols) {
374 if(constraints->grid.hexpand) {
375 cols[constraints->grid.x].expand = TRUE;
376 }
377 if(constraints->grid.pref_width > cols[constraints->grid.x].size) {
378 cols[constraints->grid.x].size = constraints->grid.pref_width;
379 }
380 } else {
381 fprintf(stderr, "Error: x >= ncols\n");
382 }
383 if(constraints->grid.y < nrows) {
384 if(constraints->grid.vexpand) {
385 rows[constraints->grid.y].expand = TRUE;
386 }
387 if(constraints->grid.pref_height > rows[constraints->grid.y].size) {
388 rows[constraints->grid.y].size = constraints->grid.pref_height;
389 }
390 } else {
391 fprintf(stderr, "Error: y >= nrows\n");
392 }
393 }
394
395 for(int i=0;i<ncols;i++) {
396 if(cols[i].expand) {
397 num_cols_expanding++;
398 }
399 req_width += cols[i].size;
400 }
401 for(int i=0;i<nrows;i++) {
402 if(rows[i].expand) {
403 num_rows_expanding++;
404 }
405 req_height += rows[i].size;
406 }
407
408 int hexpand = 0;
409 int width_diff = (int)w->core.width - req_width;
410 int hexpand2 = 0;
411 if(width_diff > 0 && num_cols_expanding > 0) {
412 hexpand = width_diff / num_cols_expanding;
413 hexpand2 = width_diff-hexpand*num_cols_expanding;
414 }
415 int x = 0;
416 for(int i=0;i<ncols;i++) {
417 cols[i].pos = x;
418 if(cols[i].expand) {
419 cols[i].size += hexpand + hexpand2;
420 }
421 x += cols[i].size;
422
423 hexpand2 = 0;
424 }
425
426 int vexpand = 0;
427 int height_diff = (int)w->core.height - req_height;
428 int vexpand2 = 0;
429 if(height_diff > 0 && num_rows_expanding > 0) {
430 vexpand = height_diff / num_rows_expanding;
431 vexpand2 = height_diff-vexpand*num_rows_expanding;
432 }
433 int y = 0;
434 for(int i=0;i<nrows;i++) {
435 rows[i].pos = y;
436 if(rows[i].expand) {
437 rows[i].size += vexpand + vexpand2;
438 }
439 y += rows[i].size;
440
441 vexpand2 = 0;
442 }
443
444 for(int i=0;i<w->composite.num_children;i++) {
445 Widget child = w->composite.children[i];
446 GridConstraintRec *constraints = child->core.constraints;
447 GridDef c = cols[constraints->grid.x];
448 GridDef r = rows[constraints->grid.y];
449 int x = c.pos;
450 int y = r.pos;
451 int width = constraints->grid.pref_width;
452 int height = constraints->grid.pref_height;
453 if(constraints->grid.hfill) {
454 if(constraints->grid.colspan > 1) {
455 Dimension cwidth = 0;
456 for(int j=0;j<constraints->grid.colspan;j++) {
457 if(constraints->grid.x+j < ncols) {
458 cwidth += cols[constraints->grid.x+j].size;
459 }
460 }
461 width = cwidth;
462 } else {
463 width = c.size;
464 }
465 }
466 if(constraints->grid.vfill) {
467 if(constraints->grid.rowspan > 1) {
468 Dimension cheight = 0;
469 for(int j=0;j<constraints->grid.rowspan;j++) {
470 if(constraints->grid.y+j < nrows) {
471 cheight += rows[constraints->grid.y+j].size;
472 }
473 }
474 height = cheight;
475 } else {
476 height = r.size;
477 }
478 }
479
480 XtConfigureWidget(child, x, y, width, height, child->core.border_width);
481 //printf("child %d %d - %d %d\n", (int)child->core.x, (int)child->core.y, (int)child->core.width, (int)child->core.height);
482 }
483
484 free(cols);
485 free(rows);
486 }
487

mercurial