/* xmenu.c: menu's met het X window systeem */

#include <Xm/Xm.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>
#include <Xm/Form.h>
#include <Xm/Label.h>
#include <Xm/TextF.h>

#include "xmenu.h"
#include "debug.h"
#include "Memory.h"
#include "error.h"

/* callback procedure opgeroepen bij activeren van om het even welk menu-item */
static void DoProc(Widget w, XtPointer client_data, XtPointer call_data)
{
	XMENUPROC proc = (XMENUPROC)client_data;

/* roep de menu-procedure op met als argument het activerende widget. Dit widget
 * kan bvb gebruikt worden als parent voor verder volgende menu's */
	proc(w);
}

/* creeert een menu widget met gegeven parent widget en menu items */
Widget CreateXMenu(Widget parent, XMENUITEM *menuitems)
{
	Widget menuBox, menuButton;
	int i;

/* creeer een RowColumn widget dat de items groepeert */
	menuBox = XtVaCreateManagedWidget("menuBox",
					  xmRowColumnWidgetClass,
					  parent,
					  NULL);

/* creeer voor ieder item een PushButton widget dat bij activatie de callback
 * procedure DoProc activeert met als client_data het activerende widget. */
	for (i=0; menuitems[i].proc; i++) {
		menuButton = XtVaCreateManagedWidget("button",
						     xmPushButtonWidgetClass,
						     menuBox,
						     XtVaTypedArg,
						       XmNlabelString, XmRString, menuitems[i].label, strlen(menuitems[i].label)+1,
						     NULL);

		XtAddCallback(menuButton, XmNactivateCallback, DoProc, (XtPointer)menuitems[i].proc);
	}

	return menuBox;
}

/* creeert een menu en brengt het op het scherm in een afzonderlijk window */
void XMenu(Widget parent, char *menutitle, XMENUITEM *menuitems)
{
	Widget menuShell, menuBox;

/* creeer een volgend permanent window */
	menuShell = XtAppCreateShell(menutitle,
				     "menu",
				     topLevelShellWidgetClass,
				     XtDisplay(parent),
				     NULL,
				     0);

/* creeer het menu widget */
	menuBox = CreateXMenu(menuShell, menuitems);

/* breng het widget op het scherm */
	XtRealizeWidget(menuShell);
}


static void XFormFillInFloat(Widget w, XtPointer client_data, XtPointer call_data)
{
	float	*pvalue = (float *)client_data;
	char *text;

	text = XmTextFieldGetString(w);	
	sscanf(text, "%g", pvalue);
	XtFree(text);
}

static void XFormFillInInt(Widget w, XtPointer client_data, XtPointer call_data)
{
	int *pvalue = (int *)client_data;
	char *text;

	text = XmTextFieldGetString(w);	
	sscanf(text, "%d", pvalue);
	XtFree(text);
}

static void XFormFillInString(Widget w, XtPointer client_data, XtPointer call_data)
{
	char *pvalue = (char *)client_data;
	char *text;

	text = XmTextFieldGetString(w);	
	if (sscanf(text, "%s", pvalue) != 1)
		*pvalue = '\0';			/* leeg veld */
	XtFree(text);
}

Widget XFormCreate(Widget parent, XFORMFIELD *formfield)
{
	Widget formBox, field, value, label;
	int i;
	char buf[MAXFIELDLENGTH+1];

	formBox = XtVaCreateManagedWidget("formBox",
					  xmRowColumnWidgetClass,
					  parent,
					  NULL);

	for (i=0; formfield[i].label && i < MAXFIELDS; i++) {
		field = XtVaCreateWidget("formField",
					xmFormWidgetClass,
					formBox,
					NULL);

		value = XtVaCreateManagedWidget("fieldValue",
						xmTextFieldWidgetClass,
						field,
						XmNmaxLength,		MAXFIELDLENGTH,
						XmNrightAttachment,	XmATTACH_FORM,
						NULL);

		switch (formfield[i].type) {
		case XFORMINT:
			sprintf(buf, "%d", *(int *)formfield[i].pvalue);
			XtAddCallback(value,	XmNlosingFocusCallback,  
				      XFormFillInInt, (XtPointer)formfield[i].pvalue);
			break;
		case XFORMFLOAT:
			sprintf(buf, "%g", *(float *)formfield[i].pvalue);
			XtAddCallback(value,	XmNlosingFocusCallback,  
				      XFormFillInFloat, (XtPointer)formfield[i].pvalue);
			break;
		case XFORMSTRING:
			sprintf(buf, "%.*s", MAXFIELDLENGTH, formfield[i].pvalue);
			XtAddCallback(value,	XmNlosingFocusCallback,  
				      XFormFillInString, (XtPointer)formfield[i].pvalue);
			break;
		default:
			Fatal(-2, "XFormCreate", "Onmogelijk veldtype");
		}

		XmTextFieldSetString(value, buf);

		if (strlen(formfield[i].label) > 0) 
			label = XtVaCreateManagedWidget("fieldLabel",
						xmLabelWidgetClass,
						field,
						XtVaTypedArg,
						  XmNlabelString, XmRString, formfield[i].label, strlen(formfield[i].label)+1,
						XmNrightAttachment, 	XmATTACH_WIDGET,
						XmNrightWidget,		value,
						XmNtopAttachment,	XmATTACH_FORM,
						XmNbottomAttachment,	XmATTACH_FORM,
						NULL);

		XtManageChild(field);
	}

	return formBox;
}

/* creeert een menu en brengt het op het scherm in een afzonderlijk window */
void XForm(Widget parent, char *formtitle, XFORMFIELD *formfields)
{
	Widget formShell, formBox;

/* creeer een volgend permanent window */
	formShell = XtAppCreateShell(formtitle,
				     "form",
				     topLevelShellWidgetClass,
				     XtDisplay(parent),
				     NULL,
				     0);

/* creeer het form widget */
	formBox = XFormCreate(formShell, formfields);

/* breng het widget op het scherm */
	XtRealizeWidget(formShell);
}


