/*******************************************************************************
*                                                                              *
*                                   Viewmol                                    *
*                                                                              *
*                             C E L L F O R M . C                              *
*                                                                              *
*                 Copyright (c) Joerg-R. Hill, October 2003                    *
*                                                                              *
********************************************************************************
*
* $Id: cellform.c,v 1.5 2004/08/29 14:49:02 jrh Exp $
* $Log: cellform.c,v $
* Revision 1.5  2004/08/29 14:49:02  jrh
* Release 2.4.1
*
* Revision 1.4  2003/11/07 10:58:46  jrh
* Release 2.4
*
* Revision 1.3  2000/12/10 15:02:51  jrh
* Release 2.3
*
* Revision 1.2  1999/05/24 01:24:56  jrh
* Release 2.2.1
*
* Revision 1.1  1999/02/07 21:45:28  jrh
* Initial revision
*
*/
#include<math.h>
#include<stdio.h>
#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 "viewmol.h"
#include "dialog.h"

void unitcellExit(Widget, caddr_t, XmPushButtonCallbackStruct *);
void setCellSliders(struct MOLECULE *);
void makeNewCell(Widget, struct SLIDER *, XmScrollBarCallbackStruct *);
void makeMillerPlane(Widget, struct SLIDER *, XmScrollBarCallbackStruct *);

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

extern struct WINDOW windows[];
extern struct MOLECULE *molecules;
extern Widget topShell;
extern int showUnitCell, iwavef;

static Widget dialog, millerButton, cellWidgets[3], millerWidgets[3];
static struct MOLECULE *mol;
static int showUnitCell_save, showMiller_save;
static int miller_save[3];
static double cellFactor_save[3], miller[3];

void unitcellDialog(Widget widget, caddr_t dummy, XmAnyCallbackStruct *data)
{
  Widget form, form1, board, togglebox, sep;
  short decimals;
  static struct SLIDER cellSliders[3], millerSliders[3];
  static struct PushButtonRow checkbox_button[] = {{"visible", changeBoolean,
                                                    (XtPointer)&showUnitCell, NULL},
                                                   {"miller", changeBoolean,
                                                    (XtPointer)NULL, NULL}};
  static struct PushButtonRow buttons[] = {
    { "ok", unitcellExit, (XtPointer)TRUE, NULL },
    { "cancel", unitcellExit, (XtPointer)FALSE, NULL },
  };
  char line[]=" value";
  register int i;

  /* This function creates the dialog for the "Unit cell" option */

  millerPlane();
  if (windows[VIEWER].set < 0)
    mol=&molecules[0];
  else
    mol=&molecules[windows[VIEWER].set];
  setMenuItem(VIEWER_UNITCELL, False);
  showUnitCell_save=showUnitCell;
  showMiller_save=mol->unitcell->showMiller;
  cellFactor_save[0]=mol->unitcell->factor[0];
  cellFactor_save[1]=mol->unitcell->factor[1];
  cellFactor_save[2]=mol->unitcell->factor[2];
  miller_save[0]=mol->unitcell->miller[0];
  miller_save[1]=mol->unitcell->miller[1];
  miller_save[2]=mol->unitcell->miller[2];

  dialog=initShell(windows[VIEWER].widget, "unitcellForm", &board,
                   &form);
  checkbox_button[1].client_data=(XtPointer)&(mol->unitcell->showMiller);
  togglebox=CreateToggleBox(form, checkbox_button, XtNumber(checkbox_button),
                            XmHORIZONTAL, 1, False, ((mol->unitcell->showMiller << 1) | showUnitCell));
  millerButton=checkbox_button[1].widget;

  sep=XtVaCreateManagedWidget("sep", xmSeparatorWidgetClass, form,
                              NULL);
  form1=XtVaCreateWidget("rowcolumn", xmRowColumnWidgetClass, form,
                         XmNorientation, XmHORIZONTAL,
                         XmNpacking, XmPACK_COLUMN,
                         XmNnumColumns, (short)3,
                         NULL);
  for (i=0; i<3; i++)
  {
    line[0]=(char)(97+i);
    cellWidgets[i]=XtVaCreateManagedWidget(line, xmScaleWidgetClass, form1,
                                           XmNorientation, XmHORIZONTAL,
                                           XmNshowValue, True,
                                           XmNsensitive, True,
                                           NULL);
    XtVaGetValues(cellWidgets[i], XmNdecimalPoints, &decimals, NULL);
    XtVaSetValues(cellWidgets[i], XmNvalue, (int)(mol->unitcell->factor[i]*pow(10.0,
                  (double)decimals)), NULL);
    cellSliders[i].number=&(mol->unitcell->factor[i]);
    cellSliders[i].decimals=decimals;
    cellSliders[i].draw=(void (*)())drawMolecule;
    XtAddCallback(cellWidgets[i], XmNvalueChangedCallback, (XtCallbackProc)makeNewCell,
                  &cellSliders[i]);

    line[0]=(char)(104+i);
    if (i > 0) line[0]+=2;
    millerWidgets[i]=XtVaCreateManagedWidget(line, xmScaleWidgetClass, form1,
                                             XmNorientation, XmHORIZONTAL,
                                             XmNshowValue, True,
                                             XmNsensitive, True,
                                             XmNdecimalPoints, 0,
                                             XmNvalue, mol->unitcell->miller[i],
                                             NULL);
    miller[i]=(double)(mol->unitcell->miller[i]);
    millerSliders[i].number=&miller[i];
    millerSliders[i].decimals=0;
    millerSliders[i].draw=(void (*)())drawMolecule;
    XtAddCallback(millerWidgets[i], XmNvalueChangedCallback, (XtCallbackProc)makeMillerPlane,
                  &millerSliders[i]);
  }
  XtManageChild(form1);

  sep=XtVaCreateManagedWidget("sep", xmSeparatorWidgetClass, form,
                              NULL);

  CreatePushButtonRow(form, buttons, XtNumber(buttons));
  XtAddCallback(dialog, XmNpopupCallback, (XtCallbackProc)MapBox,
                (XmAnyCallbackStruct *)NULL);
  XtManageChild(form);
  XtManageChild(board);
}

void unitcellExit(Widget button, caddr_t which,
                  XmPushButtonCallbackStruct *data)
{
  XtDestroyWidget(dialog);
  dialog=NULL;
  if (!(int)which)
  {
    showUnitCell=showUnitCell_save;
    mol->unitcell->showMiller=showMiller_save;
    if (mol->unitcell->factor[0] != cellFactor_save[0] ||
        mol->unitcell->factor[1] != cellFactor_save[1] ||
        mol->unitcell->factor[2] != cellFactor_save[2])
    {
      mol->unitcell->factor[0]=cellFactor_save[0];
      mol->unitcell->factor[1]=cellFactor_save[1];
      mol->unitcell->factor[2]=cellFactor_save[2];
      expandCell(TRUE, TRUE);
    }
    mol->unitcell->miller[0]=miller_save[0];
    mol->unitcell->miller[1]=miller_save[1];
    mol->unitcell->miller[2]=miller_save[2];
    redraw(VIEWER);
  }
  setMenuItem(VIEWER_UNITCELL, True);
}

void setCellSliders(struct MOLECULE *mol)
{
  short decimals;
  register int i;

  if (dialog)
  {
    for (i=0; i<3; i++)
    {
      XtVaGetValues(cellWidgets[i], XmNdecimalPoints, &decimals, NULL);
      XtVaSetValues(cellWidgets[i], XmNvalue, (int)(mol->unitcell->factor[i]*pow(10.0,
                    (double)decimals)), NULL);
    }
  }
}

void makeNewCell(Widget w, struct SLIDER *slider, XmScrollBarCallbackStruct *data)
{
  GetSlider(w, slider, data);
  expandCell(TRUE, TRUE);
  redraw(VIEWER);
}

void makeMillerPlane(Widget w, struct SLIDER *slider, XmScrollBarCallbackStruct *data)
{
  static int save=(-1);

  GetSlider(w, slider, data);
  mol->unitcell->miller[0]=(int)(miller[0]);
  mol->unitcell->miller[1]=(int)(miller[1]);
  mol->unitcell->miller[2]=(int)(miller[2]);
  if (mol->unitcell->miller[0] == 0 && mol->unitcell->miller[1] == 0 && mol->unitcell->miller[2] == 0)
  {
    save=mol->unitcell->showMiller;
    mol->unitcell->showMiller=FALSE;
    XtVaSetValues(millerButton, XmNsensitive, False,
                                XmNset, False,
                                NULL);
  }
  else
  {
    if (save != -1) mol->unitcell->showMiller=save;
    XtVaSetValues(millerButton, XmNsensitive, True, NULL);
    if (save == TRUE)
      XtVaSetValues(millerButton, XmNset, True, NULL);
    if (mol->unitcell->miller[0] != miller_save[0] || mol->unitcell->miller[1] != miller_save[1] ||
        mol->unitcell->miller[2] != miller_save[2]) millerPlane();
  }
  redraw(VIEWER);
}
