/*
    This file is part of the FElt finite element analysis package.
    Copyright (C) 1993 Jason I. Gobat and Darren C. Atkinson

    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 2 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, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/****************************************************************************
*
* File:		toggle_form.c
*
* Description:	This file contains routines for the creation and 
*		management of toggle button forms, i.e. a form consisting
*		of a list of toggle buttons (NOT a radio group), okay/
*		cancel buttons and an optional labelled text entry box.  
*
* History:	by Jason Gobat and Darren Atkinson
*
****************************************************************************/

# include <stdio.h>
# include <X11/Xlib.h>
# include <X11/Xutil.h>
# include <X11/Intrinsic.h>
# include <X11/StringDefs.h>
# include <X11/Shell.h>
# include <X11/Xaw/Dialog.h>
# include <X11/Xaw/Form.h>
# include <X11/Xaw/Toggle.h>
# include "forms.h"

# define max(x,y)	((x) > (y) ? (x) : (y))
# define min(x,y)	((x) < (y) ? (x) : (y))

# define FONTSIZE 14

static void SetButtonState ();

static unsigned selected;

#define Okay   1
#define Cancel 2

static struct {
   String	name;
   unsigned	flag;
} buttons [ ] = {
   {"okay",	Okay},
   {"cancel",	Cancel},
};


ToggleForm *CreateToggleForm (parent_w, entries)
   Widget	parent_w;
   ToggleRecord	entries;
{
   unsigned		i;
   Arg			arglist[8];
   Cardinal		count;
   char			toggle_name[120];
   ToggleForm		*toggle_form;
   unsigned		max_width,
			width;

   max_width = 10; /* (okay) (cancel) */

   for (i = 0 ; i < entries.number ; i++) {
       width = strlen (entries.label [i]);
       if (width > max_width) max_width = width;
   }

   width = FONTSIZE*max_width;

   toggle_form = XtNew (ToggleForm);

   toggle_form -> shellwidget = XtCreatePopupShell ("toggleShell", 
                                transientShellWidgetClass, parent_w, 
                                NULL, 0);

   toggle_form -> formwidget = XtCreateManagedWidget ("toggleForm", 
                                formWidgetClass, toggle_form -> shellwidget, 
                                NULL, 0);

   toggle_form -> togglewidget = (Widget *) XtMalloc 
                                           (sizeof(Widget)*entries.number);

   for (i = 0 ; i < entries.number ; i++) {
      sprintf (toggle_name,"%sToggle",entries.label [i]);

      count = 0;
      XtSetArg (arglist [count], XtNlabel, entries.label [i]); count++;
      XtSetArg (arglist [count], XtNwidth, width); count++;

      if (i > 0) {
         XtSetArg (arglist [count], XtNfromVert, 
                   toggle_form -> togglewidget [i-1]); count++;
      } 
    
      toggle_form -> togglewidget [i]= XtCreateManagedWidget (toggle_name, 
                      toggleWidgetClass, toggle_form -> formwidget, 
                      arglist, count);
   }

   count = 0;
   XtSetArg (arglist [count], XtNborderWidth, 0); count++;
   XtSetArg (arglist [count], XtNfromVert, 
             toggle_form -> togglewidget [i-1]); count++;

   if (entries.entryLabel != NULL) {
      XtSetArg (arglist [count], XtNlabel, entries.entryLabel); count++;
      XtSetArg (arglist [count], XtNvalue, ""); count++;
   } else {
      XtSetArg (arglist [count], XtNlabel, ""); count++;
      XtSetArg (arglist [count], XtNvalue, NULL); count++;
   }
      
   toggle_form -> dialogwidget = XtCreateManagedWidget ("dialog", 
                                 dialogWidgetClass, toggle_form -> formwidget, 
                                 arglist, count); 

   for (i = 0 ; i < XtNumber (buttons) ; i++)
      XawDialogAddButton (toggle_form -> dialogwidget, buttons [i].name, 
                             SetButtonState, &buttons [i].flag);

   toggle_form -> topwidget = parent_w;

   return toggle_form;
}

unsigned GetToggleFormValues (toggle_form, entries, result, name)
   ToggleForm		*toggle_form;
   ToggleRecord		entries;
   Boolean		*result;
   String		*name;
{
   unsigned 	i;
   Widget	shell;
   XEvent	event;
   XSizeHints	hints;
   Cardinal	count;
   Arg		arglist[4];
   Dimension    formwidth, formheight,
                topwidth, topheight,
                borderwidth;
   Position     formx,formy,topx,topy;

   shell = toggle_form -> shellwidget;

   XtRealizeWidget (shell);

   XGetNormalHints (XtDisplay (shell), XtWindow (shell), &hints);

   hints.max_width = hints.width;
   hints.max_height = hints.height;
   hints.min_width = hints.width;
   hints.min_height = hints.height;
   hints.flags = PMaxSize | PMinSize;

   XSetNormalHints (XtDisplay (shell), XtWindow (shell), &hints);

   count = 0;
   XtSetArg(arglist[count], XtNx, &topx); count++;
   XtSetArg(arglist[count], XtNy, &topy); count++;
   XtSetArg(arglist[count], XtNwidth, &topwidth); count++;
   XtSetArg(arglist[count], XtNheight, &topheight); count++;
   XtGetValues(toggle_form -> topwidget, arglist, count);

   count = 0;
   XtSetArg(arglist[count], XtNwidth, &formwidth); count++;
   XtSetArg(arglist[count], XtNheight, &formheight); count++;
   XtSetArg(arglist[count], XtNborderWidth, &borderwidth); count++;
   XtGetValues(shell, arglist, count);

   formx = max(0, 
       min(topx + ((Position)topwidth - (Position)formwidth) / 2, 
           (Position)DisplayWidth(XtDisplay(shell), 
	    DefaultScreen(XtDisplay(shell))) -
            (Position)formwidth - 2 * (Position)borderwidth));
   formy = max(0, 
       min(topy + ((Position)topheight - (Position)formheight) / 2,
           (Position)DisplayHeight(XtDisplay(shell), 
	    DefaultScreen(XtDisplay(shell))) -
            (Position)formheight - 2 * (Position)borderwidth));

   count = 0;
   XtSetArg(arglist[count], XtNx, formx); count++;
   XtSetArg(arglist[count], XtNy, formy); count++;
   XtSetValues(shell, arglist, count);
  
   XtPopup (shell, XtGrabExclusive);

   XWarpPointer(XtDisplay(shell), 
                XtWindow(toggle_form -> topwidget),
                XtWindow(shell), 
                0, 0, 0, 0,
                formwidth / 2, formheight / 2);

   selected = 0;
   while (!(selected & (Okay | Cancel))) {
      XtAppNextEvent (XtWidgetToApplicationContext (toggle_form -> shellwidget),
							&event);
      XtDispatchEvent (&event);
   }

   XtPopdown (shell); 

   if (selected == Okay) {
      if (name)
         *name = XawDialogGetValueString (toggle_form -> dialogwidget);
      for (i = 0 ; i < entries.number ; i++) {
         XtSetArg (arglist [0], XtNstate, &result [i]);
         XtGetValues (toggle_form -> togglewidget [i], arglist, 1);
      }
      return 1;
   }
   return 0;
}

Boolean FlipToggleState (toggle_form, number)
   ToggleForm	*toggle_form;
   unsigned	number;
{
   Arg 		arglist[1];
   Boolean	state;

   XtSetArg (arglist[0], XtNstate, &state);
   XtGetValues (toggle_form -> togglewidget [number], arglist, 1);

   state = !state;

   XtSetArg (arglist[0], XtNstate, state);
   XtSetValues (toggle_form -> togglewidget [number], arglist, 1);
  
   return state;
}
   
static void SetButtonState (w, client_data, call_data)
   Widget 	w;
   XtPointer	client_data,
		call_data;
{
   selected = *(unsigned *) client_data;
}


void SetToggleStates (toggle_form, entries, suggestion, name)
    ToggleForm   *toggle_form;
    ToggleRecord  entries;
    Boolean      *suggestion;
    String        name;
{
    unsigned i;
    Arg      arglist [1];

    for (i = 0; i < entries.number; i ++) {
	XtSetArg (arglist [0], XtNstate, suggestion [i]);
	XtSetValues (toggle_form -> togglewidget [i], arglist, 1);
    }

    XtSetArg (arglist [0], XtNvalue, name);
    XtSetValues (toggle_form -> dialogwidget, arglist, 1);
}
