/*******************************************************************************
*                                                                              *
*                                   Viewmol                                    *
*                                                                              *
*                             D R A W F O R M . C                              *
*                                                                              *
*                 Copyright (c) Joerg-R. Hill, October 2003                    *
*                                                                              *
********************************************************************************
*
* $Id: drawform.c,v 1.6 2003/11/07 10:59:50 jrh Exp $
* $Log: drawform.c,v $
* Revision 1.6  2003/11/07 10:59:50  jrh
* Release 2.4
*
* Revision 1.5  2000/12/10 15:05:13  jrh
* Release 2.3
*
* Revision 1.4  1999/05/24 01:25:14  jrh
* Release 2.2.1
*
* Revision 1.3  1999/02/07 21:47:29  jrh
* Release 2.2
*
* Revision 1.2  1998/01/26 00:47:31  jrh
* Release 2.1
*
* Revision 1.1  1996/12/10  18:40:31  jrh
* Initial revision
*
*/
#include<X11/Intrinsic.h>
#include<Xm/Xm.h>
#include<Xm/BulletinB.h>
#include<Xm/Form.h>
#include<Xm/Label.h>
#include<Xm/LabelG.h>
#include<Xm/PanedW.h>
#include<Xm/PushB.h>
#include<Xm/PushBG.h>
#include<Xm/RowColumn.h>
#include<Xm/Scale.h>
#include<Xm/Separator.h>
#include<Xm/Text.h>
#include<Xm/ToggleB.h>
#include<math.h>
#include<GL/glu.h>
#include "viewmol.h"
#include "dialog.h"

extern void GetSlider(Widget, struct SLIDER *, XmScrollBarCallbackStruct *);
extern void MapBox(Widget, caddr_t, caddr_t);
extern Widget CreateToggleBox(Widget, struct PushButtonRow *, int, int,
                              int, int, int);
extern Widget CreatePushButtonRow(Widget, struct PushButtonRow *, int);
extern void redraw(int);
extern void changeBoolean(Widget, int *, XmDrawingAreaCallbackStruct *);
extern void drawMolecule(Widget, caddr_t, XmDrawingAreaCallbackStruct *);
extern void setMenuItem(int, int);
extern Widget initShell(Widget, char *, Widget *, Widget *);

void drawingModeDialogExit(Widget, caddr_t, XmPushButtonCallbackStruct *);
void switchLight(Widget, caddr_t, XmToggleButtonCallbackStruct *);
void switchMove(Widget, caddr_t, XmToggleButtonCallbackStruct *);
void setDrawingMode(Widget, caddr_t, XmToggleButtonCallbackStruct *);
void setProjection(Widget, caddr_t, XmToggleButtonCallbackStruct *);

extern struct WINDOW windows[];
extern Widget topShell;
extern int primitive, lights, moveItem, simplify, projectionMode, shadows;
extern double sphereres, lineWidth;

static Widget dialog, simpleRot=NULL, viewPoint;
static int primitive_save, lights_save, moveItem_save, projectionMode_save;
static double sphereres_save, lineWidth_save;

void drawingModeDialog(Widget widget, caddr_t dummy, XmAnyCallbackStruct *data)
{
  Widget board, form, form1, form2, form3, label, slider1, slider2;
  Widget radiobox, checkbox, sep1, sep2, sep3, sep4, sep5;
  static struct PushButtonRow buttons[] = {
    { "ok", drawingModeDialogExit, (XtPointer)TRUE, NULL },
    { "cancel", drawingModeDialogExit, (XtPointer)FALSE, NULL },
  };
  static struct PushButtonRow radiobox_buttons1[] = {
    { "dots", setDrawingMode, (XtPointer)GLU_POINT, NULL },
    { "lines", setDrawingMode, (XtPointer)GLU_LINE, NULL },
    { "surfaces", setDrawingMode, (XtPointer)GLU_FILL, NULL },
  };
  static struct PushButtonRow radiobox_buttons3[] = {
    { "orthographic", setProjection, (XtPointer)ORTHO, NULL },
    { "perspective", setProjection, (XtPointer)PERSPECTIVE, NULL },
  };
  static struct PushButtonRow checkbox_buttons[] = {
    { "light0OnOff", switchLight, (XtPointer)0, NULL },
    { "light1OnOff", switchLight, (XtPointer)1, NULL },
  };
  static struct PushButtonRow radiobox_buttons2[] = {
    { "viewpoint", switchMove, (XtPointer)VIEWPOINT, NULL},
    { "light0",    switchMove, (XtPointer)LIGHTNO0,  NULL },
    { "light1",    switchMove, (XtPointer)LIGHTNO1,  NULL },
    { "molecule",  switchMove, (XtPointer)MOLECULES, NULL },
  };
  static struct SLIDER spheregrid, lineWidthSlider;

  setMenuItem(VIEWER_DRAWING, False);

  primitive_save=primitive;
  lights_save=lights;
  moveItem_save=moveItem;
  projectionMode_save=projectionMode;
  sphereres_save=sphereres;
  spheregrid.number=&sphereres;
  spheregrid.decimals=0;
  spheregrid.draw=(void (*)())drawMolecule;
  lineWidth_save=lineWidth;
  lineWidthSlider.number=&lineWidth;
  lineWidthSlider.decimals=0;
  lineWidthSlider.draw=(void (*)())drawMolecule;

  dialog=initShell(windows[VIEWER].widget, "drawingModeForm", &board,
			 &form);
  form1=XtVaCreateWidget("rowcolumn", xmRowColumnWidgetClass, form,
                         XmNorientation, XmHORIZONTAL,
                         NULL);
  form2=XtVaCreateWidget("rowcolumn", xmRowColumnWidgetClass, form1,
                         XmNorientation, XmVERTICAL,
                         NULL);
  sep5=XtVaCreateManagedWidget("sep5", xmSeparatorWidgetClass, form1,
                              XmNtraversalOn, False,
                              XmNtopAttachment, XmATTACH_FORM,
                              XmNbottomAttachment, XmATTACH_FORM,
                              XmNorientation, XmVERTICAL,
                              NULL);
  form3=XtVaCreateWidget("rowcolumn", xmRowColumnWidgetClass, form1,
                         XmNorientation, XmVERTICAL,
                         NULL);

  radiobox=CreateToggleBox(form2, radiobox_buttons1, XtNumber(radiobox_buttons1),
                           XmVERTICAL, 1, True, primitive-GLU_POINT);
  XtVaSetValues(radiobox, XmNleftAttachment, XmATTACH_FORM,
                          XmNrightAttachment, XmATTACH_FORM,
                          XmNtopAttachment, XmATTACH_FORM,
                          NULL);
  simpleRot=XtVaCreateManagedWidget("simplify", xmToggleButtonWidgetClass,
                                    form2, NULL);
  if (simplify) XtVaSetValues(simpleRot, XmNset, True, NULL);
  if (primitive != GLU_FILL) XtVaSetValues(simpleRot, XmNsensitive, False,
                                           NULL);
  XtAddCallback(simpleRot, XmNvalueChangedCallback,
                (XtCallbackProc)changeBoolean, &simplify);

  sep1=XtVaCreateManagedWidget("sep1", xmSeparatorWidgetClass, form2,
                              XmNtraversalOn, False,
                              XmNleftAttachment, XmATTACH_FORM,
                              XmNrightAttachment, XmATTACH_FORM,
                              XmNtopAttachment, XmATTACH_WIDGET,
                              XmNtopWidget, radiobox,
                              NULL);
  label=XtVaCreateManagedWidget("projectionLabel", xmLabelWidgetClass, form2,
                                XmNleftAttachment, XmATTACH_FORM,
                                XmNrightAttachment, XmATTACH_FORM,
                                XmNtopAttachment, XmATTACH_WIDGET,
                                XmNtopWidget, sep1,
                                NULL);
  radiobox=CreateToggleBox(form2, radiobox_buttons3, XtNumber(radiobox_buttons3),
                           XmVERTICAL, 1, True, projectionMode);
  XtVaSetValues(radiobox, XmNleftAttachment, XmATTACH_FORM,
                          XmNrightAttachment, XmATTACH_FORM,
                          XmNbottomAttachment, XmATTACH_FORM,
                          NULL);

  radiobox=CreateToggleBox(form3, radiobox_buttons2, XtNumber(radiobox_buttons2),
                           XmVERTICAL, 1, True, moveItem < WORLD ? moveItem : WORLD);
  viewPoint=radiobox_buttons2[VIEWPOINT].widget;
  if (projectionMode == ORTHO) XtVaSetValues(viewPoint, XmNsensitive, False,
                                             NULL);
  sep2=XtVaCreateManagedWidget("sep2", xmSeparatorWidgetClass, form3,
                              XmNtraversalOn, False,
                              XmNleftAttachment, XmATTACH_FORM,
                              XmNrightAttachment, XmATTACH_FORM,
                              XmNtopAttachment, XmATTACH_WIDGET,
                              XmNtopWidget, radiobox,
                              NULL);

  label=XtVaCreateManagedWidget("onOffLabel", xmLabelWidgetClass, form3,
                                XmNleftAttachment, XmATTACH_FORM,
                                XmNrightAttachment, XmATTACH_FORM,
                                XmNtopAttachment, XmATTACH_WIDGET,
                                XmNtopWidget, sep2,
                                NULL);

  checkbox=CreateToggleBox(form3, checkbox_buttons, XtNumber(checkbox_buttons),
                           XmVERTICAL, 1, False, 0);
  if (lights & 0x1) XtVaSetValues(checkbox_buttons[0].widget, XmNset, True,
                                  NULL);
  if (lights & 0x2) XtVaSetValues(checkbox_buttons[1].widget, XmNset, True,
                                  NULL);

  sep3=XtVaCreateManagedWidget("sep3", xmSeparatorWidgetClass, form,
                              XmNtraversalOn, False,
                              XmNleftAttachment, XmATTACH_FORM,
                              XmNrightAttachment, XmATTACH_FORM,
                              XmNtopAttachment, XmATTACH_WIDGET,
                              XmNtopWidget, checkbox,
                              NULL);

  label=XtVaCreateManagedWidget("sphereResolutionLabel", xmLabelWidgetClass, form,
                                XmNleftAttachment, XmATTACH_FORM,
                                XmNrightAttachment, XmATTACH_FORM,
                                XmNtopAttachment, XmATTACH_WIDGET,
                                XmNtopWidget, sep3,
                                NULL);
  slider1=XtVaCreateManagedWidget("sphereResolution", xmScaleWidgetClass, form,
                                   XmNorientation, XmHORIZONTAL,
                                   XmNvalue, (int)sphereres,
                                   XmNminimum, 4,
                                   XmNmaximum, sphereres > 30. ? (int)sphereres : 30,
                                   XmNdecimalPoints, 0,
                                   XmNshowValue, True,
                                   XmNsensitive, True,
                                   XmNleftAttachment, XmATTACH_FORM,
                                   XmNrightAttachment, XmATTACH_FORM,
                                   XmNtopAttachment, XmATTACH_WIDGET,
                                   XmNtopWidget, label,
                                   NULL);
  XtAddCallback(slider1, XmNvalueChangedCallback, (XtCallbackProc)GetSlider, &spheregrid);

  label=XtVaCreateManagedWidget("lineWidthLabel", xmLabelWidgetClass, form,
                                XmNleftAttachment, XmATTACH_FORM,
                                XmNrightAttachment, XmATTACH_FORM,
                                XmNtopAttachment, XmATTACH_WIDGET,
                                XmNtopWidget, slider1,
                                NULL);
  slider2=XtVaCreateManagedWidget("lineWidth", xmScaleWidgetClass, form,
                                   XmNorientation, XmHORIZONTAL,
                                   XmNvalue, (int)lineWidth,
                                   XmNminimum, 0,
                                   XmNmaximum, lineWidth > 10. ? (int)lineWidth : 10,
                                   XmNdecimalPoints, 0,
                                   XmNshowValue, True,
                                   XmNsensitive, True,
                                   XmNleftAttachment, XmATTACH_FORM,
                                   XmNrightAttachment, XmATTACH_FORM,
                                   XmNtopAttachment, XmATTACH_WIDGET,
                                   XmNtopWidget, label,
                                   NULL);
  XtAddCallback(slider2, XmNvalueChangedCallback, (XtCallbackProc)GetSlider, &lineWidthSlider);

  sep4=XtVaCreateManagedWidget("sep4", xmSeparatorWidgetClass, form,
                              XmNtraversalOn, False,
                              XmNleftAttachment, XmATTACH_FORM,
                              XmNrightAttachment, XmATTACH_FORM,
                              XmNtopAttachment, XmATTACH_WIDGET,
                              XmNtopWidget, slider1,
                              NULL);

  CreatePushButtonRow(form, buttons, XtNumber(buttons));
  XtAddCallback(dialog, XmNpopupCallback, (XtCallbackProc)MapBox, (XtPointer)NULL);

  XtManageChild(form3);
  XtManageChild(form2);
  XtManageChild(form1);
  XtManageChild(form);
  XtManageChild(board);
}

void drawingModeDialogExit(Widget widget, caddr_t which, XmPushButtonCallbackStruct *data)
{
  XtDestroyWidget(dialog);
  simpleRot=NULL;
  if (!(int)which)
  {
    primitive=primitive_save;
    lights=lights_save;
    moveItem=moveItem_save;
    projectionMode=projectionMode_save;
    sphereres=sphereres_save;
    lineWidth=lineWidth_save;
    if (projectionMode == PERSPECTIVE) shadows=TRUE;
    else                               shadows=FALSE;
  }
  setMenuItem(VIEWER_DRAWING, True);
  redraw(VIEWER);
}

void setDrawingMode(Widget w, caddr_t mode, XmToggleButtonCallbackStruct *data)
{
  if (data->set)
  {
    primitive=(int)mode;
    if (simpleRot != NULL)
    {
      if (primitive == GLU_FILL) XtVaSetValues(simpleRot, XmNsensitive, True, NULL);
      else                       XtVaSetValues(simpleRot, XmNsensitive, False, NULL);
    }
    redraw(VIEWER);
  }
}

void setProjection(Widget w, caddr_t mode, XmToggleButtonCallbackStruct *data)
{
  if (data->set)
  {
    projectionMode=(int)mode;
    if (projectionMode == PERSPECTIVE)
    {
      shadows=TRUE;
      setMenuItem(VIEWER_FOREGROUND, True);
    }
    else
    {
      shadows=FALSE;
      setMenuItem(VIEWER_FOREGROUND, False);
    }
    if (viewPoint) XtVaSetValues(viewPoint, XmNsensitive, shadows, NULL);
    redraw(VIEWER);
  }
}

void switchLight(Widget widget, caddr_t which, XmToggleButtonCallbackStruct *data)
{
  register int i;

  i=1 << (int)which;
  if (data->set)
    lights|=i;
  else
    lights&=~i;
  redraw(VIEWER);
}

void switchMove(Widget widget, caddr_t which, XmToggleButtonCallbackStruct *data)
{
  if (data->set) moveItem=(int)which;
  redraw(VIEWER);
}
