/* Copyright (C) 2000 Damir Zucic */

/*=============================================================================

				control_click.c

Purpose:
	Handle ButtonPress event which came from control window.

Input:
	(1) Pointer to MolComplexS structure, with macromol. complexes.
	(2) Number of macromolecular complexes.
	(3) Pointer to RuntimeS structure.
	(4) Pointer to ConfigS structure, with configuration data.
	(5) Pointer to GUIS structure, with GUI data.
	(6) Pointer to NearestAtomS structure.
	(7) The number of pixels in the main window free area.
	(8) Pointer to refreshI.
	(9) Pointer to XButtonEvent structure.

Output:
	(1) The click may cause rotation,  translation,  slab change or
	    fading change.
	(2) Return value.

Return value:
	(1) Positive if some transformation is done.
	(2) Zero if click is ignored (no button pressed).

Notes:
	(1) Indices are assigned as follows:
             0 = KP_0
             1 = KP_1
             2 = KP_2
             3 = KP_3
             4 = KP_4
             5 = KP_5
             6 = KP_6
             7 = KP_7
             8 = KP_8
             9 = KP_9
            10 = KP_Decimal
            11 = KP_Enter
            12 = KP_Add
            13 = KP_Subtract
            14 = KP_Multiply
            15 = KP_Divide
            16 = F1
            17 = F2
            18 = F3
            19 = F4

========includes:============================================================*/

#include <stdio.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>

#include "defines.h"
#include "typedefs.h"

/*======function prototypes:=================================================*/

int		IdentifyButton_ (XButtonEvent *, GUIS *);
size_t		MainRefresh_ (MolComplexS *, int,
			      RuntimeS *, ConfigS *, GUIS *,
			      NearestAtomS *, size_t, unsigned int);
int		ControlRefresh_ (MolComplexS *, ConfigS *, GUIS *);
int		DockingRefresh_ (RuntimeS *, GUIS *);
double		TranslationShift_ (ConfigS *, GUIS *, double);
void		Translate_ (MolComplexS *, int,
			    RuntimeS *, ConfigS *, double, int);
double		RotationAngle_ (ConfigS *, GUIS *, double);
int		Rotate_ (MolComplexS *, int,
			 RuntimeS *, ConfigS *, double, int);
double		SlabShift_ (ConfigS *, GUIS *, double);
void		MoveBackSlab_ (MolComplexS *, int, ConfigS *, double);
void		MoveFrontSlab_ (MolComplexS *, int, ConfigS *, double);
double		FadingShift_ (ConfigS *, GUIS *, double);
void		MoveBackFading_ (MolComplexS *, int, ConfigS *, double);
void		MoveFrontFading_ (MolComplexS *, int, ConfigS *, double);

/*======handle ButtonPress from control window:==============================*/

int ControlClick_ (MolComplexS *mol_complexSP, int mol_complexesN,
		   RuntimeS *runtimeSP, ConfigS *configSP, GUIS *guiSP,
		   NearestAtomS *nearest_atomSP, size_t pixelsN,
		   unsigned int *refreshIP,
		   XButtonEvent *button_eventSP)
{
int		buttonI;
double		shift;
double		rotation_angle;

/* Identify dummy button which was pressed: */
buttonI = IdentifyButton_ (button_eventSP, guiSP);

/* Hit or miss: */
if (buttonI < 0) return 0;

/* Apply the requested transformation: */
switch (buttonI)
	{
	/* Translation along z, negative shift: */
	case 0:
		(*refreshIP)++;
		shift = TranslationShift_ (configSP, guiSP, -1.0);
		Translate_ (mol_complexSP, mol_complexesN,
			    runtimeSP, configSP, shift, 3);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		if (guiSP->dockingF) DockingRefresh_ (runtimeSP, guiSP);
		break;

	/* Move back slab surface along z, positive shift: */
	case 1:
		(*refreshIP)++;
		shift = SlabShift_ (configSP, guiSP, 1.0);
		MoveBackSlab_ (mol_complexSP, mol_complexesN,
			       configSP, shift);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		ControlRefresh_ (mol_complexSP + runtimeSP->default_complexI,
				 configSP, guiSP);
		break;

	/* Positive rotation around x: */
	case 2:
		(*refreshIP)++;
		rotation_angle = RotationAngle_ (configSP, guiSP, 1.0);
		Rotate_ (mol_complexSP, mol_complexesN,
			 runtimeSP, configSP, rotation_angle, 1);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		ControlRefresh_ (mol_complexSP + runtimeSP->default_complexI,
				 configSP, guiSP);
		if (guiSP->dockingF) DockingRefresh_ (runtimeSP, guiSP);
		break;

	/* Move back slab surface along z, negative shift: */
	case 3:
		(*refreshIP)++;
		shift = SlabShift_ (configSP, guiSP, -1.0);
		MoveBackSlab_ (mol_complexSP, mol_complexesN,
			       configSP, shift);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		ControlRefresh_ (mol_complexSP + runtimeSP->default_complexI,
				 configSP, guiSP);
		break;

	/* Positive rotation around y: */
	case 4:
		(*refreshIP)++;
		rotation_angle = RotationAngle_ (configSP, guiSP, +1.0);
		Rotate_ (mol_complexSP, mol_complexesN,
			 runtimeSP, configSP, rotation_angle, 2);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		ControlRefresh_ (mol_complexSP + runtimeSP->default_complexI,
				 configSP, guiSP);
		if (guiSP->dockingF) DockingRefresh_ (runtimeSP, guiSP);
		break;

	/* Translation along z, positive shift: */
	case 5:
		(*refreshIP)++;
		shift = TranslationShift_ (configSP, guiSP, +1.0);
		Translate_ (mol_complexSP, mol_complexesN,
			    runtimeSP, configSP, shift, 3);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		if (guiSP->dockingF) DockingRefresh_ (runtimeSP, guiSP);
		break;

	/* Negative rotation around y: */
	case 6:
		(*refreshIP)++;
		rotation_angle = RotationAngle_ (configSP, guiSP, -1.0);
		Rotate_ (mol_complexSP, mol_complexesN,
			 runtimeSP, configSP, rotation_angle, 2);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		ControlRefresh_ (mol_complexSP + runtimeSP->default_complexI,
				 configSP, guiSP);
		if (guiSP->dockingF) DockingRefresh_ (runtimeSP, guiSP);
		break;

	/* Negative rotation around z: */
	case 7:
		(*refreshIP)++;
		rotation_angle = RotationAngle_ (configSP, guiSP, -1.0);
		Rotate_ (mol_complexSP, mol_complexesN,
			 runtimeSP, configSP, rotation_angle, 3);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		ControlRefresh_ (mol_complexSP + runtimeSP->default_complexI,
				 configSP, guiSP);
		if (guiSP->dockingF) DockingRefresh_ (runtimeSP, guiSP);
		break;

	/* Negative rotation aroung x: */
	case 8:
		(*refreshIP)++;
		rotation_angle = RotationAngle_ (configSP, guiSP, -1.0);
		Rotate_ (mol_complexSP, mol_complexesN,
			 runtimeSP, configSP, rotation_angle, 1);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		ControlRefresh_ (mol_complexSP + runtimeSP->default_complexI,
				 configSP, guiSP);
		if (guiSP->dockingF) DockingRefresh_ (runtimeSP, guiSP);
		break;

	/* Positive rotation around z: */
	case 9:
		(*refreshIP)++;
		rotation_angle = RotationAngle_ (configSP, guiSP, +1.0);
		Rotate_ (mol_complexSP, mol_complexesN,
			 runtimeSP, configSP, rotation_angle, 3);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		ControlRefresh_ (mol_complexSP + runtimeSP->default_complexI,
				 configSP, guiSP);
		if (guiSP->dockingF) DockingRefresh_ (runtimeSP, guiSP);
		break;

	/* Move front slab surface along z, positive shift: */
	case 10:
		(*refreshIP)++;
		shift = SlabShift_ (configSP, guiSP, 1.0);
		MoveFrontSlab_ (mol_complexSP, mol_complexesN,
				configSP, shift);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		ControlRefresh_ (mol_complexSP + runtimeSP->default_complexI,
				 configSP, guiSP);
		break;

	/* Move front slab surface along z, negative shift: */
	case 11:
		(*refreshIP)++;
		shift = SlabShift_ (configSP, guiSP, -1.0);
		MoveFrontSlab_ (mol_complexSP, mol_complexesN,
				configSP, shift);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		ControlRefresh_ (mol_complexSP + runtimeSP->default_complexI,
				 configSP, guiSP);
		break;

	/* Translation along y, positive shift: */
	case 12:
		(*refreshIP)++;
		shift = TranslationShift_ (configSP, guiSP, +1.0);
		Translate_ (mol_complexSP, mol_complexesN,
			    runtimeSP, configSP, shift, 2);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		if (guiSP->dockingF) DockingRefresh_ (runtimeSP, guiSP);
		break;

	/* Translation along y, negative shift: */
	case 13:
		(*refreshIP)++;
		shift = TranslationShift_ (configSP, guiSP, -1.0);
		Translate_ (mol_complexSP, mol_complexesN,
			    runtimeSP, configSP, shift, 2);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		if (guiSP->dockingF) DockingRefresh_ (runtimeSP, guiSP);
		break;

	/* Translation along x, positive shift: */
	case 14:
		(*refreshIP)++;
		shift = TranslationShift_ (configSP, guiSP, +1.0);
		Translate_ (mol_complexSP, mol_complexesN,
			    runtimeSP, configSP, shift, 1);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		if (guiSP->dockingF) DockingRefresh_ (runtimeSP, guiSP);
		break;

	/* Translation along x, negative shift: */
	case 15:
		(*refreshIP)++;
		shift = TranslationShift_ (configSP, guiSP, -1.0);
		Translate_ (mol_complexSP, mol_complexesN,
			    runtimeSP, configSP, shift, 1);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		if (guiSP->dockingF) DockingRefresh_ (runtimeSP, guiSP);
		break;

	/* Move back fading surface, positive shift: */
	case 16:
		(*refreshIP)++;
		shift = FadingShift_ (configSP, guiSP, 1.0);
		MoveBackFading_ (mol_complexSP, mol_complexesN,
				 configSP, shift);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		ControlRefresh_ (mol_complexSP + runtimeSP->default_complexI,
				 configSP, guiSP);
		break;

	/* Move back fading surface, negative shift: */
	case 17:
		(*refreshIP)++;
		shift = FadingShift_ (configSP, guiSP, -1.0);
		MoveBackFading_ (mol_complexSP, mol_complexesN,
				 configSP, shift);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		ControlRefresh_ (mol_complexSP + runtimeSP->default_complexI,
				 configSP, guiSP);
		break;

	/* Move front fading surface, positive shift: */
	case 18:
		(*refreshIP)++;
		shift = FadingShift_ (configSP, guiSP, 1.0);
		MoveFrontFading_ (mol_complexSP, mol_complexesN,
				  configSP, shift);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		ControlRefresh_ (mol_complexSP + runtimeSP->default_complexI,
				 configSP, guiSP);
		break;

	/* Move front fading surface, negative shift: */
	case 19:
		(*refreshIP)++;
		shift = FadingShift_ (configSP, guiSP, -1.0);
		MoveFrontFading_ (mol_complexSP, mol_complexesN,
				  configSP, shift);
		MainRefresh_ (mol_complexSP, mol_complexesN,
			      runtimeSP, configSP, guiSP,
			      nearest_atomSP, pixelsN, *refreshIP);
		ControlRefresh_ (mol_complexSP + runtimeSP->default_complexI,
				 configSP, guiSP);
		break;

	/* Unresolved: */
	default:
		;
	}

/* Return positive value: */
return 1;
}

/*===========================================================================*/


