/****************************************************************************/
/*                                                                          */
/*  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"



void oco_display_x_slices_callback( w, volume_index, call_data )
Widget		w;
int		volume_index;
XtPointer	call_data;
{
	extern C_ObjectControlInfo	oco_info;

	void		oco_create_slice_display();
	OcoVolumeInfo	*vinfo;

	vinfo = oco_info.volume_info[ volume_index ];

	if ( vinfo->data.volume_x_slices )
	{
		if ( XtIsManaged( vinfo->data.volume_x_slices))
		    XtUnmanageChild(vinfo->data.volume_x_slices);

		XtManageChild( vinfo->data.volume_x_slices );	
	}
	else
	{
		oco_create_slice_display( volume_index, C_X_AXIS );
	}
}

void oco_display_y_slices_callback( w, volume_index, call_data )
Widget		w;
int		volume_index;
XtPointer	call_data;
{
	extern C_ObjectControlInfo	oco_info;

	void		oco_create_slice_display();

	OcoVolumeInfo	*vinfo;

	vinfo = oco_info.volume_info[ volume_index ];

	if ( vinfo->data.volume_y_slices )
	{
		if ( XtIsManaged( vinfo->data.volume_y_slices))
		    XtUnmanageChild(vinfo->data.volume_y_slices);

		XtManageChild( vinfo->data.volume_y_slices);	
	}
	else
	{
		oco_create_slice_display( volume_index, C_Y_AXIS );
	}
}

void oco_display_z_slices_callback( w, volume_index, call_data )
Widget		w;
int		volume_index;
XtPointer	call_data;
{
	extern C_ObjectControlInfo	oco_info;

	void		oco_create_slice_display();

	OcoVolumeInfo	*vinfo;

	vinfo = oco_info.volume_info[ volume_index ];

	if ( vinfo->data.volume_z_slices )
	{
		if ( XtIsManaged( vinfo->data.volume_z_slices))
		    XtUnmanageChild(vinfo->data.volume_z_slices);

		XtManageChild( vinfo->data.volume_z_slices );	
	}
	else
	{
		oco_create_slice_display( volume_index, C_Z_AXIS );
	}
}

void oco_create_slice_display( volume_index, slice_type )
int		volume_index;
C_AxisType	slice_type;
{

	extern void	close_callback();
	extern void	help_callback();

	extern C_ObjectControlInfo	oco_info;
	extern C_World			world;
	extern C_WindowDefs		window_defs;
	extern Widget			vv_toplevel;

	void				oco_slice_display();

	Arg		args[30];
	int		n;

	Widget		label;
	Widget		slider;
	Widget		frame;
	Widget		rowcolumn;
	Widget		bboard;
	Widget		button;
	Widget		drawing_area;
	Widget		parent_widget;
	XmString	label_string;
	Window		windows[5];
	char		string[30];
	char		slider_string[30];
	C_Volume	*volume;
	OcoVolumeInfo	*vinfo;
	int		width;
	int		height;
	int		slider_limit;
	OcoSliceInfo	*slice_info;

	vinfo = oco_info.volume_info[ volume_index ];
	volume = world.volume[ volume_index ];

	n=0;
        XtSetArg( args[n], XmNautoUnmanage, False ); n++;
        C_Set_Color_Dialog( args, n, window_defs );

	slice_info = C_New( OcoSliceInfo );
	slice_info->axis = slice_type;
	slice_info->volume_num = volume_index;
	
	switch ( slice_type )
	{
	  case C_X_AXIS:
		sprintf( string, "%s X Slices", 
			world.volume[volume_index]->volume_name );
        	label_string = XmStringCreate(string, 
				XmSTRING_DEFAULT_CHARSET );
		XtSetArg( args[n], XmNdialogTitle, label_string ); n++;
        	vinfo->data.volume_x_slices = 
			XmCreateBulletinBoardDialog( 
			vv_toplevel, "xslice", args, n );
		parent_widget = vinfo->data.volume_x_slices;
		width = volume->y_size_voxels;
		height = volume->z_size_voxels;
		slider_limit = volume->x_size_voxels-1;
		sprintf( slider_string, "X slice: ");
		break;

	  case C_Y_AXIS:
		sprintf( string, "%s Y Slices", 
			world.volume[volume_index]->volume_name );
        	label_string = XmStringCreate(string, 
				XmSTRING_DEFAULT_CHARSET );
		XtSetArg( args[n], XmNdialogTitle, label_string ); n++;
        	vinfo->data.volume_y_slices = 
			XmCreateBulletinBoardDialog( 
			vv_toplevel, "yslice", args, n );
		parent_widget = vinfo->data.volume_y_slices;
		width = volume->x_size_voxels;
		height = volume->z_size_voxels;
		slider_limit = volume->y_size_voxels-1;
		sprintf( slider_string, "Y slice: ");
		break;

	  case C_Z_AXIS:
		sprintf( string, "%s Z Slices", 
			world.volume[volume_index]->volume_name );
        	label_string = XmStringCreate(string, 
				XmSTRING_DEFAULT_CHARSET );
		XtSetArg( args[n], XmNdialogTitle, label_string ); n++;
        	vinfo->data.volume_z_slices = 
			XmCreateBulletinBoardDialog( 
			vv_toplevel, "zslice", args, n );
		parent_widget = vinfo->data.volume_z_slices;
		width = volume->x_size_voxels;
		height = volume->y_size_voxels;
		slider_limit = volume->z_size_voxels-1;
		sprintf( slider_string, "Z slice: ");
		break;

	}

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

        n = 0;
	C_Set_Color_Bboard( args, n, window_defs );
	XtSetArg( args[n], XmNwidth, width ); n++;
	XtSetArg( args[n], XmNheight, height ); n++;
        drawing_area = 
		XmCreateDrawingArea(frame, "draw", args, n);
        XtManageChild (drawing_area);

	slice_info->draw_area = drawing_area;

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

        n = 0;
	C_Set_Color_RowColumn( args, n, window_defs );
        bboard = 
		XmCreateBulletinBoard(frame, "bboard", args, n);
        XtManageChild (bboard);

        label_string = XmStringCreate(slider_string, XmSTRING_DEFAULT_CHARSET );
        n=0;
        XtSetArg( args[n], XmNx, 10 ); n++;
        XtSetArg( args[n], XmNy, 25 ); n++;
        XtSetArg( args[n], XmNlabelString, label_string ); n++;
        label = XmCreateLabelGadget( bboard, "label", args, n );
        XtManageChild( label );
        XmStringFree( label_string );
 

        n = 0;
        XtSetArg( args[n], XmNorientation, XmHORIZONTAL ); n++;
        XtSetArg( args[n], XmNminimum, 0 ); n++;
        XtSetArg( args[n], XmNmaximum, slider_limit ); n++;
        XtSetArg( args[n], XmNdecimalPoints, 0 ); n++;
        XtSetArg( args[n], XmNshowValue, TRUE ); n++;
        XtSetArg( args[n], XmNvalue, slider_limit / 2 ); n++; 
        XtSetArg( args[n], XmNscaleMultiple, 1 ); n++;
        XtSetArg( args[n], XmNscaleWidth, 200 ); n++;
        XtSetArg( args[n], XmNx, 80 ); n++;
        XtSetArg( args[n], XmNy, 0 ); n++;
        C_Set_Color_Scale( args, n, window_defs );
        slider = XtCreateManagedWidget("slider",
                        xmScaleWidgetClass, bboard, args, n );

	slice_info->slider = slider;

	XtAddCallback( slider, XmNvalueChangedCallback, oco_slice_display,
		slice_info );
	XtAddCallback( slider, XmNdragCallback, oco_slice_display,
		slice_info );
	XtAddCallback( drawing_area, XmNexposeCallback, oco_slice_display,
		slice_info );
 

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

	/********************************************************/		
	/*	Create a RowColumn for Buttons   		*/
	/********************************************************/		
        n = 0;
	XtSetArg( args[n], XmNorientation, XmHORIZONTAL ); n++;
	C_Set_Color_RowColumn( args, n, window_defs );
        rowcolumn = 
		XmCreateRowColumn(frame, "rowcolumn", args, n);
        XtManageChild (rowcolumn);

	n = 0;
	C_Set_Color_Button( args, n, window_defs );
	button = XtCreateManagedWidget("Close", 
			xmPushButtonWidgetClass, rowcolumn, args, n );
	XtAddCallback( button, XmNactivateCallback, close_callback, 
		       parent_widget );
	n = 0;
	C_Set_Color_Button( args, n, window_defs );
	button = XtCreateManagedWidget("Help", 
			xmPushButtonWidgetClass, rowcolumn, args, n );
	switch ( slice_type )
	{
	  case C_X_AXIS:
		XtAddCallback( button, XmNactivateCallback, help_callback, 
		       	       C_OCO_VOLUME_X_SLICES_HELP );
		break;

	  case C_Y_AXIS:
		XtAddCallback( button, XmNactivateCallback, help_callback, 
		       	       C_OCO_VOLUME_Y_SLICES_HELP );
		break;

	  case C_Z_AXIS:
		XtAddCallback( button, XmNactivateCallback, help_callback, 
		       	       C_OCO_VOLUME_Z_SLICES_HELP );
		break;

	}

 	XtManageChild( parent_widget );

	slice_info->gc = XCreateGC( XtDisplay( drawing_area), 
				   XtWindow( drawing_area ), NULL, 0 );


}

void oco_slice_display( w, slice_info, call_data )
Widget		w;
OcoSliceInfo	*slice_info;
XtPointer	call_data;
{
	extern C_WindowDefs	window_defs;
	extern C_World		world;

	int			slider_val;
	int			width, height;
	C_Volume		*volume;
	XImage			*ximage;
	char			*image_data;
	char			*img_ptr;
	int			byte_mult;
	int		        i, j;
	C_Voxel_8bit		*data_ptr;
	
	XmScaleGetValue( slice_info->slider, &slider_val );

	volume = world.volume[slice_info->volume_num];

	switch ( slice_info->axis )
	{
	  case C_X_AXIS:
		width = volume->y_size_voxels;
		height = volume->z_size_voxels;
		break;
	  case C_Y_AXIS:
		width = volume->x_size_voxels;
		height = volume->z_size_voxels;
		break;
	  case C_Z_AXIS:
		width = volume->x_size_voxels;
		height = volume->y_size_voxels;
		break;
	}

	if ( window_defs.depth == 8 )
		byte_mult = 1;
	else if ( window_defs.depth == 24 )
		byte_mult = 4;

	image_data = (char *)malloc( width*height*sizeof(char)*byte_mult );

	if ( window_defs.depth == 8 )
	{
	  switch ( slice_info->axis )
	  {
	    case C_X_AXIS:
		img_ptr = image_data;
		data_ptr = volume->data.scalar_data_8bit->scalar_data + 
			   slider_val; 

		for ( i=0; i < height; i++ )
		{
		  for ( j=0; j < width; j++ )
		  {
			*(img_ptr++) = window_defs.first_grey_index +
				       (*(data_ptr))/4;
			data_ptr += volume->x_size_voxels;
		   }
		}
		break;
	    case C_Y_AXIS:
		img_ptr = image_data;
		data_ptr = volume->data.scalar_data_8bit->scalar_data + 
			   slider_val * width; 

		for ( i=0; i < height; i++ )
		{
		  for ( j=0; j < width; j++ )
		  {
			*(img_ptr++) = window_defs.first_grey_index +
				       (*(data_ptr++))/4;
		  }
		  data_ptr += (volume->y_size_voxels-1)*volume->x_size_voxels;
		}
		break;
	    case C_Z_AXIS:
		img_ptr = image_data;
		data_ptr = volume->data.scalar_data_8bit->scalar_data + 
			   slider_val * width * height; 

		for ( i=0; i < height; i++ )
		  for ( j=0; j < width; j++ )
		  {
			*(img_ptr++) = window_defs.first_grey_index +
				       (*(data_ptr++))/4;
		   }
		break;
	  }
	}
	else if ( window_defs.depth == 24 )
	{
	  switch ( slice_info->axis )
	  {
	    case C_X_AXIS:
		img_ptr = image_data;
		data_ptr = volume->data.scalar_data_8bit->scalar_data + 
			   slider_val; 

		for ( i=0; i < height; i++ )
		{
		  for ( j=0; j < width; j++ )
		  {
			*(img_ptr++) = 0;
			*(img_ptr++) = *data_ptr;
			*(img_ptr++) = *data_ptr;
			*(img_ptr++) = *(data_ptr);
			data_ptr += volume->x_size_voxels;
		   }
		}
		break;
	    case C_Y_AXIS:
		img_ptr = image_data;
		data_ptr = volume->data.scalar_data_8bit->scalar_data + 
			   slider_val * width; 

		for ( i=0; i < height; i++ )
		{
		  for ( j=0; j < width; j++ )
		  {
			*(img_ptr++) = 0;
			*(img_ptr++) = *data_ptr;
			*(img_ptr++) = *data_ptr;
			*(img_ptr++) = *(data_ptr++);
		   }
		   data_ptr += (volume->y_size_voxels-1)*volume->x_size_voxels;
		}
		break;
	    case C_Z_AXIS:
		img_ptr = image_data;
		data_ptr = volume->data.scalar_data_8bit->scalar_data + 
			   slider_val * width * height; 

		for ( i=0; i < height; i++ )
		  for ( j=0; j < width; j++ )
		  {
			*(img_ptr++) = 0;
			*(img_ptr++) = *data_ptr;
			*(img_ptr++) = *data_ptr;
			*(img_ptr++) = *(data_ptr++);
		   }
		break;
	  }
	}

	ximage = XCreateImage( XtDisplay( slice_info->draw_area ),
			       window_defs.visual,  window_defs.depth,
			       ZPixmap, 0, image_data, width, height,
			       8, width*byte_mult );
			       
	XPutImage( XtDisplay(slice_info->draw_area), 
		   XtWindow(slice_info->draw_area), slice_info->gc, 
		   ximage, 0, 0, 0, 0, width, height );

	free( image_data );

	XDestroyImage( ximage );

}
