 /*
  * Khoros: $Id: create.c,v 1.3 1991/12/18 08:56:30 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: create.c,v 1.3 1991/12/18 08:56:30 dkhoros Exp $";
#endif

 /*
  * $Log: create.c,v $
 * Revision 1.3  1991/12/18  08:56:30  dkhoros
 * HellPatch3
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.
 * 
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *----------------------------------------------------------------------
 */

#include "unmcopyright.h"        /* Copyright 1990 by UNM */
#include "editimage.h"
#include <X11/Xaw/Box.h>

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>      Creation of Custom Widget Routines		      <<<<
   >>>>                                                       <<<<
   >>>>		create_raster_display()			      <<<<
   >>>>		create_zoom_display()			      <<<<
   >>>>		create_pixel_display()			      <<<<
   >>>>		create_psuedo_display()			      <<<<
   >>>>		create_lut_display()			      <<<<
   >>>>		create_thres_display()			      <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */



/*
 *  fonts used by create_pixel_display
 */
static  num_fonts = 5;
static  char *fonts[] =
{
          "fixed",
          "-adobe-times-medium-r-normal--12*",
          "-adobe-times-bold-r-normal--12*",
          "6x10",
          "variable"
};

/****************************************************************
*
* Routine Name:  create_raster_display
*
*
* Purpose:  creates the raster widget in which the image will be displayed
*	    inside the workspace that is part of the graphical user interface
*
* Input:  form   - the form that the raster display will belong
*	  parent - the workspace on which the raster widget will be created
*
* Output:  none 
*
* Written By:  Mark Young & Danielle Argiro
*
****************************************************************/

create_raster_display(form, parent)

xvf_form *form;
Widget parent;
{
	xvd_create_raster(xvdisplay->display, parent, xvdisplay, True); 
	xvd_create_icon(xvdisplay->display, xvdisplay, 64, 64);
	xvf_change_form_glyph(form, xvdisplay->icon, ICON);
}


/****************************************************************
*
* Routine Name:  create_zoom_display 
*
*
* Purpose:  creates the zoom box 
*
* Input:  parent - the workspace on which the zoom window will be created
*	  zoomfactor - default zoom factor for zooming window
*
* Output:  none 
*
* Written By:  Mark Young & Danielle Argiro
*
****************************************************************/

create_zoom_display(parent, zoomfactor)
Widget parent;
float  zoomfactor;
{
        int width, height;
	unsigned   long mask;
	Widget	   toplevel;

	width = height = 210;
	zoom = (ZoomStructure *) XtMalloc(sizeof(ZoomStructure));

	if ((zoom->ximage = xvd_shrink_ximage(xvdisplay->display,
			xvdisplay->ximage, width, height, NULL)) != NULL)
	{
	   if (zoom->ximage->depth == 1)
	      zoom->ximage->format = XYBitmap;
	}
	zoom->image  = parent;
	zoom->mode   = Continuous_Mode;
	zoom->cursor = Cross;
	zoom->zoomfactor = zoomfactor;

	mask = StructureNotifyMask | ExposureMask;
	XtAddEventHandler(zoom->image, mask, FALSE, redisplay_zoom, zoom);

	toplevel = parent;
	while (XtParent(toplevel) != NULL)
	   toplevel = XtParent(toplevel);

	mask = StructureNotifyMask;
	XtAddEventHandler(toplevel, mask, FALSE, redisplay_zoom, zoom);

} /* end create_zoom_display */



/****************************************************************
*
* Routine Name:  create_pixel_display 
*
*
* Purpose:  creates the RGB pixel display, the CMY pixel display, and
*	    the HSV pixel display on the pixel workspace that is part of the
*	    user interface. 
*
* Input:  parent - the workspace on which the zoom widget will be created
*
* Output:  none 
*
* Written By:  Mark Young & Danielle Argiro
*
****************************************************************/

create_pixel_display(parent)
Widget parent;
{
	int	i;
	Widget  toplevel, create_pixel_back();

	XGCValues xgcv;
	unsigned  long mask;
	XCharStruct ov_return;
        int	  ascent, descent, dir_return;
	Display   *display = XtDisplay(parent);
	int	  screen = XDefaultScreen(display);


	pixels = (PixelStructure *) malloc(sizeof(PixelStructure));

	/*
         *  Create the gc and font that we will be drawing the pixel
         *  values.
         */
        xgcv.function   = GXset;
        xgcv.line_width = 0;
        xgcv.foreground = XWhitePixel(display, screen);
	mask = GCFunction | GCLineWidth | GCForeground;
        pixels->gc = XCreateGC(display, XDefaultRootWindow(display), mask,
			&xgcv);

	/* font to be used with text on the workspace */
        for (i = 0; i < num_fonts; i++)
        {
            if ((pixels->font = XLoadQueryFont(display, fonts[i])) != NULL)
               break;
        }
        if (pixels->font == NULL)
        {
           xvf_error_wait("Can't find any default fonts!", 
			  "create_pixel_display", NULL);
           return;
        }

	/*
         * specify font in gc
         */
        XSetFont(display, pixels->gc, pixels->font->fid);
        pixels->width = XTextWidth(pixels->font," 000  ",  6) + 5;
        XTextExtents(pixels->font, "  000 ", 6, &dir_return,
                     &ascent, &descent, &ov_return);
        pixels->height = ascent + descent + 5;

	pixels->pixels = parent;
	pixels->mode = Continuous_Mode;

	/*
         *  Create the colorspace pixel display.
         */
	pixels->rgb_back = create_pixel_back(parent, "Red", "Green", "Blue",
			red, green, blue, pixels->rgb, NULL, NULL);
	pixels->cmy_back = create_pixel_back(parent, "Cyan", "Magenta","Yellow",
			cyan, magenta, yellow, pixels->cmy, NULL, NULL);
	pixels->hsv_back = create_pixel_back(parent, "Hue", "Saturation",
			"Value", grey, grey, grey, pixels->hsv, NULL, NULL);
	pixels->hls_back = create_pixel_back(parent, "Hue", "Light",
			"Saturation", grey, grey, grey, pixels->hls, NULL,NULL);
	pixels->yiq_back = create_pixel_back(parent, "Y", "I", "Q", grey, grey,
			grey, pixels->yiq, NULL, NULL);
	pixels->uvw_back = create_pixel_back(parent, "U", "V", "W", grey, grey,
			grey, pixels->uvw, NULL, NULL);
	pixels->xyz_back = create_pixel_back(parent, "X", "Y", "Z", grey, grey,
			grey, pixels->xyz, NULL, NULL);
	pixels->grey_back = create_pixel_back(parent, "Pixel Values", NULL,
			NULL, grey, grey, grey, pixels->grey, NULL, NULL);

        pixels->model = RGB;
	XtMapWidget(pixels->rgb_back);
	XRaiseWindow(display, XtWindow(pixels->rgb_back));


	mask = StructureNotifyMask | ExposureMask;
	XtAddEventHandler(pixels->pixels, mask, FALSE, redisplay_pixels,pixels);

	toplevel = parent;
	while (XtParent(toplevel) != NULL)
	   toplevel = XtParent(toplevel);

	mask = StructureNotifyMask;
	XtAddEventHandler(toplevel, mask, FALSE, redisplay_pixels, pixels);

} /* end create_pixel_display */


/****************************************************************
*
* Routine Name:  create_pseudo_display 
*
*
* Purpose:  creates the psuedocoloring display on the pseudocoloring 
*	    workspace that is part of the user interface. 
*
* Input:  parent - the workspace on which the zoom widget will be created
*
* Output:  none 
*
* Written By:  Mark Young & Danielle Argiro
*
****************************************************************/

create_pseudo_display(parent)

Widget parent;
{
        int     i;
        Arg     args[15];
        Widget  create_pseudo_back(), create_color_palette();
	void	undo_cb();

	pseudo = (PseudoStructure *) malloc(sizeof(PseudoStructure));
        pseudo->pseudo = parent;

	i = 0;
	XtSetArg(args[i], XtNfromVert, NULL);                   i++;
	XtSetArg(args[i], XtNfromHoriz, NULL);			i++;
        XtSetArg(args[i], XtNheight, 30);                       i++;
        XtSetArg(args[i], XtNlabel, "UNDO");                	i++;
	pseudo->undo = XtCreateManagedWidget("Undo", commandWidgetClass,
                                              parent, args, i);
	XtAddCallback(pseudo->undo,XtNcallback, undo_cb, NULL);


	/*
	 * create two color boxes at the top of the pseudocolor display
	 */
	i = 0;
        XtSetArg(args[i], XtNwidth, 30);                        i++;
        XtSetArg(args[i], XtNheight, 30);                       i++;
        XtSetArg(args[i], XtNhSpace, 30);                       i++;
        XtSetArg(args[i], XtNvSpace, 30);                       i++;
        XtSetArg(args[i], XtNfromVert, NULL);                   i++;
        XtSetArg(args[i], XtNfromHoriz, pseudo->undo);          i++;
        XtSetArg(args[i], XtNforeground, white);                i++;
        XtSetArg(args[i], XtNbackground, white);                i++;
        XtSetArg(args[i], XtNborderColor, black);               i++;
        XtSetArg(args[i], XtNhorizDistance, 50);          	i++;
	pseudo->color1 = XtCreateManagedWidget("color1", boxWidgetClass,
                                         	parent, args, i);


        i--; XtSetArg(args[i], XtNfromHoriz, pseudo->color1);        i++;
        pseudo->color2 = XtCreateManagedWidget("color2", boxWidgetClass,
                                         	parent, args, i);

        XtSetMappedWhenManaged(pseudo->color1, FALSE);
        XtSetMappedWhenManaged(pseudo->color2, FALSE);
	pseudo->palette = create_color_palette(parent, pseudo->color1, NULL);

	/*
         *  Create the colorspace pseudo display.
         */
	pseudo->rgb_back = create_pseudo_back(parent, "R", "G", "B",
			red, green, blue, red, green, blue,
			pseudo->rgb, pseudo->palette, NULL);
	pseudo->cmy_back = create_pseudo_back(parent, "C", "M", "Y",
			cyan, magenta, yellow, cyan, magenta, yellow,
			pseudo->cmy, pseudo->palette, NULL);
	pseudo->hsv_back = create_pseudo_back(parent, "H", "S", "V",
			black, black, black, white, white, white,
			pseudo->hsv, pseudo->palette, NULL);
	pseudo->hls_back = create_pseudo_back(parent, "H", "L", "S",
			black, black, black,  white, white, white,
			pseudo->hls, pseudo->palette, NULL);
	pseudo->yiq_back = create_pseudo_back(parent, "Y", "I", "Q",
			black, black, black,  white, white, white,
			pseudo->yiq, pseudo->palette, NULL);
	pseudo->uvw_back = create_pseudo_back(parent, "U", "V", "W",
			black, black, black, white, white, white,
			pseudo->uvw, pseudo->palette, NULL);
	pseudo->xyz_back = create_pseudo_back(parent, "X", "Y", "Z",
			black, black, black, white, white, white,
			pseudo->xyz, pseudo->palette, NULL);
	pseudo->grey_back = create_pseudo_back(parent, "G", NULL, NULL,
			black, black, black,  white, white, white,
			pseudo->grey, pseudo->palette, NULL);

        pseudo->model = RGB;
	XtMapWidget(pseudo->rgb_back);
	XRaiseWindow(XtDisplay(pseudo->rgb_back), XtWindow(pseudo->rgb_back));
}


/****************************************************************
*
* Routine Name:  create_lut_display 
*
*
*      Purpose:  creates the lookup table display on the lookup table 
*	         workspace that is part of the user interface. 
*
*        Input:  parent - the workspace on which the lookup table widget 
*		 will be created
*
*       Output:  none 
*
*   Written By:  Mark Young & Danielle Argiro
*
****************************************************************/

create_lut_display(parent)

Widget parent;
{
	int      i;
        Arg      args[MaxArgs];
	Widget   create_lut_back(); 
	void	 refresh_palette(), undo_cb();

	lut = (LutStructure *) malloc(sizeof(LutStructure));
        lut->toplevel  = parent;
        lut->hist_type = Continuous;
        lut->histogram = True;

	lut_width  = 350;
        lut_height = 100;
        lut_xpos   = -1;
        lut_ypos   = -1;


	i = 0;
	XtSetArg(args[i], XtNfromVert, NULL);                   i++;
	XtSetArg(args[i], XtNfromHoriz, NULL);			i++;
        XtSetArg(args[i], XtNheight, 30);                       i++;
        XtSetArg(args[i], XtNlabel, "UNDO");                	i++;
	lut->undo = XtCreateManagedWidget("Undo", commandWidgetClass,
                                              parent, args, i);
	XtAddCallback(lut->undo,XtNcallback, undo_cb, NULL);

	/*
	 *  Create the lookup table palette.
	 */
	i = 0;
	XtSetArg(args[i], XtNforeground, black);                i++;
	XtSetArg(args[i], XtNbackground, black);                i++;
	XtSetArg(args[i], XtNborderColor, black);               i++;
	XtSetArg(args[i], XtNfromVert, NULL); 		        i++;
	XtSetArg(args[i], XtNhorizDistance, 10);		i++;
	XtSetArg(args[i], XtNfromHoriz, lut->undo);             i++;
	XtSetArg(args[i], XtNwidth, (Dimension) 350);           i++;
	XtSetArg(args[i], XtNheight, (Dimension) 30);           i++;
	lut->palette = XtCreateManagedWidget("palette", 
				formWidgetClass, parent, args, i);

	XtAddEventHandler(lut->palette, ExposureMask, False, refresh_palette,
			  NULL);
	lut->rgb_back = create_lut_back(parent, "Red", "Green", "Blue",
				red, green, blue, red, green, blue,
				lut->rgb, lut->palette, NULL);
	lut->cmy_back = create_lut_back(parent, "Cyan", "Magenta", "Yellow",
				cyan, magenta, yellow, cyan, magenta, yellow,
				lut->cmy, lut->palette, NULL);
	lut->hsv_back = create_lut_back(parent, "Hue", "Saturation", "Value",
				black, black, black, white, white, white,
				lut->hsv, lut->palette, NULL);
	lut->hls_back = create_lut_back(parent, "Hue", "Luminance","Saturation",
				black, black, black, white, white, white,
				lut->hls, lut->palette, NULL);
	lut->yiq_back = create_lut_back(parent, "Y", "I","Q",
				black, black, black, white, white, white,
				lut->yiq, lut->palette, NULL);
	lut->uvw_back = create_lut_back(parent, "U", "V","W",
				black, black, black, white, white, white,
				lut->uvw, lut->palette, NULL);
	lut->xyz_back = create_lut_back(parent, "X", "Y","Z",
				black, black, black, white, white, white,
				lut->xyz, lut->palette, NULL);
	lut->grey_back = create_lut_back(parent, "Grey", NULL, NULL,
				black, black, black, white, white, white,
				lut->grey, lut->palette, NULL);

        lut->model = RGB;
        lut->current_lut = lut->rgb;
	lut->active_canvas = NULL;
	XtMapWidget(lut->rgb_back);
	XRaiseWindow(XtDisplay(lut->rgb_back), XtWindow(lut->rgb_back));
}


/****************************************************************
*
* Routine Name:  create_thres_display 
*
*
*      Purpose:  creates the threshold display on the threshold
*	         workspace that is part of the user interface. 
*
*        Input:  parent - the workspace on which the threshold widget 
*		 will be created
*
*       Output:  none 
*
*   Written By:  Mark Young & Danielle Argiro
*
****************************************************************/

create_thres_display(parent)

Widget parent;
{
	int       i;
        Arg      args[MaxArgs];
	Widget   scroll_back, create_thres_scrollbar();
	void	 refresh_palette(), thres_reset_cb();

	thres = (ThresStructure *) malloc(sizeof(ThresStructure));
        thres->toplevel = parent;
	thres->mode   = Windowing;
	thres->accept = True;
	thres->invert = False;
	thres->fill_pixel = 0;
	thres->nonzero_pixel = 255;

	thres->lower = (ScrollStruct *) malloc(sizeof(ScrollStruct));
	thres->upper = (ScrollStruct *) malloc(sizeof(ScrollStruct));
	thres->range = (ScrollStruct *) malloc(sizeof(ScrollStruct));


	i = 0;
	XtSetArg(args[i], XtNfromVert, NULL);                   i++;
	XtSetArg(args[i], XtNfromHoriz, NULL);			i++;
        XtSetArg(args[i], XtNheight, 30);                       i++;
        XtSetArg(args[i], XtNlabel, "RESET");                	i++;
        XtSetArg(args[i], XtNhorizDistance, 10);                	i++;
	thres->reset = XtCreateManagedWidget("RESET", commandWidgetClass,
                                              parent, args, i);
	XtAddCallback(thres->reset,XtNcallback, thres_reset_cb, NULL);

	/*
	 *  Create the threshold palette.
	 */
	i = 0;
	XtSetArg(args[i], XtNforeground, black);                i++;
	XtSetArg(args[i], XtNbackground, white);                i++;
	XtSetArg(args[i], XtNborderColor, black);               i++;
	XtSetArg(args[i], XtNfromVert, NULL);                   i++;
	XtSetArg(args[i], XtNfromHoriz, thres->reset);            i++;
	XtSetArg(args[i], XtNwidth, (Dimension) 256);           i++;
	XtSetArg(args[i], XtNheight, (Dimension) 30);           i++;
	thres->palette = XtCreateManagedWidget("palette", 
				formWidgetClass, parent, args, i);

	XtAddEventHandler(thres->palette, ExposureMask, False,
			refresh_palette, NULL);


	/*
  	 *  Create the lower scroll bar
	 */
	thres->lower->num = 0;
	scroll_back = create_thres_scrollbar(thres, thres->lower, "lower",
			black, red, parent, thres->palette, NULL);
	update_int_scroll(thres->lower, thres->lower->num, xvdisplay->pixelmax,
			xvdisplay->pixelmin, xvdisplay->pixelmax);

	/*
  	 *  Create the upper scroll bar
	 */
	thres->upper->num = 255;
	scroll_back = create_thres_scrollbar(thres, thres->upper, "upper", red,
			black, parent, scroll_back, NULL);
	update_int_scroll(thres->upper, thres->upper->num, xvdisplay->pixelmax,
			xvdisplay->pixelmin, xvdisplay->pixelmax);

	/*
  	 *  Create the upper scroll bar
	 */
	thres->range->num = 255;
	scroll_back = create_thres_scrollbar(thres, thres->range, "range", red,
			black, parent, scroll_back, NULL);
	update_int_scroll(thres->range, thres->lower->num, thres->upper->num,
			xvdisplay->pixelmin, xvdisplay->pixelmax);
}


void undo_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
	int index, num;


	if (!pop_cstack(xvdisplay->xcolors, &index1, &index2))
	   return;

	index = MIN(index1, index2);
	num = abs(index2 - index1) +1;
	store_colors(xvdisplay->xcolors, index, num);
}
