/*
* X11 GUI for slide puzzle game
* Copyright © 2022 Nick Bowler
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include "motif.h"
#include "motifstr.h"
#include "motifgui.h"
#define SPLIT_NUMERATOR 75
#define SPLIT_DENOMINATOR 100
#define MIN(a, b) ((a) < (b) ? (a) : (b))
/* XXX generate this list? */
enum {
widgetMainWindow,
widgetForm,
widgetFrame,
widgetDrawingArea,
widgetCascadeButton,
widgetPushButton,
widgetMax,
/* Pseudo-widgets */
widgetMenuBar = widgetMax
};
static WidgetClass * const widgets[widgetMax] = {
&xmMainWindowWidgetClass,
&xmFormWidgetClass,
&xmFrameWidgetClass,
&xmDrawingAreaWidgetClass,
&xmCascadeButtonWidgetClass,
&xmPushButtonWidgetClass
};
static const struct ui_widget {
uint_least16_t name;
uint_least8_t subtree;
uint_least8_t widget_type;
} mainwin[] = { MAINWIN_INITIALIZER };
static const struct ui_menuitem {
struct ui_widget w;
uint_least16_t label;
} mainmenu[] = { MAINMENU_INITIALIZER };
static void
ResizeGameArea(Widget form, XEvent *e, String *args, Cardinal *num_args)
{
Widget game = XtNameToWidget(form, &tree_strtab[gameArea]);
Widget goal = XtNameToWidget(form, &tree_strtab[goalArea]);
Dimension w, h, gamesz, gameborder, goalsz, goalborder;
int x, y, gap;
XtVaGetValues(form, XmNwidth, &w, XmNheight, &h, (char *)NULL);
XtVaGetValues(game, XmNshadowThickness, &gameborder, (char *)NULL);
XtVaGetValues(goal, XmNshadowThickness, &goalborder,
XmNleftOffset, &gap,
(char *)NULL);
gamesz = MIN(h, w * SPLIT_NUMERATOR / SPLIT_DENOMINATOR);
gamesz = 5*( (gamesz - 2*gameborder)/5 ) + 2*gameborder;
goalsz = MIN(gamesz*3/5, w - gamesz - gap);
goalsz = 3*( (goalsz - 2*goalborder)/3 ) + 2*goalborder;
x = (w - gamesz - goalsz - gap) / 2;
if (x < 2) x = 0;
y = (h - gamesz) / 2;
if (y < 3) y = 0;
XtVaSetValues(game, XmNleftOffset, x, XmNtopOffset, y, (char *)NULL);
XtVaSetValues(game, XmNwidth, gamesz, XmNheight, gamesz, (char *)NULL);
XtVaSetValues(goal, XmNwidth, goalsz, XmNheight, goalsz, (char *)NULL);
}
static void game_configure(Widget form)
{
Widget gamearea = XtNameToWidget(form, &tree_strtab[gameArea]);
Widget goalarea = XtNameToWidget(form, &tree_strtab[goalArea]);
XtActionsRec resize_rec;
assert(gamearea && goalarea);
XtVaSetValues(form, XmNfractionBase, SPLIT_DENOMINATOR, (char *)NULL);
XtVaSetValues(gamearea, XmNleftAttachment, XmATTACH_FORM,
XmNtopAttachment, XmATTACH_FORM,
(char *)NULL);
XtVaSetValues(goalarea, XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, gamearea,
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
XmNtopWidget, gamearea,
(char *)NULL);
resize_rec.string = "ResizeGameArea";
resize_rec.proc = ResizeGameArea;
XtAppAddActions(XtWidgetToApplicationContext(form), &resize_rec, 1);
XtOverrideTranslations(form, XtParseTranslationTable(
": ResizeGameArea()\n"
"