/*
 * National Center for SuperComputing Applications, University of Illinois
 *
 * This NCSA software product is public domain software.  Permission
 * is hereby granted to do whatever you like with it. Should you wish
 * to make a contribution towards the production of this software, please
 * send us your comments about your experience with the software,  why
 * you liked or disliked it, how you use it, and most importantly, how it
 * helps your work. We will receive your comments at softdev@ncsa.uiuc.edu.
 *
 * Please send bug reports to bugs@ncsa.uiuc.edu
 *
 * Author: Eng-Whatt Toh, National Center for Supercomputing Applications
 *         ewtoh@ncsa.uiuc.edu
 */

/*
 *	File:		gr_isolev.c
 *	Contents:	Iso level window functions for graphics module
 */

#include "gr_com.h"

#define MINISOXSIZE	630
#define MINISOYSIZE	100
#define MAXISOXSIZE	900
#define MAXISOYSIZE	900
#define	LEEWAY		3
#define SPACING		10
#define ORIGIN		10
#define NUMSUBS		10

/* #ifdef XIMAGE_PALETTE  now dynamically choose (gr_Data.paletteEditor).
   gbourhis Feb 93 */
/* Stuff for Ximage changes. */
extern void PaletteBox();
extern void CBPalSave();
static A_Palette_t PalData = { &gr_color, NULL, gr_LoadPAL, CBPalSave};
/* #endif   XIMAGE_PALETTE */

/*
 *	Return a iso-surface renderer window
 */
A_IsoWind_t
*gr_InitIsoLevel(header,parent,tparent,scale)
A_IsoWind_t	*header;
Widget parent;
A_BossWind_t	*tparent;
int				scale;
{
	A_IsoWind_t *tmp;
	Widget		boxWind,boxWind1;
	int			winxsize, winysize, maxsize;
	Display		*dpy;
	int			scr,i;
	XGCValues	gcvals;
	XImage		*palimage;
	char		endX[10],endY[10],endZ[10];
	float32		avgVal;

	gr_WidgetCursor(tparent->shell,XC_watch);

	if ((tmp = (A_IsoWind_t *)td_Malloc(sizeof(A_IsoWind_t),
			   "A_IsoWind_t")) == NULL)
		return(NULL);

	avgVal = (tparent->data->max-tparent->data->min)/(float32)NUMSUBS;

	tmp->stopIso = FALSE;
	tmp->scale = scale;
	tmp->xdim = td_HdfgetDim(tparent->data,1);
	tmp->ydim = td_HdfgetDim(tparent->data,2);
	tmp->zdim = td_HdfgetDim(tparent->data,3);

	for (i=0;i<NUMSUBS;i++)
	{
		tmp->startX[i] = 0;
		tmp->startY[i] = 0;
		tmp->startZ[i] = 0;
		tmp->endX[i] = tmp->xdim-1;
		tmp->endY[i] = tmp->ydim-1;
		tmp->endZ[i] = tmp->zdim-1;
	}

	tmp->xangle = tmp->yangle = tmp->zangle = 0.0;
	sprintf(endX,"%d",tmp->endX[0]);
	sprintf(endY,"%d",tmp->endY[0]);
	sprintf(endZ,"%d",tmp->endZ[0]);

	tmp->xmid = tmp->xdim*scale/2.0;
	tmp->ymid = tmp->ydim*scale/2.0;
	tmp->zmid = tmp->zdim*scale/2.0;

	maxsize = (XDS_GREATER(tmp->xdim,XDS_GREATER(tmp->ydim,tmp->zdim)))
	  *scale;

	maxsize = 1.500*maxsize;
	tmp->xsize = tmp->ysize = maxsize+2.0*SPACING;
	tmp->xoff = tmp->yoff = tmp->zoff = tmp->xsize/2.0;

	if ((tmp->data24=
	     td_Malloc1D(tmp->xsize*3,tmp->ysize,sizeof(unsigned char),
			"Iso 24 data"))==NULL)
		return(NULL);
	if ((tmp->palData=
	     td_Malloc1D(768,1,sizeof(unsigned char),"Palette data"))==NULL)
		return(NULL);

	if ((tmp->data=
	     td_Malloc1D(tmp->xsize,tmp->ysize,sizeof(unsigned char),
			"Iso raster"))==NULL)
	  return(NULL);

	if ((tmp->fb=td_Malloc2DInt(tmp->xsize,tmp->ysize,"Iso fb data"))==NULL)
	  return(NULL);

	if (tmp->xsize > MINISOXSIZE)
	  if (tmp->xsize > MAXISOXSIZE)
            winxsize = MAXISOXSIZE;
	  else
            winxsize = tmp->xsize;
	else
	  winxsize = MINISOXSIZE;
	
	if (tmp->ysize > MINISOYSIZE)
	  if (tmp->ysize > MAXISOYSIZE)
            winysize = MAXISOYSIZE;
	  else
            winysize = tmp->ysize;
	else
	  winysize = MINISOYSIZE;
	
	sprintf(msg,"%s: Iso-surface",tparent->filename);
	
	tmp->shell = gr_MakeWindow("XDS Iso-surface",parent,&(tmp->win),
				   (XtCallbackProc)gr_CloseIsoLevel,
				   ISOWIND,msg,"Close",(caddr_t)tmp,
				   10,10,winxsize+4+LEEWAY,winysize+190+LEEWAY);

	gr_ImageSetCMap(tmp->shell); /* this two lines */
	XtManageChild(tmp->shell); /* added by gbourhis Feb 93 */

	boxWind = gr_MakeBulletin("XDSbulletin",tmp->win,
		2,2,winxsize+LEEWAY,winysize+LEEWAY);

	tmp->imageVPort = gr_MakeVPort("XDSvport",boxWind,
				       NOSCROLL, HP, NULL, NULL, 5,
				       (caddr_t)tmp,
				       0,0,winxsize+LEEWAY,winysize+LEEWAY);

	tmp->imageWin = gr_MakeWorkSpace("XDSworkspace",tmp->imageVPort,
					 (XtCallbackProc)gr_IsoExpose,
					 NULL, NULL,
					 (caddr_t)tmp,0,0,winxsize,winysize);

	tmp->doUpdate = TRUE;	/* added by gbourhis Jan 93 */
	gr_IsoInit(tmp);
	tmp->image = gr_ImageCreate(tmp->imageVPort,tmp->xsize,tmp->ysize,
				    tmp->data);

	boxWind = gr_MakeBulletin("XDSbulletin",tmp->win,
				  2,winysize+LEEWAY+5,winxsize,104);
	
	tmp->IDLabel = gr_MakeTitleBar("XDSlabel",boxWind,"S 1",
				       0,0,25,25);
	
	gr_MakeButton("XDSbutton",boxWind,"Set",
		      (XtCallbackProc)gr_IsoSetValues,(caddr_t)tmp,0,25,25,25);
	
	tmp->IDSlider =
		gr_MakeSlider("SDSslider",boxWind,0,NUMSUBS,1,0,1,
		(XtCallbackProc)gr_IsoIDSliderSel,
		(XtCallbackProc)gr_IsoIDSliderMov,
		(XtCallbackProc)gr_IsoIDSliderRel,
		VERTONLY, (caddr_t)tmp,25,0,25,50);

	sprintf(msg,"%7.2f",avgVal+tparent->data->min);
	tmp->isoDialog = gr_MakeDialog("XDSdialog",boxWind,
				       "Value",msg,8,50,0,56,50);
	tmp->redDialog = gr_MakeDialog("XDSdialog",boxWind,
				       "Red  ","0.0",5,106,0,50,50);
	tmp->greenDialog = gr_MakeDialog("XDSdialog",boxWind,
					 "Green","0.9",5,156,0,50,50);
	tmp->blueDialog = gr_MakeDialog("XDSdialog",boxWind,
					"Blue ","0.0",5,206,0,56,50);
	
	tmp->startXDialog = gr_MakeDialog("XDSdialog",boxWind,
					  "Start X","0",5,260,0,60,50);
	tmp->startYDialog = gr_MakeDialog("XDSdialog",boxWind,
					  "Start Y","0",5,320,0,60,50);
	tmp->startZDialog = gr_MakeDialog("XDSdialog",boxWind,
					  "Start Z","0",5,380,0,60,50);
	tmp->rotXDialog = gr_MakeDialog("XDSdialog",boxWind,
					"Rot X  ","0.0",5,440,0,60,50);
	tmp->rotYDialog = gr_MakeDialog("XDSdialog",boxWind,
					"Rot Y  ","0.0",5,500,0,60,50);
	tmp->rotZDialog = gr_MakeDialog("XDSdialog",boxWind,
					"Rot Z  ","0.0",5,560,0,60,50);
	palimage = gr_ImageCreate(boxWind,gr_color.maxColors,30,gr_palData);
	gr_MakeImageStatic("XDSstaticimage",boxWind,palimage,
		  NULL,(caddr_t)NULL,0,52,256,30);
/* #ifdef XIMAGE_PALETTE */
	if (gr_Data.paletteEditor) /* gbourhis Feb 93 */
	  {
	    PalData.client_data = (caddr_t) tmp->shell;
	    gr_MakeButton("XDSbutton",boxWind,"Palette",
			  (XtCallbackProc)PaletteBox, (caddr_t) &PalData,
			  0,82,256,18);
	  }
	else			/* #else before */
	  gr_MakeButton("XDSbutton",boxWind,"Palette",
			(XtCallbackProc)gr_LoadPAL,(caddr_t)tmp->shell,
			0,82,256,18);
/* #endif */
	tmp->endXDialog = gr_MakeDialog("XDSdialog",boxWind,
					"End X  ",endX,5,260,52,60,50);
	tmp->endYDialog = gr_MakeDialog("XDSdialog",boxWind,
					"End Y  ",endY,5,320,52,60,50);
	tmp->endZDialog = gr_MakeDialog("XDSdialog",boxWind,
					"End Z  ",endZ,5,380,52,60,50);
	tmp->incXDialog = gr_MakeDialog("XDSdialog",boxWind,
					"Inc X  ","0.0",5,440,52,60,50);
	tmp->incYDialog = gr_MakeDialog("XDSdialog",boxWind,
					"Inc Y  ","0.0",5,500,52,60,50);
	tmp->incZDialog = gr_MakeDialog("XDSdialog",boxWind,
					"Inc Z  ","0.0",5,560,52,60,50);
	
	boxWind = gr_MakeBulletin("XDSbulletin",tmp->win,
				  2,winysize+LEEWAY+5+104,winxsize,52);
	
	
	boxWind1 = gr_MakeBulletin("XDSbulletin",boxWind,
				   0,0,256,50);
	gr_MakeToggle("XDStoggle",boxWind1,"Rotate     ",SQUARE,
		      TRUE,(XtCallbackProc)gr_IsoSetRotate,
		      (XtCallbackProc)gr_IsoSetNoRotate,(caddr_t)tmp,
		      2,2,70,20);
	gr_MakeToggle("XDStoggle",boxWind1,"Update     ",SQUARE,
		      TRUE,(XtCallbackProc)gr_IsoSetUpdate,
		      (XtCallbackProc)gr_IsoSetNoUpdate,(caddr_t)tmp,
		      2,25,70,20);
	gr_MakeToggle("XDStoggle",boxWind,"Perspective",SQUARE,
		      TRUE,(XtCallbackProc)gr_IsoSetPerspective,
		      (XtCallbackProc)gr_IsoSetNoPerspective,(caddr_t)tmp,
		      72,2,90,20);
	gr_MakeToggle("XDStoggle",boxWind,"Attenuate  ",SQUARE,
		      TRUE,(XtCallbackProc)gr_IsoSetAttenuate,
		      (XtCallbackProc)gr_IsoSetNoAttenuate,(caddr_t)tmp,
		      72,25,90,20);
	gr_MakeToggle("XDStoggle",boxWind,"Wire Frame",SQUARE,
		      FALSE,(XtCallbackProc)gr_IsoSetWireFrame,
		      (XtCallbackProc)gr_IsoSetPainted,(caddr_t)tmp,
		      162,2,90,20);
	gr_MakeToggle("XDStoggle",boxWind,"True Color",SQUARE,
		      FALSE,(XtCallbackProc)gr_IsoSetTrueColor,
		      (XtCallbackProc)gr_IsoSetPseudo,(caddr_t)tmp,
		      162,25,90,20);
	
	tmp->pFactorDialog = gr_MakeDialog("XDSdialog",boxWind,
					   "Focal Pt.","1.0",5,260,0,60,50);
	tmp->attenDialog = gr_MakeDialog("XDSdialog",boxWind,
					 "Attenuate","100.0",10,320,0,60,50);
	tmp->numFramesDialog = gr_MakeDialog("XDSdialog",boxWind,
					     "Frames   ","1",5,380,0,60,50);
	tmp->numSubsDialog = gr_MakeDialog("XDSdialog",boxWind,
					   "Surfaces ","1",5,440,0,60,50);
	
	gr_MakeButton("XDSbutton",boxWind,"View",
		      (XtCallbackProc)gr_IsoView,(caddr_t)tmp,500,0,60,22);
	gr_MakeButton("XDSbutton",boxWind,"Save",
		      (XtCallbackProc)gr_SaveIso,(caddr_t)tmp,500,23,60,22);
	gr_MakeButton("XDSbutton",boxWind,"Animate",
		      (XtCallbackProc)gr_SaveDiskIAni,(caddr_t)tmp,560,0,60,22);
	gr_MakeButton("XDSbutton",boxWind,"Clear",
		      (XtCallbackProc)gr_IsoClear,(caddr_t)tmp,560,23,30,22);
	gr_MakeButton("XDSbutton",boxWind,"Stop",
		      (XtCallbackProc)gr_IsoInterrupt,(caddr_t)tmp,590,23,30,22);
	

	dpy = XtDisplay(tmp->imageWin);
	scr = DefaultScreen(dpy);
	gcvals.foreground = BlackPixel(dpy,scr);
	gcvals.background = WhitePixel(dpy,scr);
	gcvals.function   = GXcopy;
	tmp->gc = XtGetGC(tmp->imageWin, 
		GCForeground|GCBackground|GCFunction, &gcvals);

	for (i=0;i<NUMSUBS;i++)
	{
		tmp->subsVal[i] = (float32)
			(((float32)(i+1.0)*avgVal)+tparent->data->min);
		tmp->redCoeff[i] = (double)((1.0/NUMSUBS)*i);
		tmp->greenCoeff[i] = (double)(1.0-((1.0/NUMSUBS)*(i+1.0)));
		tmp->blueCoeff[i] = (double)((1.0/NUMSUBS)*i);
	}

	tmp->pFactor = 1.0;
	tmp->atten = 100.0;
	tmp->numFrames = 1;
	tmp->numSubs = 1;
	tmp->curSubsID = 0;
	tmp->curSubs = 0;
	tmp->incX = 0.0;
	tmp->incY = 0.0;
	tmp->incZ = 0.0;

	tmp->stopIso = TRUE;
	tmp->doWireFrame = FALSE;
	tmp->doTrueColor = FALSE;
	tmp->doAttenuate = TRUE;
	tmp->doRotate = TRUE;
	tmp->doPerspective = TRUE;

	tmp->parent = tparent;
	tmp->prev = NULL;
	tmp->next = header;
	if (header != NULL)
		header->prev = tmp;

	gr_WidgetCursor(tmp->shell,XC_draped_box);
	gr_WidgetCursor(tparent->shell,XC_draped_box);

	return(tmp);
}


/*
 *	Close a Iso-surface renderer window
 */
void
gr_CloseIsoLevel(w, client_data, call_data)
Widget	w;
caddr_t	client_data;
caddr_t	call_data;
{
	A_IsoWind_t	*isoWin=(A_IsoWind_t *)client_data;

	if (isoWin != NULL)
	{
        if (isoWin->prev != NULL)
            isoWin->prev->next = isoWin->next;
        else
            isoWin->parent->isoWin = isoWin->next;

        if (isoWin->next != NULL)
            isoWin->next->prev = isoWin->prev;

        isoWin->parent->numIsoWins--;

		XDestroyImage(isoWin->image);
		td_Free((char *)isoWin->image);
		td_Free((char *)isoWin->data);
		td_Free((char *)isoWin->data24);
		td_Free((char *)isoWin->palData);
		td_Free((int *)isoWin->fb);
		XtDestroyWidget(isoWin->shell);
		td_Free((char *)isoWin);
	}
}
