2 * X11 GUI for slide puzzle game
3 * Copyright © 2022 Nick Bowler
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
27 #define SPLIT_NUMERATOR 75
28 #define SPLIT_DENOMINATOR 100
30 #define MIN(a, b) ((a) < (b) ? (a) : (b))
32 static void game_configure(Widget w);
34 static const struct ui_widget {
36 uint_least16_t subtree;
38 void (*configure)(Widget w);
39 } mainwin[] = { MAINWIN_INITIALIZER };
42 ResizeGameArea(Widget form, XEvent *e, String *args, Cardinal *num_args)
44 Widget game = XtNameToWidget(form, &tree_strtab[gameArea]);
45 Widget goal = XtNameToWidget(form, &tree_strtab[goalArea]);
46 Dimension w, h, gamesz, gameborder, goalsz, goalborder;
49 XtVaGetValues(form, XmNwidth, &w, XmNheight, &h, (char *)NULL);
50 XtVaGetValues(game, XmNshadowThickness, &gameborder, (char *)NULL);
51 XtVaGetValues(goal, XmNshadowThickness, &goalborder,
55 gamesz = MIN(h, w * SPLIT_NUMERATOR / SPLIT_DENOMINATOR);
56 gamesz = 5*( (gamesz - 2*gameborder)/5 ) + 2*gameborder;
58 goalsz = MIN(gamesz*3/5, w - gamesz - gap);
59 goalsz = 3*( (goalsz - 2*goalborder)/3 ) + 2*goalborder;
61 x = (w - gamesz - goalsz - gap) / 2;
67 XtVaSetValues(game, XmNleftOffset, x, XmNtopOffset, y, (char *)NULL);
68 XtVaSetValues(game, XmNwidth, gamesz, XmNheight, gamesz, (char *)NULL);
69 XtVaSetValues(goal, XmNwidth, goalsz, XmNheight, goalsz, (char *)NULL);
72 static void game_configure(Widget form)
74 Widget gamearea = XtNameToWidget(form, &tree_strtab[gameArea]);
75 Widget goalarea = XtNameToWidget(form, &tree_strtab[goalArea]);
76 XtActionsRec resize_rec;
78 assert(gamearea && goalarea);
79 XtVaSetValues(form, XmNfractionBase, SPLIT_DENOMINATOR, (char *)NULL);
81 XtVaSetValues(gamearea, //XmNrightAttachment, XmATTACH_POSITION,
82 //XmNrightPosition, SPLIT_NUMERATOR,
83 XmNleftAttachment, XmATTACH_FORM,
84 XmNtopAttachment, XmATTACH_FORM,
87 XtVaSetValues(goalarea, XmNleftAttachment, XmATTACH_WIDGET,
88 XmNleftWidget, gamearea,
89 XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
90 XmNtopWidget, gamearea,
93 resize_rec.string = "ResizeGameArea";
94 resize_rec.proc = ResizeGameArea;
95 XtAppAddActions(XtWidgetToApplicationContext(form), &resize_rec, 1);
96 XtOverrideTranslations(form, XtParseTranslationTable(
97 "<Configure>: ResizeGameArea()\n"
98 "<Map>: ResizeGameArea()\n"
103 construct_widgets(const struct ui_widget *root, Widget parent, unsigned i)
105 const struct ui_widget *item;
107 for (item = &root[i]; item->name; item++) {
110 w = XtCreateWidget(&tree_strtab[item->name], *item->class,
113 construct_widgets(root, w, item->subtree);
116 if (item->configure) {
124 static void game_resize(Widget w, void *data, void *cb_data)
126 Dimension width, height;
128 XtVaGetValues(w, XmNwidth, &width, XmNheight, &height, (char *)NULL);
130 printf("game %ux%u\n", width, height);
133 static void goal_resize(Widget w, void *data, void *cb_data)
135 Dimension width, height;
137 XtVaGetValues(w, XmNwidth, &width, XmNheight, &height, (char *)NULL);
139 printf("goal %ux%u\n", width, height);
142 void ui_initialize(Widget shell)
146 construct_widgets(mainwin, shell, 0);
148 game = XtNameToWidget(shell, "*gameCanvas");
149 goal = XtNameToWidget(shell, "*goalCanvas");
151 XtAddCallback(game, XmNresizeCallback, game_resize, NULL);
152 XtAddCallback(goal, XmNresizeCallback, goal_resize, NULL);