/****************************************************************************/
/*                                                                          */
/*  VolVis is a volume visualization system for investigating, manipulating */
/*  and rendering geometric and volumetric data.                            */
/*                                                                          */
/*  Copyright (C) 1993 by the Research Foundation of the State University   */
/*                            of New York                                   */
/*                                                                          */
/*  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 1, 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.               */
/*                                                                          */
/*  For information on VolVis, contact us at:                               */
/*                                                                          */
/*                volvis@cs.sunysb.edu                         (email)      */
/*                                                                          */
/*                Lisa Sobierajski & Ricardo Avila             (US Mail)    */
/*                Department of Computer Science                            */
/*                State University of New York at Stony Brook               */
/*                Stony Brook, New York  11794-4400                         */
/*                                                                          */
/****************************************************************************/




/*
 *			File: MOTIF_oco_ui.c
 *		      Author: Lisa Sobierajski 
 *			Date: 03/07/92
 *		 Description: Motif Windowing Routines Of The Object Properties 
 *	Modification History:
 *
 *		Who?		When?		Why?
 *	--------------------------------------------------------------------
 *
 */

#include <stdio.h>
#include <math.h>
#include <Xm/Xm.h>
#include <Xm/RowColumn.h>
#include <X11/StringDefs.h>
#include <Xm/PushB.h>
#include <Xm/PushBG.h>
#include <Xm/BulletinB.h>
#include <Xm/LabelG.h>
#include <Xm/Text.h>
#include <Xm/TextF.h>
#include <Xm/DrawingA.h>
#include <Xm/Frame.h>
#include <Xm/Scale.h>

#include "C_volvis.h"
#include "MOTIF_windefs.h"
#include "C_help.h"
#include "C_oco.h"


/* Global Variables For Motif Windowing */
extern Widget		vv_toplevel;	/* Bulletin Board Dialog */
extern Widget		oco_bbdialog;	/* Bulletin Board Dialog */
extern C_WindowDefs	window_defs;


C_ObjectControlInfo	oco_info;

create_oco_window()
{
	extern void	oco_display_callback();
	extern void	close_callback();
	extern void	help_callback();
	extern void	oco_control_callback();
	extern void	oco_create_callback();
	extern void	oco_modify_callback();
	
	extern C_World	world;

	void		oco_active_opt_callback();
	void		oco_delete_callback();
	void		oco_clone_callback();

	Arg		args[20];	/* Argument List */
	int		n;		/* Argument Count */
	Widget		frame;
	Widget		rowcolumn;
	Widget		rc;
	Widget		button;
	XmString	string;
	int		i;

	/********************************************************/		
	/* 		Do Some Initialization 			*/
	/********************************************************/		

	for (i = 0; i < C_MAX_VOLUMES; i++)
		oco_info.volume_info[i] = NULL;

	for (i = 0; i < C_MAX_LIGHTS; i++)
		oco_info.light_info[i] = NULL;

	oco_info.world_info.world_displayed	= NULL;
	oco_info.create_window			= NULL;
	oco_info.create_geo_obj_window		= NULL;
	oco_info.create_light_window		= NULL;
	oco_info.control_window 		= NULL;
	oco_info.view_frame			= NULL;
	oco_info.volume_frame			= NULL;
	oco_info.light_frame			= NULL;
	oco_info.button_frame			= NULL;

	oco_info.active_object = 0;

	/********************************************************/		
	/* Create The Object Properties Bulletin Board		*/
	/********************************************************/		
	n=0;
	XtSetArg( args[n], XmNx, 0 ); n++;
	XtSetArg( args[n], XmNy, 0 ); n++;
	XtSetArg( args[n], XmNnoResize, False ); n++;
	XtSetArg( args[n], XmNautoUnmanage, False ); n++;
	XtSetArg( args[n], XmNtitle, "Object Control" ); n++;
	C_Set_Color_Dialog( args, n, window_defs );
	oco_bbdialog = XmCreateBulletinBoardDialog( vv_toplevel,
		       "Object Properties", args, n );

	n = 0;
	XtSetArg( args[n], XmNx, 0 ); n++;
	XtSetArg( args[n], XmNy, 0 ); n++;
	C_Set_Color_Frame( args, n, window_defs );
	frame = XmCreateFrame( oco_bbdialog, "frame", args, n );
	XtManageChild( frame );

	/********************************************************/		
	/*	Create a RowColumn for Active Object		*/
	/********************************************************/		
        n = 0;
	C_Set_Color_RowColumn( args, n, window_defs );
        rowcolumn = 
		XmCreateRowColumn(frame, "rowcolumn", args, n);
        XtManageChild (rowcolumn);
	
	/********************************************************/		
	/*	Create a Pulldown Selection for Active Object	*/
	/********************************************************/		
        n = 0;
	C_Set_Color_PullDown( args, n, window_defs );
        oco_info.oco_active_pulldown = 
		XmCreatePulldownMenu(rowcolumn, "pulldown", args, n);

        n = 0;
        string = XmStringCreate ("World",
			XmSTRING_DEFAULT_CHARSET);
        XtSetArg (args[n], XmNlabelString, string); n++;
        oco_info.oco_active_opt[0] = 
		XmCreatePushButtonGadget(oco_info.oco_active_pulldown,
			"World", args, n);
        XmStringFree (string);

        XtAddCallback (oco_info.oco_active_opt[0], XmNactivateCallback,
                           oco_active_opt_callback, 0);

        n = 0;
        string = XmStringCreate ("View",
			XmSTRING_DEFAULT_CHARSET);
        XtSetArg (args[n], XmNlabelString, string); n++;
        oco_info.oco_active_opt[1] = 
		XmCreatePushButtonGadget(oco_info.oco_active_pulldown,
			"View", args, n);
        XmStringFree (string);

        XtAddCallback (oco_info.oco_active_opt[1], XmNactivateCallback,
                           oco_active_opt_callback, 1);

        for (i=2; i<world.num_volumes+2; i++)
        {
            n = 0;
            string = XmStringCreate (world.volume[i-2]->volume_name,
			XmSTRING_DEFAULT_CHARSET);
            XtSetArg (args[n], XmNlabelString, string); n++;
            oco_info.oco_active_opt[i] = 
		XmCreatePushButtonGadget(oco_info.oco_active_pulldown,
			world.volume[i-2]->volume_name, args, n);
            XmStringFree (string);

            XtAddCallback (oco_info.oco_active_opt[i], XmNactivateCallback,
                           oco_active_opt_callback, i);

        }

        for (i=world.num_volumes+2; i<world.num_volumes+world.num_lights+2; i++)
        {
            n = 0;
            string = XmStringCreate(
			world.light[i-(world.num_volumes+2)]->light_name,
			XmSTRING_DEFAULT_CHARSET);
            XtSetArg (args[n], XmNlabelString, string); n++;
            oco_info.oco_active_opt[i] = 
		XmCreatePushButtonGadget(oco_info.oco_active_pulldown,
			world.light[i-(world.num_volumes+2)]->light_name, 
			args, n);
            XmStringFree (string);

            XtAddCallback (oco_info.oco_active_opt[i], XmNactivateCallback,
                           oco_active_opt_callback, i);

        }

        XtManageChildren (oco_info.oco_active_opt, i);

	oco_info.num_active_options = i;

	/********************************************************/		
	/*	Create An Option Menu, And Attach The Pulldown	*/
	/********************************************************/		

        n = 0;
        string = XmStringCreate ("Active Object:", 
				     XmSTRING_DEFAULT_CHARSET);
        XtSetArg (args[n], XmNlabelString, string); n++;
        XtSetArg (args[n], XmNsubMenuId, oco_info.oco_active_pulldown); n++;
	C_Set_Color_OptionMenu( args, n, window_defs );
	XtSetArg( args[n], XmNmenuHistory,
                          oco_info.oco_active_opt[oco_info.active_object]); n++;
        oco_info.oco_option_menu = XmCreateOptionMenu(rowcolumn, 
				"oco_option_menu", args, n);

        XtManageChild(oco_info.oco_option_menu);


	/********************************************************/		
	/*	Create a RowColumn for Modify, Clone and Delete	*/
	/********************************************************/		
        n = 0;
	XtSetArg( args[n], XmNorientation, XmHORIZONTAL ); n++;
	C_Set_Color_RowColumn( args, n, window_defs );
        rc = 
		XmCreateRowColumn(rowcolumn, "rc", args, n);
        XtManageChild (rc);
	
	/************************************************/
	/*     Create The Modify  Button		*/
	/************************************************/
	n=0;
	C_Set_Color_Button( args, n, window_defs );
	button = XtCreateManagedWidget( "Modify", 
		xmPushButtonWidgetClass, rc, args, n );
	XtAddCallback( button, XmNactivateCallback,
		       oco_modify_callback, NULL );

	
	/************************************************/
	/*     Create The Clone  Button			*/
	/************************************************/
	n=0;
	C_Set_Color_Button( args, n, window_defs );
	XtSetArg( args[n], XmNsensitive, False ); n++;
	oco_info.clone_button = XtCreateManagedWidget( "Clone ", 
		xmPushButtonWidgetClass, rc, args, n );
	XtAddCallback( oco_info.clone_button, XmNactivateCallback,
		       oco_clone_callback, NULL );


	/************************************************/
	/*     Create The Delete  Button		*/
	/************************************************/
	n=0;
	C_Set_Color_Button( args, n, window_defs );
	XtSetArg( args[n], XmNsensitive, False ); n++;
	oco_info.delete_button = XtCreateManagedWidget( "Delete ", 
		xmPushButtonWidgetClass, rc, args, n );
	XtAddCallback( oco_info.delete_button, XmNactivateCallback,
		       oco_delete_callback, NULL );

	n = 0;
	XtSetArg( args[n], XmNx, 0 ); n++;
	XtSetArg( args[n], XmNy, 120 ); n++;
	C_Set_Color_Frame( args, n, window_defs );
	frame = XmCreateFrame( oco_bbdialog, "frame", args, n );
	XtManageChild( frame );

	/********************************************************/		
	/*	Create a RowColumn for Create and Control	*/
	/********************************************************/		
        n = 0;
	XtSetArg( args[n], XmNorientation, XmHORIZONTAL ); n++;
	C_Set_Color_RowColumn( args, n, window_defs );
        rowcolumn = 
		XmCreateRowColumn(frame, "rowcolumn", args, n);
        XtManageChild (rowcolumn);
	
	/************************************************/
	/*     Create The Create Button			*/
	/************************************************/
	n=0;
	C_Set_Color_Button( args, n, window_defs );
	button = XtCreateManagedWidget( "Create", 
		xmPushButtonWidgetClass, rowcolumn, args, n );
	XtAddCallback( button, XmNactivateCallback,
		       oco_create_callback, NULL );

	/************************************************/
	/*     Create The Control Button		*/
	/************************************************/
	n=0;
	C_Set_Color_Button( args, n, window_defs );
	button = XtCreateManagedWidget( "Control", 
		xmPushButtonWidgetClass, rowcolumn, args, n );
	XtAddCallback( button, XmNactivateCallback,
		       oco_control_callback, NULL );

	n = 0;
	XtSetArg( args[n], XmNx, 0 ); n++;
	XtSetArg( args[n], XmNy, 220 ); n++;
	C_Set_Color_Frame( args, n, window_defs );
	frame = XmCreateFrame( oco_bbdialog, "frame", args, n );
	XtManageChild( frame );

	/********************************************************/		
	/*	Create a RowColumn for Close and Help		*/
	/********************************************************/		
        n = 0;
	XtSetArg( args[n], XmNorientation, XmHORIZONTAL ); n++;
	C_Set_Color_RowColumn( args, n, window_defs );
        rowcolumn = 
		XmCreateRowColumn(frame, "rowcolumn", args, n);
        XtManageChild (rowcolumn);
	
	/************************************************/
	/*     Create The Close Button			*/
	/************************************************/
	n=0;
	XtSetArg( args[n], XmNx, 10 ); n++;
	XtSetArg( args[n], XmNy, 60 ); n++;
	C_Set_Color_Button( args, n, window_defs );
	button = XtCreateManagedWidget( " Close ", 
		xmPushButtonWidgetClass, rowcolumn, args, n );
	XtAddCallback( button, XmNactivateCallback,
		       close_callback, oco_bbdialog );

	/************************************************/
	/*     Create The Help Button			*/
	/************************************************/
	n=0;
	XtSetArg( args[n], XmNx, 110 ); n++;
	XtSetArg( args[n], XmNy, 60 ); n++;
	C_Set_Color_Button( args, n, window_defs );
	button = XtCreateManagedWidget( " Help  ", 
		xmPushButtonWidgetClass, rowcolumn, args, n );
	XtAddCallback( button, XmNactivateCallback,
		       help_callback, C_OCO_HELP );

}

void oco_active_opt_callback( w, active_object_index, call_data )
Widget          w;
int             active_object_index;
XtPointer       call_data;
{
	Arg	args[1];

	if ( oco_info.active_object <= 1 && active_object_index > 1 )
	{ 
		XtSetArg( args[0], XmNsensitive, True );
		XtSetValues( oco_info.delete_button, args, 1 );
		XtSetValues( oco_info.clone_button, args, 1 );
	}
	else if ( oco_info.active_object > 1 && active_object_index <= 1 )
	{
		XtSetArg( args[0], XmNsensitive, False );
		XtSetValues( oco_info.delete_button, args, 1 );
		XtSetValues( oco_info.clone_button, args, 1 );
	}
	    
	oco_info.active_object = active_object_index;
}


void update_oco_active_opt()
{
	extern C_World	world;

	Arg		args[10];	/* Argument List */
	int		n;		/* Argument Count */
	int		loop;
	XmString	oco_string;
	int		i;

	if (oco_bbdialog)
	{	
	    for (loop=2; loop < oco_info.num_active_options; loop++)
	    {
	    		XtDestroyWidget( oco_info.oco_active_opt[loop] ); 	
	    }

            for (i=2; i<world.num_volumes+2; i++)
            {
              n = 0;
              oco_string= XmStringCreate(world.volume[i-2]->volume_name,
			XmSTRING_DEFAULT_CHARSET);
              XtSetArg (args[n], XmNlabelString, oco_string); n++;
              oco_info.oco_active_opt[i] = 
		XmCreatePushButtonGadget(oco_info.oco_active_pulldown,
			world.volume[i-2]->volume_name, args, n);
              XmStringFree (oco_string);

              XtManageChild( oco_info.oco_active_opt[i] );


              XtAddCallback (oco_info.oco_active_opt[i], XmNactivateCallback,
                           oco_active_opt_callback, i);

            }

            for (i=world.num_volumes+2; 
		 i<world.num_volumes+world.num_lights+2; i++)
            {
              n = 0;
              oco_string= XmStringCreate(
			world.light[i-(world.num_volumes+2)]->light_name,
			XmSTRING_DEFAULT_CHARSET);
              XtSetArg (args[n], XmNlabelString, oco_string); n++;
              oco_info.oco_active_opt[i] = 
		XmCreatePushButtonGadget(oco_info.oco_active_pulldown,
			world.light[i-(world.num_volumes+2)]->light_name, 
			args, n);
              XmStringFree (oco_string);

              XtManageChild( oco_info.oco_active_opt[i] );

              XtAddCallback (oco_info.oco_active_opt[i], XmNactivateCallback,
                           oco_active_opt_callback, i);

            }

	    oco_info.num_active_options = i;

	    n = 0;
	    XtSetArg( args[n], XmNmenuHistory,
		      oco_info.oco_active_opt[oco_info.active_object] ); n++;
	    XtSetArg (args[n], XmNsubMenuId, oco_info.oco_active_pulldown); n++;
	    XtSetValues( oco_info.oco_option_menu, args, n );

	    if ( oco_info.active_object <= 1  )
	    {
		XtSetArg( args[0], XmNsensitive, False );
		XtSetValues( oco_info.delete_button, args, 1 );
		XtSetValues( oco_info.clone_button, args, 1 );
	    }

	}

}

void oco_clone_callback( w, client_data, call_data )
Widget		w;
XtPointer	client_data;
XtPointer	call_data;
{
	extern int	C_clone_volume();
	extern int	C_clone_light();

	extern C_World  world;

	int		object;


	object = oco_info.active_object - 2;

	if ( object >= 0 && 
	     object < world.num_volumes )
	{
	    C_clone_volume( world.volume[object] );
	}
	else
	{
		object -= world.num_volumes;
		if ( object >= 0 && object < world.num_lights )
		{
printf("cloning\n");
			C_clone_light( world.light[object] );
		}
	}
}

void oco_delete_callback( w, client_data, call_data )
Widget		w;
XtPointer	client_data;
XtPointer	call_data;
{
	extern	void		C_delete_volume();
	extern  void		C_update_system();

	extern  C_World		world;

	void			oco_destroy_modify_volume_windows();
	void			oco_destroy_modify_light_windows();

	int			loop;
	OcoVolumeInfo		*vinfo;
	int			object;

	object = oco_info.active_object - 2;
	oco_info.active_object = 0;

	if ( object >= 0 && 
	     object < world.num_volumes )
	{

	  oco_destroy_modify_volume_windows( object );
		
	  for (loop=object; loop<world.num_volumes-1; loop++)
		oco_info.volume_info[loop] = oco_info.volume_info[loop+1];

	  C_delete_volume( &world, 
		   world.volume[object]->volume_name ); 
	}
	else 
	{
	  object -= world.num_volumes;

	  if (object >= 0 && object < world.num_lights )
	  {
	      oco_destroy_modify_light_windows( object );

	      for (loop=object; loop<world.num_lights-1; loop++)
		  oco_info.light_info[loop] = oco_info.light_info[loop+1];
	
	      C_delete_light( &world, world.light[object]->light_name );
	  }
	}
}

void oco_destroy_modify_volume_windows( volume_num )
int		volume_num;
{
	extern	void		C_delete_volume();
	extern  void		C_update_system();

	extern  C_World		world;

	int			loop;
	OcoVolumeInfo		*vinfo;

	if ( oco_info.volume_info[volume_num] )
	{
	    vinfo = oco_info.volume_info[volume_num];
	    
	    XtDestroyWidget( vinfo->volume_displayed );
	    vinfo->volume_displayed = NULL;
	

	    if ( vinfo->data.volume_data_displayed  )
	    {
		XtDestroyWidget( vinfo->data.volume_data_displayed );
		vinfo->data.volume_data_displayed = NULL;

		if ( vinfo->data.volume_x_slices )
	 	{
		    XtDestroyWidget( vinfo->data.volume_x_slices );
	 	    vinfo->data.volume_x_slices = NULL;
		}

		if ( vinfo->data.volume_y_slices )
		{
		    XtDestroyWidget( vinfo->data.volume_y_slices );
	 	    vinfo->data.volume_y_slices = NULL;
		}

		if ( vinfo->data.volume_z_slices )
		{
		    XtDestroyWidget( vinfo->data.volume_z_slices );
	 	    vinfo->data.volume_z_slices = NULL;
		}
	    }

	    if ( vinfo->color.volume_color_displayed )
	    {
		XtDestroyWidget( vinfo->color.volume_color_displayed );
		vinfo->color.volume_color_displayed = NULL;

		if ( vinfo->color.volume_color_selector )
		{
			free( vinfo->color.volume_color_selector );
			vinfo->color.volume_color_selector = NULL;
		}
	    }

	    if ( vinfo->shade.volume_shade_change )
	    {
		XtDestroyWidget( vinfo->shade.volume_shade_change );
		vinfo->shade.volume_shade_change = NULL;
	    }

	    free( vinfo ); 

	}
		
	oco_info.volume_info[volume_num] = NULL;


}

void oco_destroy_modify_light_windows( light_num )
int	light_num;
{
	extern	void		C_delete_volume();
	extern  void		C_update_system();

	extern  C_World		world;

	int			loop;
	OcoVolumeInfo		*vinfo;
	int			object;

	if ( oco_info.light_info[light_num] )
	{
	    if ( oco_info.light_info[light_num]->light_color_selector )
	    {
	      free( oco_info.light_info[light_num]->light_color_selector );
	      oco_info.light_info[light_num]->light_color_selector = NULL;
	    }

	    if ( oco_info.light_info[light_num]->light_displayed )
	    {
	      XtDestroyWidget(oco_info.light_info[light_num]->light_displayed);
	      oco_info.light_info[light_num]->light_displayed = NULL;
	    }
	}
	
	oco_info.light_info[light_num] = NULL;
}

void oco_destroy_all_modify_windows()
{
	void			oco_destroy_volume_modify_windows();
	void			oco_destroy_light_modify_windows();

	int	loop;

	for (loop = 0; loop < C_MAX_VOLUMES; loop++)
		oco_destroy_modify_volume_windows( loop );

	for (loop = 0; loop < C_MAX_LIGHTS; loop++)
		oco_destroy_modify_light_windows( loop );

	oco_info.active_object = 0;
}

void oco_update_all_modify_windows()
{

	extern void oco_reset_volume_properties();
	extern void oco_cancel_volume_shade();
	extern void oco_reset_volume_color();
	extern void oco_reset_data_props();
	extern void oco_reset_old_light();

	extern  C_World		world;

	int	loop;

	for (loop = 0; loop < world.num_volumes; loop++)
	{
	    if ( oco_info.volume_info[loop] )
	    {
		oco_reset_volume_properties( 
		    oco_info.volume_info[loop]->volume_displayed, loop, NULL );

		if ( oco_info.volume_info[loop]->shade.volume_shade_change )
		    oco_cancel_volume_shade( 
			oco_info.volume_info[loop]->shade.volume_shade_change,
			loop, NULL );

		if ( oco_info.volume_info[loop]->color.volume_color_displayed )
		    oco_reset_volume_color( 
		      oco_info.volume_info[loop]->color.volume_color_displayed,
		      loop, NULL );

		if ( oco_info.volume_info[loop]->data.volume_data_displayed )
		    oco_reset_data_props( 
		      oco_info.volume_info[loop]->data.volume_data_displayed,
		      oco_info.volume_info[loop]->data.seg_info, NULL );
	    }
	}

	for (loop = 0; loop < world.num_lights; loop++)
	{
	    if ( oco_info.light_info[loop] )
	    {
		if ( oco_info.light_info[loop]->light_displayed )
		    oco_reset_old_light( 
		       oco_info.light_info[loop]->light_displayed, loop, NULL );	
	    }
	}

	if ( oco_info.world_info.world_displayed )
	{
		oco_reset_bkgrnd_color( oco_info.world_info.world_displayed,
			oco_info.world_info.background_info, NULL );
		oco_reset_ambient_color( oco_info.world_info.world_displayed,
			oco_info.world_info.ambient_info, NULL );
		oco_reset_ambient_coef( oco_info.world_info.ambient_slider,
			oco_info.world_info.ambient_slider, NULL );
	}
}
