/****************************************************************************/
/*                                                                          */
/*  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_color_select.c
 *                    Author: Lisa Sobierajski 
 *                      Date: 9/17/92
 *               Description: Motif Color Selection Routines Of VolVis
 *			      These routines can be used to create a three
 *			      slider color selection box (the three sliders
 *			      will be labeled "R", "G", and "B") with a two
 *			      line label for the box.  The color selection
 *			      box has a display area which will show the
 *			      current color selection, and will updated as
 *			      the user adjusts the sliders.
 *      Modification History:
 *
 *              Who?            When?           Why?
 *      --------------------------------------------------------------------
 *
 */

/****		Standard C Includes		****/
#include <stdio.h>

/****		X11 Includes			****/
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>

/****		Motif Includes			****/
#include <Xm/Xm.h>
#include <Xm/BulletinB.h>
#include <Xm/LabelG.h>
#include <Xm/DrawingA.h>
#include <Xm/Scale.h>
#include <Xm/Frame.h>

/****		VolVis Includes			****/
#include "C_volvis.h"
#include "MOTIF_windefs.h"


/*
 *        Procedure Name: C_create_color_selection
 *        Return Value: C_ColorSelectInfo *
 *				The return value (color_info) contains
 *				the three slider widgets, the widget for
 *				the drawing area, and the connection to the
 *				display.
 *        Input Variables: 
 *		
 *		parent		-  The parent widget for the frame created
 *				   in this routine
 *		x		-  the x location of the frame in the parent
 *		y		-  the y location of the frame in the parent
 *		first_title	-  the first line of the title for this
 *				   color selection box
 *		second_title	-  the second line of the title for this
 *				   color selection box.  This string will be
 *				   placed directly below first_title
 *		color		-  a pointer to the color which will be
 *				   initially displayed
 *
 *       Output Variables: none
 *       Update Variables: none
 *       Global Variables: 
 *
 *		window_defs	-  window appearance definitions
 *
 *           Description:
 *
 *		This procedure creates a color selection area.  This consists
 *		of a frame placed at location (x,y) within the parent, a two
 *		line title (first_title and second_title), and three sliders
 *		(one for red, one for green, and one for blue).  The three
 *		sliders are vertical sliders, labeled R, G and B, which
 *		have initial values defined by the color parameter.
 */


C_ColorSelectInfo *C_create_color_selection( parent, x, y,
					     first_title, second_title, color )
Widget		parent;
int		x, y;
char		*first_title;
char		*second_title;
C_Color		*color;
{
	/***    External Variables  ***/
	extern 	C_WindowDefs   	window_defs;

	/***	Local Routines   ***/
	void 			C_change_color();

	/***	Local Variables     ***/
	Arg			args[20]; 	  /* Used for XtSetArg     */
	int			n;		  /* Used for XtSetArg     */
	Widget			draw_area;        /* The color display area*/
	Widget			slider;           /* The three sliders     */
	Widget			frame;            /* The enclosing frame   */
	Widget			bboard;           /* Bboard with the frame */
	Widget			label;            /* The label of the area */
	XmString		label_string;     /* The label string      */
	XColor			background_color; /* The color of draw_area*/
	int			pixel;		  /* Pixel val of draw_area*/
	Display			*display;         /* Connection to display */
	C_ColorSelectInfo	*color_info;      /* The return value      */


	/****    Allocate memory for the return value   ****/
	color_info = C_New( C_ColorSelectInfo );
	
	/****   Create a frame at the specified x,y location   ****/
        n = 0;
        XtSetArg( args[n], XmNx, x ); n++;
        XtSetArg( args[n], XmNy, y ); n++;
	C_Set_Color_Frame( args, n, window_defs );
        frame = XmCreateFrame( parent, "frame", args, n );
	XtManageChild( frame );

	color_info->frame = frame;

	/****  Put a bulletin board in frame ****/
        n = 0;
	C_Set_Color_Bboard( args, n, window_defs );
        bboard = XmCreateBulletinBoard( frame, "bboard", args, n );
        XtManageChild( bboard );

        /****     Create the color labels   ****/

	/****    First Label    ****/
        label_string = XmStringCreate( first_title, XmSTRING_DEFAULT_CHARSET );
        n=0;
        XtSetArg( args[n], XmNx, 10 ); n++;
        XtSetArg( args[n], XmNy, 20 ); n++;
        XtSetArg( args[n], XmNlabelString, label_string ); n++;
        label = XmCreateLabelGadget( bboard, first_title, args, n );
        XtManageChild( label );
        XmStringFree( label_string );

	/****    Second Label   ****/
        label_string = XmStringCreate( second_title, XmSTRING_DEFAULT_CHARSET );
        n=0;
        XtSetArg( args[n], XmNx, 10 ); n++;
        XtSetArg( args[n], XmNy, 35 ); n++;
        XtSetArg( args[n], XmNlabelString, label_string ); n++;
        label = XmCreateLabelGadget( bboard, second_title, args, n );
        XtManageChild( label );


	/****    Create the red slider - This is a vertical slider   ****/
	/****    which has a label of "R", and goes from 0 to 255    ****/
	/****    in steps of 1.					     ****/
	n = 0;
        label_string = XmStringCreate("R", XmSTRING_DEFAULT_CHARSET );
	XtSetArg( args[n], XmNtitleString, label_string ); n++;
	XtSetArg( args[n], XmNorientation, XmVERTICAL ); n++;
	XtSetArg( args[n], XmNminimum, 0 ); n++;
	XtSetArg( args[n], XmNmaximum, 255 ); n++;
	XtSetArg( args[n], XmNdecimalPoints, 0 ); n++;
	XtSetArg( args[n], XmNshowValue, TRUE ); n++;
	XtSetArg( args[n], XmNvalue, 
			(int)( color->red ) ); n++;
	XtSetArg( args[n], XmNscaleMultiple, 1 ); n++;
        XtSetArg( args[n], XmNscaleHeight, 100 ); n++;
        XtSetArg( args[n], XmNx, 125 ); n++;
        XtSetArg( args[n], XmNy, 0 ); n++;
	C_Set_Color_Scale( args, n, window_defs );
	slider = XtCreateManagedWidget("R", xmScaleWidgetClass, 
					bboard, args, n );

	/****    Store the red slider widget in color info    ****/
	color_info->red_slider = slider;

	/****    Add a callback to change the draw_area color whenever  ****/
	/****    the value of the red slider is changed                 ****/
	XtAddCallback( slider, XmNvalueChangedCallback, C_change_color, 
		       color_info );

	/****    Add a callback to change the draw_area color whenever  ****/
	/****    the red slider is dragged                              ****/
	XtAddCallback( slider, XmNdragCallback, C_change_color, 
		       color_info );

	/****    Create the green slider - This is a vertical slider ****/
	/****    which has a label of "G", and goes from 0 to 255    ****/
	/****    in steps of 1.					     ****/
	n = 0;
        label_string = XmStringCreate("G", XmSTRING_DEFAULT_CHARSET );
	XtSetArg( args[n], XmNtitleString, label_string ); n++;
	XtSetArg( args[n], XmNorientation, XmVERTICAL ); n++;
	XtSetArg( args[n], XmNminimum, 0 ); n++;
	XtSetArg( args[n], XmNmaximum, 255 ); n++;
	XtSetArg( args[n], XmNdecimalPoints, 0 ); n++;
	XtSetArg( args[n], XmNshowValue, TRUE ); n++;
	XtSetArg( args[n], XmNvalue, 
			(int)( color->green ) ); n++;
	XtSetArg( args[n], XmNscaleMultiple, 1 ); n++;
        XtSetArg( args[n], XmNscaleHeight, 100 ); n++;
        XtSetArg( args[n], XmNx, 200 ); n++;
        XtSetArg( args[n], XmNy, 0 ); n++;
	C_Set_Color_Scale( args, n, window_defs );
	slider = XtCreateManagedWidget("G", xmScaleWidgetClass, 
					bboard, args, n );
	
	/****    Store the green slider widget in color info    ****/
	color_info->green_slider = slider;

	/****    Add a callback to change the draw_area color whenever  ****/
	/****    the value of the green slider is changed               ****/
	XtAddCallback( slider, XmNvalueChangedCallback, C_change_color, 
		       color_info );

	/****    Add a callback to change the draw_area color whenever  ****/
	/****    the green slider is dragged                            ****/
	XtAddCallback( slider, XmNdragCallback, C_change_color, 
		       color_info );

	/****    Create the blue slider - This is a vertical slider  ****/
	/****    which has a label of "B", and goes from 0 to 255    ****/
	/****    in steps of 1.					     ****/
	n = 0;
        label_string = XmStringCreate("B", XmSTRING_DEFAULT_CHARSET );
	XtSetArg( args[n], XmNtitleString, label_string ); n++;
	XtSetArg( args[n], XmNorientation, XmVERTICAL ); n++;
	XtSetArg( args[n], XmNminimum, 0 ); n++;
	XtSetArg( args[n], XmNmaximum, 255 ); n++;
	XtSetArg( args[n], XmNdecimalPoints, 0 ); n++;
	XtSetArg( args[n], XmNshowValue, TRUE ); n++;
	XtSetArg( args[n], XmNvalue, 
			(int)( color->blue ) ); n++;
	XtSetArg( args[n], XmNscaleMultiple, 1 ); n++;
        XtSetArg( args[n], XmNscaleHeight, 100 ); n++;
        XtSetArg( args[n], XmNx, 275 ); n++;
        XtSetArg( args[n], XmNy, 0 ); n++;
	C_Set_Color_Scale( args, n, window_defs );
	slider = XtCreateManagedWidget("B", xmScaleWidgetClass, 
					bboard, args, n );

	/****    Store the blue slider widget in color info    ****/
	color_info->blue_slider = slider;

	/****    Add a callback to change the draw_area color whenever  ****/
	/****    the value of the blue slider is changed                ****/
	XtAddCallback( slider, XmNvalueChangedCallback, C_change_color, 
		       color_info );

	/****    Add a callback to change the draw_area color whenever  ****/
	/****    the blue slider is dragged                             ****/
	XtAddCallback( slider, XmNdragCallback, C_change_color, 
		       color_info );

	/****	Get the display connect to the X server   ****/
	display = XtDisplay( bboard );

	/****   Store the display in color_info   ****/
	color_info->display = display;

	/****   Set up the background color for the draw_area to the   ****/
	/****   input color.  We must multiply the color value by 256  ****/
	/****   since the components of a C_Color are 8 bit, and the   ****/
	/****   components of a XColor are 16 bit		       ****/
	background_color.red   = color->red;
	background_color.green = color->green;
	background_color.blue  = color->blue;

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

	/****   Create the draw_area widget    ****/
	n = 0;
        XtSetArg( args[n], XmNwidth, 100 ); n++;
        XtSetArg( args[n], XmNheight, 50 ); n++;
        XtSetArg( args[n], XmNx, 0 ); n++;
        XtSetArg( args[n], XmNy, 60 ); n++;
        XtSetArg( args[n], XmNsensitive, FALSE ); n++;
	XtSetArg( args[n], XmNbackground, pixel ); n++;
	draw_area = XmCreateDrawingArea( bboard, 
					    "draw_area", args, n );
	XtManageChild( draw_area );

	/****    Store the draw_area widget in color_info   ****/
	color_info->draw_area = draw_area;

	/****    Return the color info   ****/
	return color_info;
	
}

/*
 *        Procedure Name: C_change_color
 *        Return Value: void 
 *        Input Variables: 
 *		
 *		w		-	The widget to which this callback
 *					is attached
 *		client_data     -	the C_ColorSelectInfo which contains
 *					the red, green and blue sliders,
 *					the draw_area and the display
 *		call_data	-	unused
 *
 *        Output Variables: none
 *        Update Variables: none
 *        Global Variables: none
 *
 *        Description:
 *
 *		This procedure will update the background color of
 *		draw_area to reflect the color specified by the red, green
 *		and blue sliders.  This routine is called from 
 * 		C_create_color_selection, and should not be called from
 *		anywhere else.
 */
void C_change_color( w, client_data, call_data )
Widget			w;
C_ColorSelectInfo	*client_data;
XtPointer		call_data;
{
	extern C_WindowDefs	window_defs;

	/****	Local Variables    ****/
	Arg		args[1];		/* Used for XtSetArg     */
	XColor		background_color;	/* Used to set the color */
	int		pixel;
	int		tmp_val;		/* Temporary value	 */
	

	/****   Get the current value of the red slider   ****/
	/****   and store it in the  background color.	  ****/
	XmScaleGetValue( client_data->red_slider, &tmp_val );
	background_color.red = tmp_val;

	/****   Get the current value of the green slider  ****/
	/****   and store it in the  background color.	  ****/
	XmScaleGetValue( client_data->green_slider, &tmp_val );
	background_color.green = tmp_val;

	/****   Get the current value of the blue slider  ****/
	/****   and store it in the  background color.	  ****/
	XmScaleGetValue( client_data->blue_slider, &tmp_val );
	background_color.blue = tmp_val;

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

	/****   Set the background color of the draw_area   ****/
	XtSetArg( args[0], XmNbackground, pixel );
	XtSetValues( client_data->draw_area, args, 1 );
		
}
