/*
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Matthew P. Hodges
This file is part of XMakemol.
XMakemol 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, or (at your option)
any later version.
XMakemol 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 XMakemol; see the file COPYING. If not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <Xm/Frame.h>
#include <Xm/Label.h>
#include <Xm/MessageB.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>
#include <Xm/Scale.h>
#include <Xm/Separator.h>
#include <Xm/TextF.h>
#include <Xm/ToggleBG.h>
#include "defs.h"
#include "globals.h"
void echo_to_message_area(char *);
void place_dialog_cb (Widget, XtPointer, XtPointer);
enum perspective_types {PERSPECTIVE_ALL,
PERSPECTIVE_CURRENT};
static enum perspective_types perspective_type = PERSPECTIVE_ALL;
static Widget d_scale, v_scale;
char string[BUFSIZ];
double deg_to_rad=(double)(180.0/PI);
void
cont_cb(Widget widget, XtPointer client_data, XtPointer call_data)
{
void animate(Widget);
void make_frame_dlg(Widget);
void make_pers_dlg(Widget);
void measure(Widget);
int item_no = (int) client_data;
switch(item_no){
case 0:
make_frame_dlg(main_w);
break;
case 1:
animate(main_w);
break;
case 2:
measure(main_w);
break;
case 3:
make_pers_dlg(main_w);
break;
}
}
void
measure(Widget parent)
{
void meas_dlg_cancel_cb(Widget, XtPointer, XtPointer);
void sel_reset_cb(Widget, XtPointer, XtPointer);
void select_atom_cb(Widget, XtPointer, XtPointer);
void update_lengths_dialog(Boolean);
int i,j,k,w,n=0;
static Widget meas_rc[6],meas_frame[4];
Widget sep,select_atom_label_w,select_atom_w,sel_reset_w;
XmString label=XmStringCreateLocalized("Measure");
if(!meas_dialog){
XtSetArg (args[n],XmNdialogTitle, label); n++;
XtSetArg (args[n],XmNautoUnmanage, False); n++;
XtSetArg (args[n],XmNdefaultPosition, False); n++;
meas_dialog=(Widget)XmCreateMessageDialog(parent, "lengths", args, n);
label=XmStringCreateLocalized(" ");
meas_rc[0] = XtVaCreateManagedWidget
("lengths",
xmRowColumnWidgetClass,meas_dialog,
XmNorientation, XmVERTICAL,
NULL);
meas_frame[0] = XtVaCreateManagedWidget
("frame1",
xmFrameWidgetClass, meas_rc[0],
XmNshadowType, XmSHADOW_IN,
NULL);
meas_rc[1] = XtVaCreateManagedWidget
("lengths",
xmRowColumnWidgetClass,meas_frame[0],
XmNorientation, XmVERTICAL,
NULL);
XtVaCreateManagedWidget
("Label X Y Z Type No.",
xmLabelWidgetClass,meas_rc[1],
XmNalignment, XmALIGNMENT_BEGINNING,
NULL);
if(!meas_label_w){
meas_label_w=(Widget *)malloc(15*sizeof(Widget));
}
w=0;
for(i=0;i<4;i++){
meas_label_w[w] = XtVaCreateManagedWidget
("dim",
xmLabelWidgetClass,meas_rc[1],
XmNlabelString, label,
NULL);
w++;
}
meas_rc[2] = XtVaCreateManagedWidget
("lengths",
xmRowColumnWidgetClass,meas_rc[0],
XmNorientation, XmHORIZONTAL,
NULL);
meas_frame[1] = XtVaCreateManagedWidget
("frame1",
xmFrameWidgetClass, meas_rc[2],
XmNshadowType, XmSHADOW_IN,
NULL);
meas_rc[3] = XtVaCreateManagedWidget
("lengths",
xmRowColumnWidgetClass,meas_frame[1],
XmNorientation, XmVERTICAL,
NULL);
XtVaCreateManagedWidget
(" Lengths",
xmLabelWidgetClass,meas_rc[3],
XmNalignment, XmALIGNMENT_BEGINNING,
NULL);
for(i=0;i<3;i++){
for(j=i+1;j<4;j++){
meas_label_w[w] = XtVaCreateManagedWidget
("dim",
xmLabelWidgetClass,meas_rc[3],
XmNlabelString, label,
NULL);
w++;
}
}
meas_rc[4] = XtVaCreateManagedWidget
("lengths",
xmRowColumnWidgetClass,meas_rc[2] ,
XmNorientation, XmVERTICAL,
NULL);
meas_frame[2] = XtVaCreateManagedWidget
("frame1",
xmFrameWidgetClass, meas_rc[4],
XmNshadowType, XmSHADOW_IN,
NULL);
meas_rc[5] = XtVaCreateManagedWidget
("lengths",
xmRowColumnWidgetClass,meas_frame[2] ,
XmNorientation, XmVERTICAL,
NULL);
XtVaCreateManagedWidget
(" Angles",
xmLabelWidgetClass,meas_rc[5],
XmNalignment, XmALIGNMENT_BEGINNING,
NULL);
for(i=0;i<2;i++){
for(j=i+1;j<3;j++){
for(k=j+1;k<4;k++){
meas_label_w[w] = XtVaCreateManagedWidget
("dim",
xmLabelWidgetClass,meas_rc[5],
XmNlabelString, label,
NULL);
w++;
}
}
}
meas_frame[3] = XtVaCreateManagedWidget
("frame1",
xmFrameWidgetClass, meas_rc[4],
XmNshadowType, XmSHADOW_IN,
NULL);
meas_rc[5] = XtVaCreateManagedWidget
("lengths",
xmRowColumnWidgetClass,meas_frame[3] ,
XmNorientation, XmVERTICAL,
NULL);
XtVaCreateManagedWidget
(" Torsion",
xmLabelWidgetClass,meas_rc[5],
XmNalignment, XmALIGNMENT_BEGINNING,
NULL);
meas_label_w[w] = XtVaCreateManagedWidget
("dim",
xmLabelWidgetClass,meas_rc[5],
XmNlabelString, label,
NULL);
XmStringFree(label);
sep=XmCreateSeparator(meas_rc[0],"sep",NULL,0);
XtManageChild(sep);
select_atom_label_w=XtVaCreateManagedWidget
("Select atom:",
xmLabelWidgetClass,meas_rc[0],
XmNalignment, XmALIGNMENT_BEGINNING,
NULL);
select_atom_w=XtVaCreateManagedWidget
("select",xmTextFieldWidgetClass,meas_rc[0], NULL);
XtAddCallback(select_atom_w,XmNactivateCallback,select_atom_cb,NULL);
sep=XmCreateSeparator(meas_rc[0],"sep",NULL,0);
XtManageChild(sep);
sel_reset_w=XtVaCreateManagedWidget
("Unselect all atoms",xmPushButtonWidgetClass,meas_rc[0],NULL);
XtAddCallback(sel_reset_w,XmNactivateCallback,sel_reset_cb,NULL);
/* If the user selects cancel, just destroy the meas_dialog */
XtAddCallback((Widget)meas_dialog, XmNcancelCallback,
meas_dlg_cancel_cb, NULL);
/* XtUnmanageChild
(XmMessageBoxGetChild(meas_dialog,XmDIALOG_OK_BUTTON)); */
/* No help available ... */
XtUnmanageChild
(XmMessageBoxGetChild(meas_dialog,XmDIALOG_HELP_BUTTON));
update_lengths_dialog(True);
}
XtAddCallback (meas_dialog, XmNmapCallback, place_dialog_cb, NULL);
XtManageChild(meas_dialog);
XtPopup(XtParent(meas_dialog), XtGrabNone);
}
void
meas_dlg_cancel_cb(Widget widget, XtPointer client_data, XtPointer call_data)
{
XtDestroyWidget(meas_dialog);
meas_dialog=NULL;
}
double
get_length(int l, int m)
{
double x, y, z, distance;
x = atoms[l].x - atoms[m].x;
y = atoms[l].y - atoms[m].y;
z = atoms[l].z - atoms[m].z;
distance = sqrt ((x * x) + (y * y) + (z * z));
return (distance);
}
double
get_angle(int l, int m, int n)
{
double dot_product(double *, double *);
void normalize_vec(double *);
double a[3],b[3],angle;
/* work out angle */
a[0]=atoms[l].x-atoms[m].x;
a[1]=atoms[l].y-atoms[m].y;
a[2]=atoms[l].z-atoms[m].z;
normalize_vec(a);
b[0]=atoms[n].x-atoms[m].x;
b[1]=atoms[n].y-atoms[m].y;
b[2]=atoms[n].z-atoms[m].z;
normalize_vec(b);
angle=dot_product(a,b);
angle=acos(angle)*deg_to_rad;
return(angle);
}
double
get_torsion(int l, int m, int n, int o)
{
double dot_product(double *, double *);
void normalize_vec(double *);
void vector_product(double *, double *, double *);
double lm[3], mn[3], no[3], p[3], q[3], temp[3], torsion;
/* work out torsion angle:
there are four atoms (l,m,n,o). Two planes are defined - the
first contains atoms l, m and n and the second contains atoms m,
n and o. The angle between these two planes (actually plane
normals) is the torsion angle. Additionally, we need to assign a
sign - the cross product of the two plane normals is either
parallel or antiparallel to the vector between atoms m and n.
Parallel -> +ve torsion angle and antiparallel -> -ve torsion
angle. */
/* The l->m vector */
lm[0] = atoms[m].x - atoms[l].x;
lm[1] = atoms[m].y - atoms[l].y;
lm[2] = atoms[m].z - atoms[l].z;
normalize_vec(lm);
/* The m->n vector */
mn[0] = atoms[n].x - atoms[m].x;
mn[1] = atoms[n].y - atoms[m].y;
mn[2] = atoms[n].z - atoms[m].z;
normalize_vec(mn);
/* The n->o vector */
no[0] = atoms[o].x - atoms[n].x;
no[1] = atoms[o].y - atoms[n].y;
no[2] = atoms[o].z - atoms[n].z;
normalize_vec(no);
/* The plane normal of (l,m,n) */
vector_product(p, lm, mn); /* p = lm x mn */
normalize_vec(p);
/* The plane normal of (m,n,o) */
vector_product(q, mn, no); /* q = mn x no */
normalize_vec(q);
/* The torsion angle is the angle between the two plane normals -
the next step gives cos(torsion) */
torsion = dot_product(p, q);
/* some systems don't like acos(1.0) and return nan0x7fffffff */
if(fabs((torsion - 1.0)) < 1e-10)
{
torsion = 0.0;
}
else
{
torsion = acos(torsion) * deg_to_rad;
}
/* Now determine the sign - determined from mn . (p x q) */
vector_product(temp, p, q); /* temp = p x q */
if(dot_product(mn, temp) < 0.0)
{
torsion *= -1.0; /* Negate */
}
return(torsion);
}
void
make_pers_dlg(Widget parent)
{
void d_scale_cb(Widget, XtPointer, XtPointer);
void depth_on_cb(Widget, XtPointer, XtPointer);
void pers_dlg_cancel_cb(Widget, XtPointer, XtPointer);
void perspective_type_cb (Widget, XtPointer, XtPointer);
void reset_pers_scales(void);
void v_scale_cb(Widget, XtPointer, XtPointer);
int n=0;
Widget depth_on, rc1, radio, button;
XmString title;
if(!pers_dialog){
title=XmStringCreateLocalized("Perspective");
n=0;
XtSetArg (args[n],XmNdialogTitle,title); n++;
XtSetArg (args[n],XmNwidth,300); n++;
pers_dialog=XmCreateMessageDialog(parent,"v_scale",args,n);
rc1=XtVaCreateManagedWidget
("rc1",xmRowColumnWidgetClass,pers_dialog,NULL);
title=XmStringCreateLocalized("Alter scale");
v_scale = XtVaCreateManagedWidget
("v_scale", xmScaleWidgetClass,
rc1,
XmNmaximum, 1000,
XmNminimum, 0,
XmNvalue, 0,
XmNshowValue, True,
XmNorientation, XmHORIZONTAL,
XmNtitleString, title,
NULL);
XtAddCallback(v_scale, XmNdragCallback, v_scale_cb, NULL);
XtAddCallback(v_scale, XmNvalueChangedCallback, v_scale_cb, NULL);
title=XmStringCreateLocalized("Choose depth");
d_scale = XtVaCreateManagedWidget
("d_scale", xmScaleWidgetClass,
rc1,
XmNmaximum, 100,
XmNminimum, 0,
XmNvalue, 1,
XmNshowValue, True,
XmNorientation, XmHORIZONTAL,
XmNtitleString, title,
NULL);
/* This sets the value correctly from the current canvas_scale */
reset_pers_scales();
XmStringFree(title);
XtAddCallback(d_scale, XmNdragCallback, d_scale_cb, NULL);
XtAddCallback(d_scale, XmNvalueChangedCallback, d_scale_cb, NULL);
depth_on=XtVaCreateManagedWidget
("Toggle depth",xmToggleButtonGadgetClass, rc1, NULL);
if(depth_is_on){
XtVaSetValues(depth_on,XmNset,True,NULL);
}
XtAddCallback(depth_on,XmNvalueChangedCallback, depth_on_cb,(XtPointer)1);
XtManageChild (XmCreateSeparator (rc1, "sep", NULL, 0));
radio = XmCreateRadioBox (rc1,
"pers_radio",
NULL,
0);
button = XtVaCreateManagedWidget ("Act on all frames",
xmToggleButtonGadgetClass,
radio,
NULL);
if (perspective_type == PERSPECTIVE_ALL)
{
XtVaSetValues (button, XmNset, True, NULL);
}
XtAddCallback (button,
XmNvalueChangedCallback,
perspective_type_cb,
(XtPointer) PERSPECTIVE_ALL);
button = XtVaCreateManagedWidget ("Act on current frame",
xmToggleButtonGadgetClass,
radio,
NULL);
if (perspective_type == PERSPECTIVE_CURRENT)
{
XtVaSetValues (button, XmNset, True, NULL);
}
XtAddCallback (button,
XmNvalueChangedCallback,
perspective_type_cb,
(XtPointer) PERSPECTIVE_CURRENT);
XtManageChild (radio);
XtAddCallback(pers_dialog, XmNcancelCallback,
pers_dlg_cancel_cb,NULL);
XtUnmanageChild
(XmMessageBoxGetChild(pers_dialog,XmDIALOG_OK_BUTTON));
/* No help available ... */
XtUnmanageChild
(XmMessageBoxGetChild(pers_dialog,XmDIALOG_HELP_BUTTON));
}
XtAddCallback (pers_dialog, XmNmapCallback, place_dialog_cb, NULL);
XtManageChild(pers_dialog);
}
void
pers_dlg_cancel_cb(Widget widget, XtPointer client_data, XtPointer call_data)
{
XtDestroyWidget(pers_dialog);
pers_dialog=NULL;
d_scale = NULL;
v_scale = NULL;
}
void
v_scale_cb(Widget widget, XtPointer client_data, XtPointer call_data)
{
void canvas_cb(Widget, XtPointer, XtPointer);
struct frame * get_selected_frame (void);
void set_canvas_scale (double);
void set_scale_all_frames (int);
double scale;
struct frame *this_frame;
XmScaleCallbackStruct *cbs=
(XmScaleCallbackStruct *)call_data;
int cb_value;
cb_value = cbs->value;
if (no_frames != 0)
{
if (perspective_type == PERSPECTIVE_CURRENT)
{
/* Update current frame */
this_frame = get_selected_frame ();
this_frame->perspective_scale = cb_value;
}
else
{
/* Update all frames */
set_scale_all_frames (cb_value);
}
}
/* cb_value can vary between 0 and 1000 so we can vary the scale
between 0 and 1023 */
scale = pow (2.0, cb_value / 100.0) - 1;
set_canvas_scale (scale);
redraw = 1;
canvas_cb (canvas, NULL, NULL);
}
void
set_scale_all_frames (int value)
{
struct frame * get_first_frame ();
struct frame *this_frame;
this_frame = get_first_frame ();
while (this_frame != NULL)
{
this_frame->perspective_scale = value;
this_frame = this_frame->next;
}
}
void
d_scale_cb (Widget widget,
XtPointer client_data,
XtPointer call_data)
{
void canvas_cb(Widget, XtPointer, XtPointer);
struct frame * get_selected_frame (void);
void set_depth_all_frames (int);
void set_z_depth (double);
struct frame *this_frame;
XmScaleCallbackStruct *cbs=
(XmScaleCallbackStruct *)call_data;
int cb_value;
cb_value = cbs->value;
depth = cb_value;
if (no_frames != 0)
{
if (perspective_type == PERSPECTIVE_CURRENT)
{
/* Update current frame */
this_frame = get_selected_frame ();
this_frame->perspective_depth = cb_value;
}
else
{
/* Update all frames */
set_depth_all_frames (cb_value);
}
}
set_z_depth (depth);
redraw = 1;
canvas_cb (canvas, NULL, NULL);
}
void
set_depth_all_frames (int value)
{
struct frame * get_first_frame ();
struct frame *this_frame;
this_frame = get_first_frame ();
while (this_frame != NULL)
{
this_frame->perspective_depth = value;
this_frame = this_frame->next;
}
}
void
depth_on_cb(Widget widget, XtPointer client_data, XtPointer call_data)
{
void canvas_cb(Widget, XtPointer, XtPointer);
if(depth_is_on==0){
depth_is_on=1;
}else{
depth_is_on=0;
}
redraw=1;
canvas_cb(canvas,NULL,NULL); /* update display */
}
void
perspective_type_cb (Widget widget,
XtPointer client_data,
XtPointer call_data)
{
perspective_type = (enum perspective_types) client_data;
}
void
select_atom_cb(Widget widget, XtPointer client_data, XtPointer call_data)
{
void update_selected(int);
int selected_atom;
char* selected_atom_str,string[100];
XtVaGetValues(widget,XmNvalue,&selected_atom_str,NULL);
if ((strlen (selected_atom_str) == 0) ||
(sscanf (selected_atom_str, "%d", &selected_atom) <= 0))
{
echo_to_message_area("Cannot parse string!");
return;
}
selected_atom--; /* 0..no_atoms-1 */
if((selected_atom>no_atoms-1)||(selected_atom<0)){
echo_to_message_area("Choice of atom out of bounds!");
return;
}else{
update_selected(selected_atom);
sprintf(string,"Atom %d selected",selected_atom+1);
echo_to_message_area(string);
}
}
void
sel_reset_cb(Widget widget, XtPointer client_data, XtPointer call_data)
{
void canvas_cb(Widget, XtPointer, XtPointer);
void update_lengths_dialog(Boolean);
int i;
for(i = 0; i < 4; i++)
{
if(selected[i] != -1)
{
atoms[selected[i]].sel = 0;
selected[i] = -1;
}
}
redraw = 1;
canvas_cb(canvas, NULL, NULL);
update_lengths_dialog(True);
}
void
reset_pers_scales(void)
{
double get_z_depth(void);
double get_canvas_scale(void);
int xm_nint (double);
int v_scale_int, local_z_depth;
v_scale_int = xm_nint (100.0 * log (get_canvas_scale() + 1) / log(2.0));
if(d_scale != NULL)
{
local_z_depth = (int) get_z_depth();
XtVaSetValues(d_scale,
XmNvalue, local_z_depth,
NULL);
}
if(v_scale != NULL)
{
XtVaSetValues(v_scale,
XmNvalue, v_scale_int,
NULL);
}
}
syntax highlighted by Code2HTML, v. 0.9.1