/****************************************************************************/
/*                                                                          */
/*  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_modify_color_array.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_oco.h"




void oco_color_array_input( w, volume_index, event )
Widget		w;
int		volume_index;
XEvent		*event;
{
	extern void oco_draw_s_opacity();

	extern C_World			world;
	extern C_ObjectControlInfo	oco_info;

	void 		oco_draw_color_array();


	static OcoEditType	edit_type = C_NO_EDIT;

	static int	old_x = -1;
	static int	old_y = -1;	
	int		x, y;
	int		loop;

	Arg		args[1];
	char		string[256];
	C_Volume	*volume;
	OcoVolumeInfo	*vinfo;

	
	vinfo = oco_info.volume_info[volume_index];

	switch ( event->type )
	{
	    case ButtonPress:
		edit_type = vinfo->color.color_array_edit_type;
		sprintf( string, "Modify %s Color -- MODIFIED",
			world.volume[volume_index]->volume_name );
		XtSetArg( args[0], XmNdialogTitle, 
			XmStringCreate( string, XmSTRING_DEFAULT_CHARSET ) );
		XtSetValues( vinfo->color.volume_color_displayed, args, 1 );
		break;

	    case ButtonRelease:
		edit_type = C_NO_EDIT;
		old_x = -1;
		old_y = -1;
		break;

	    case MotionNotify:

		volume = world.volume[volume_index];

		x = event->xbutton.x;
		y = 255 - event->xbutton.y;

		if ( x < 0 ) x = 0;
		if ( x > 255 ) x = 255;
		if ( y < 0 ) y = 0;
		if ( y > 255 ) y = 255;

		if ( edit_type != C_NO_EDIT && old_x == -1 )
		{
		 	old_x = x;
			old_y = y;
		}
		switch ( edit_type )
		{
		    case C_RED_COLOR_EDIT:

			if ( old_x == x )
			{
			  vinfo->color.color_array_red[x] = y;
			}
			else if ( old_x <= x )
			{
			  for ( loop = old_x; loop <= x; loop++ )
			  {
				vinfo->color.color_array_red[loop] = 
					old_y + ( (float)(loop - old_x) / 
						  (float)(   x - old_x) ) * 
						( y - old_y );
			  }
			}
			else
			{
			  for ( loop = old_x; loop >= x; loop-- )
			  {
				vinfo->color.color_array_red[loop] = 
					old_y + ( (float)(loop - old_x) / 
						  (float)(   x - old_x) ) * 
						( y - old_y );
			  }
			}
			
			
			break;

		    case C_GREEN_COLOR_EDIT:

			if ( old_x == x )
			{
			  vinfo->color.color_array_green[x] = y;
			}
			else if ( old_x <= x )
			{
			  for ( loop = old_x; loop <= x; loop++ )
			  {
				vinfo->color.color_array_green[loop] = 
					old_y + ( (float)(loop - old_x) / 
						  (float)(   x - old_x) ) * 
						( y - old_y );
			  }
			}
			else
			{
			  for ( loop = old_x; loop >= x; loop-- )
			  {
				vinfo->color.color_array_green[loop] = 
					old_y + ( (float)(loop - old_x) / 
						  (float)(   x - old_x) ) * 
						( y - old_y );
			  }
			}
			
			
			break;

		    case C_BLUE_COLOR_EDIT:

			if ( old_x == x )
			{
			  vinfo->color.color_array_blue[x] = y;
			}
			else if ( old_x <= x )
			{
			  for ( loop = old_x; loop <= x; loop++ )
			  {
				vinfo->color.color_array_blue[loop] = 
					old_y + ( (float)(loop - old_x) / 
						  (float)(   x - old_x) ) * 
						( y - old_y );
			  }
			}
			else
			{
			  for ( loop = old_x; loop >= x; loop-- )
			  {
				vinfo->color.color_array_blue[loop] = 
					old_y + ( (float)(loop - old_x) / 
						  (float)(   x - old_x) ) * 
						( y - old_y );
			  }
			}
			
			
			break;
		}

		if ( edit_type != C_NO_EDIT )
		{
			oco_draw_color_array( volume_index, old_x, x );
			oco_draw_s_opacity( vinfo->data.seg_info, old_x, x );

			old_x = x;
			old_y = y;
		}

		sprintf(string, "%d", x );
		XtSetArg( args[0], XmNlabelString, 
		  XmStringCreate( string, XmSTRING_DEFAULT_CHARSET ) );
		XtSetValues( vinfo->color.color_array_x_label, args, 1 );

		sprintf(string, "%1.2f", (float)(y) / 255.0 );
		XtSetArg( args[0], XmNlabelString, 
		  XmStringCreate( string, XmSTRING_DEFAULT_CHARSET ) );
		XtSetValues( vinfo->color.color_array_y_label, args, 1 );

		sprintf(string, "%1.2f", 
			(float)(vinfo->color.color_array_red[x])/255.0 );
		XtSetArg( args[0], XmNlabelString, 
		  XmStringCreate( string, XmSTRING_DEFAULT_CHARSET ) );
		XtSetValues( vinfo->color.color_array_r_label, args, 1 );

		sprintf(string, "%1.2f", 
			(float)(vinfo->color.color_array_green[x])/255.0 );
		XtSetArg( args[0], XmNlabelString, 
		  XmStringCreate( string, XmSTRING_DEFAULT_CHARSET ) );
		XtSetValues( vinfo->color.color_array_g_label, args, 1 );

		sprintf(string, "%1.2f", 
			(float)(vinfo->color.color_array_blue[x])/255.0 );
		XtSetArg( args[0], XmNlabelString, 
		  XmStringCreate( string, XmSTRING_DEFAULT_CHARSET ) );
		XtSetValues( vinfo->color.color_array_b_label, args, 1 );


		break;
	}
}

void oco_color_array_expose( w, volume_index, call_data )
Widget		w;
int		volume_index;
XtPointer	call_data;
{
	extern	C_WindowDefs		window_defs;
	extern  C_ObjectControlInfo	oco_info;

	void	oco_draw_color_array();

	XColor		color;
	int		pixel;
	XGCValues	gcvalues;
	OcoVolumeInfo	*vinfo;

	vinfo = oco_info.volume_info[volume_index];

	if ( vinfo->color.color_array_gc == NULL )
	{
		color.red = 0;
		color.green = 0;
		color.blue = 0;
		
		if ( window_defs.depth == 24 )
			pixel = C_Get_Pixel( color );
		else if ( window_defs.depth == 8 )
			pixel = window_defs.first_color_index;

		gcvalues.background = pixel;

		vinfo->color.color_array_gc = XCreateGC( 
			XtDisplay( vinfo->color.color_array_draw_area ),
			XtWindow( vinfo->color.color_array_draw_area ),
		 	GCBackground, &gcvalues );
	}
	oco_draw_color_array( volume_index, 0, 255 );
}

void oco_draw_color_array( volume_index, min, max )
int			volume_index;
int			min;
int			max;
{
	extern C_World			world;
	extern C_WindowDefs		window_defs;
	extern C_ObjectControlInfo	oco_info;

	C_Volume		*volume;
	int			loop;
	int			tmp;
	XColor			color;
	int			pixel;
	XGCValues		gcvalues;
	OcoVolumeInfo		*vinfo;

	

	vinfo = oco_info.volume_info[volume_index];

	if ( !vinfo->color.volume_color_displayed ) return;
	if ( !vinfo->color.color_array_gc ) return;

	if ( min > max )
	{
		tmp = min;
		min = max;
		max = tmp;
	}
	volume =  world.volume[volume_index];

	for ( loop = 0; loop <= max; loop++ )
	{
		color.red   = vinfo->color.color_array_red[loop];
		color.green = vinfo->color.color_array_green[loop];
		color.blue  = vinfo->color.color_array_blue[loop];
		if ( window_defs.depth == 24 )
		{
			color.red   *= 256;
			color.green *= 256;
			color.blue  *= 256;
			pixel = C_Get_Pixel( color );
		}
		else if ( window_defs.depth == 8 )
		    pixel = window_defs.first_color_index +
			C_Round(((float)( color.red )/63.75))*25 + 
			C_Round(((float)( color.green )/63.75))*5 + 
			C_Round(((float)( color.blue )/63.75)); 

		gcvalues.foreground = pixel;	
		XChangeGC( XtDisplay( vinfo->color.color_array_draw_area ),
			   vinfo->color.color_array_gc,
			   GCForeground, &gcvalues );

		XDrawLine( XtDisplay( vinfo->color.color_array_draw_area ),
			   XtWindow( vinfo->color.color_array_draw_area ),
			   vinfo->color.color_array_gc, loop, 256, loop, 285 );
	}

	color.red = color.green = color.blue = 0;

	if ( window_defs.depth == 24 )
		pixel = C_Get_Pixel( color );
	else if ( window_defs.depth == 8 )
		pixel = window_defs.first_color_index;

	gcvalues.foreground = pixel;
	XChangeGC( XtDisplay( vinfo->color.color_array_draw_area ),
		   vinfo->color.color_array_gc,
		   GCForeground, &gcvalues );

	XFillRectangle( XtDisplay( vinfo->color.color_array_draw_area ),
		        XtWindow( vinfo->color.color_array_draw_area ),
		        vinfo->color.color_array_gc, 
			min-1, 0, (max - min) + 3, 256 );

	if ( min > 0 ) min--;
	if ( max < 255 ) max++;
	if ( min > 0 ) min--;
	if ( max < 255 ) max++;

	color.red = 255;
	color.green = 0;
	color.blue = 0;

	if ( window_defs.depth == 24 )
	{
		color.red   *= 256;
		color.green *= 256;
		color.blue  *= 256;
		pixel = C_Get_Pixel( color );
	}
	else if ( window_defs.depth == 8 )
	    pixel = window_defs.first_color_index +
		C_Round(((float)( color.red )/63.75))*25 + 
		C_Round(((float)( color.green )/63.75))*5 + 
		C_Round(((float)( color.blue )/63.75)); 

	gcvalues.foreground = pixel;
	XChangeGC( XtDisplay( vinfo->color.color_array_draw_area ),
		   vinfo->color.color_array_gc,
		   GCForeground, &gcvalues );

	for ( loop = min; loop < max; loop++ )
	{
		XDrawLine( XtDisplay( vinfo->color.color_array_draw_area ),
			   XtWindow( vinfo->color.color_array_draw_area ),
			   vinfo->color.color_array_gc, 
			   loop, 255 - vinfo->color.color_array_red[loop], 
			   loop+1, 255 - vinfo->color.color_array_red[loop+1] );
	}

	color.red = 0; 
	color.green = 255; 
	color.blue = 0;

	if ( window_defs.depth == 24 )
	{
		color.red   *= 256;
		color.green *= 256;
		color.blue  *= 256;
		pixel = C_Get_Pixel( color );
	}
	else if ( window_defs.depth == 8 )
	    pixel = window_defs.first_color_index +
		C_Round(((float)( color.red )/63.75))*25 + 
		C_Round(((float)( color.green )/63.75))*5 + 
		C_Round(((float)( color.blue )/63.75)); 

	gcvalues.foreground = pixel;
	XChangeGC( XtDisplay( vinfo->color.color_array_draw_area ),
		   vinfo->color.color_array_gc,
		   GCForeground, &gcvalues );

	for ( loop = min; loop < max; loop++ )
	{
		XDrawLine( XtDisplay( vinfo->color.color_array_draw_area ),
		   XtWindow( vinfo->color.color_array_draw_area ),
		   vinfo->color.color_array_gc, 
		   loop, 255 - vinfo->color.color_array_green[loop], 
		   loop+1, 255 - vinfo->color.color_array_green[loop+1] );
	}

	color.red = 0; 
	color.green = 0; 
	color.blue = 255;

	if ( window_defs.depth == 24 )
	{
		color.red   *= 256;
		color.green *= 256;
		color.blue  *= 256;
		pixel = C_Get_Pixel( color );
	}
	else if ( window_defs.depth == 8 )
	    pixel = window_defs.first_color_index +
		C_Round(((float)( color.red )/63.75))*25 + 
		C_Round(((float)( color.green )/63.75))*5 + 
		C_Round(((float)( color.blue )/63.75)); 

	gcvalues.foreground = pixel;
	XChangeGC( XtDisplay( vinfo->color.color_array_draw_area ),
		   vinfo->color.color_array_gc,
		   GCForeground, &gcvalues );

	for ( loop = min; loop < max; loop++ )
	{
		XDrawLine( XtDisplay( vinfo->color.color_array_draw_area ),
		   XtWindow( vinfo->color.color_array_draw_area ),
		   vinfo->color.color_array_gc, 
		   loop, 255 - vinfo->color.color_array_blue[loop], 
		   loop+1, 255 - vinfo->color.color_array_blue[loop+1] );
	}
}
