/*
* X11 GUI for slide puzzle game
* Copyright © 2022-2023 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
#include
#include "motif.h"
#include "motifgui.h"
#include "xcounter.h"
#include "version.h"
#define tree_strtab strtab
/* XXX generate this list? */
enum {
widgetMainWindow,
widgetForm,
widgetFrame,
widgetDrawingArea,
widgetCascadeButton,
widgetPushButton,
widgetMax,
/* Pseudo-widgets */
widgetMenuBar = widgetMax,
widgetMessageDialog,
widgetScrolledText,
widgetUnmanaged = 128
};
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 char *timer_text(int_fast32_t ms, char *buf)
{
unsigned min, sec;
sec = ms / 1000, ms %= 1000;
min = sec / 60, sec %= 60;
sprintf(buf, "Time: %u:%.2u.%.3u", min, sec, (unsigned)ms);
return buf;
}
void ui_timer_update(struct app_state *state, int_fast32_t ms)
{
char buf[100];
if (ms < 0) {
xcounter_update(state->timer, "\n");
return;
}
xcounter_update(state->timer, timer_text(ms, buf));
}
static void configure_mainwin(struct app_state *state, Widget form)
{
Widget gamearea = XtNameToWidget(form, &tree_strtab[gameArea]);
Widget goalarea = XtNameToWidget(form, &tree_strtab[goalArea]);
Widget timer = XtNameToWidget(form, &tree_strtab[timeDisplay]);
XtActionsRec resize_rec;
char xc_template[100];
assert(gamearea && goalarea && timer);
state->game = XtNameToWidget(gamearea, &tree_strtab[gameCanvas]);
XtVaSetValues(gamearea, XmNleftAttachment, XmATTACH_FORM,
XmNtopAttachment, XmATTACH_FORM,
(char *)NULL);
state->goal = XtNameToWidget(goalarea, &tree_strtab[goalCanvas]);
XtVaSetValues(goalarea, XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, gamearea,
XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
XmNtopWidget, gamearea,
(char *)NULL);
XtVaSetValues(timer, XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, gamearea,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, goalarea,
XmNrightAttachment, XmATTACH_FORM,
(char *)NULL);
state->timer = xcounter_simple_init(timer, timer_text(0, xc_template));
ui_timer_update(state, -1);
XtOverrideTranslations(form, XtParseTranslationTable(
": ResizeGameArea()\n"
"