 /*
  * Khoros: $Id$
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id$";
#endif

 /*
  * $Log$
  */ 

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1991, 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 to 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 1991 by UNM */

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 >>>>
 >>>>  		        Scroll Utility Routines
 >>>>
 >>>>			create_legend_scrollbars()
 >>>>			create_legend_scrollbar()
 >>>>			create_scroll_value()
 >>>>			update_scroll()
 >>>>			update_legend_incr()
 >>>>			update_legend_cont()
 >>>>
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/

#include "spectrum.h"

/****************************************************************
*
* Routine Name:  create_legend_scrollbars
*
*
*      Purpose:  creates each individual backplane for 3 scrollbars
*		 in each of the color spaces (ie RGB, HSV, YIQ, etc).
*
*        Input:  parent: the parent for the back plane to lie on
*                label1: label for the first color widget
*                label2: label for the second color widget
*                label3: label for the third color widget
*                (note: if any label is NULL then the widget won't be created).
*                color1: color for the first widget label
*                color2: color for the second widget label
*                color3: color for the third widget label
*                pixel1: color for the first legend structure
*                pixel2: color for the second legend structure
*                pixel3: color for the third legend structure
*                scrolls: the scroll structures to be filled with the scrollbars
*                vertical:  the widget to vertically offset the back from
*                horizontal: the widget to horizontally offset the back from
*
*       Output:  back:  the back plane where the legend scrollbars will lie.
*                scrolls: the color space widgets to be created (calls
*                create_legend_scrollbar to actually create each widget).
*
*   Written By:  Mark Young & Danielle Argiro
*
****************************************************************/

Widget create_legend_scrollbars(parent,label1, label2, label3, color1, 
				color2, color3, pixel1, pixel2, pixel3, 
			 	scrolls, vertical, horizontal)

Widget    parent, vertical, horizontal;
char      *label1, *label2, *label3;
unsigned  long color1, color2, color3,
               pixel1, pixel2, pixel3;
ScrollStruct  *scrolls;
{
        int     i;
        Arg     arg[MaxArgs];
        Widget  back, widget = NULL;

        /*
         *  Create the backplane for the set of 3 scrollbars
         */
        i = 0;
        XtSetArg(arg[i], XtNforeground, black);                i++;
        XtSetArg(arg[i], XtNbackground, white);                i++;
        XtSetArg(arg[i], XtNborderColor, black);               i++;
        XtSetArg(arg[i], XtNwidth, (Dimension) 390);           i++;
        XtSetArg(arg[i], XtNheight, (Dimension) 120);          i++;
        XtSetArg(arg[i], XtNfromVert, vertical);               i++;
        XtSetArg(arg[i], XtNfromHoriz, horizontal);            i++;
        back = XtCreateManagedWidget("back", formWidgetClass, parent, arg, i);

        if (label1 != NULL)
        {
	   scrolls[0].id = 0;
           widget = create_legend_scrollbar(&scrolls[0], label1, color1,
                                            pixel1, back, widget, NULL);
           scrolls[0].num = 0.0;
           scrolls[0].pixel = color1;
        }
        if (label2 != NULL)
        {
	   scrolls[1].id = 1;
           widget = create_legend_scrollbar(&scrolls[1], label2, color2,
                                            pixel2, back, widget, NULL);
           scrolls[1].num = 0.0;
           scrolls[1].pixel = color2;
        }
        if (label3 != NULL)
        {
	   scrolls[2].id = 2;
           widget = create_legend_scrollbar(&scrolls[2], label3, color3,
                                            pixel3, back, widget, NULL);
           scrolls[2].num = 0.0;
           scrolls[2].pixel = color3;
        }

        return(back);
}

/****************************************************************
*
* Routine Name:  create_legend_scrollbar
*
*
*      Purpose:  creates the scroll bars on the legend display 
*		 with which the user will be able to spectify the
*		 desired color for the (range of) pixel(s)
*
*        Input:  id	     - indicates scroll bar 0, 1, or 2
*		 scroll_data - scroll structure
*                label       - label for the scroll bar
*                color       - color value for label foreground (color)
*                pixel       - pixel value for scroll bar foreground (color)
*                parent      - parent of the scroll bar widget
*                vertical    - widget from which to do vertical offset
*                horizontal  - widget from which to do horizontal offset
*
*
*       Output:  returns the Widget backplane of the scroll bar
*
*   Written By:  Mark Young & Danielle Argiro
*
****************************************************************/

Widget create_legend_scrollbar(scroll_data, label, color, pixel, 
			       parent, vertical, horizontal)
ScrollStruct  *scroll_data;
char    *label;
unsigned long color, pixel;
Widget  parent, vertical, horizontal;
{
        int     i;
        Arg     arg[15];
        Widget  back, colorname;



        i = 0;
        XtSetArg(arg[i], XtNwidth, 360);                       i++;
        XtSetArg(arg[i], XtNheight, 30);                       i++;
        XtSetArg(arg[i], XtNfromVert, vertical);               i++;
        XtSetArg(arg[i], XtNfromHoriz, horizontal);            i++;
        XtSetArg(arg[i], XtNforeground, black);                i++;
        XtSetArg(arg[i], XtNbackground, white);                i++;
        XtSetArg(arg[i], XtNborderColor, black);               i++;
        back = XtCreateManagedWidget(label, formWidgetClass,
                                     parent, arg, i);

        i = 0;
        XtSetArg(arg[i], XtNlabel, label);                     i++;
        XtSetArg(arg[i], XtNfromVert, NULL);                   i++;
        XtSetArg(arg[i], XtNfromHoriz, NULL);                  i++;
        XtSetArg(arg[i], XtNforeground, color);                i++;
        XtSetArg(arg[i], XtNbackground, white);                i++;
        XtSetArg(arg[i], XtNborderColor, black);               i++;
        colorname = XtCreateManagedWidget("colorname", labelWidgetClass,
                                           back, arg, i);
        i = 0;
        XtSetArg(arg[i], XtNfromVert, NULL);                   i++;
        XtSetArg(arg[i], XtNfromHoriz, colorname);             i++;
        XtSetArg(arg[i], XtNx, 0);                             i++;
        XtSetArg(arg[i], XtNy, 0);                             i++;
        XtSetArg(arg[i], XtNorientation, XtorientHorizontal);  i++;
        XtSetArg(arg[i], XtNwidth, 256);                       i++;
        XtSetArg(arg[i], XtNheight, 16);                       i++;
        XtSetArg(arg[i], XtNshown, 1.0);                       i++;
        XtSetArg(arg[i], XtNtopOfThumb, 0.0);                  i++;
        XtSetArg(arg[i], XtNforeground, pixel);                i++;
        XtSetArg(arg[i], XtNbackground, black);                i++;
        XtSetArg(arg[i], XtNborderColor, white);            i++;
        scroll_data->scrollbar = XtCreateManagedWidget("scrollbar",
                                scrollbarWidgetClass, back, arg, i);
        scroll_data->string = xvf_strcpy(" 0   ");
        create_scroll_value(back, scroll_data, xvf_strlen(scroll_data->string));

	XawScrollbarSetThumb(scroll_data->scrollbar, 1.0, 1.0);

        XtAddCallback(scroll_data->scrollbar, XtNscrollProc, update_legend_incr,
                      (caddr_t) scroll_data);
        XtAddCallback(scroll_data->scrollbar, XtNjumpProc, update_legend_cont,
                      (caddr_t) scroll_data);
        return(back);
}

/****************************************************************
*
* Routine Name:  create_scroll_value
*
*      Purpose:  Creates the value widget to the right of a scroll
*                bar which has the value represented by the scroll
*                bar.  The value can be when the user enters a new
*                value in the text widget and hits <cr>
*
*        Input:  parent      - backplane of the value widget
*                scroll_data - the ScrollStruct of the current scrollbar
*                length      - the length of the value widget in characters
*
*       Output:  none
*
*   Written By:  Danielle Argiro & Mark Young
*
****************************************************************/

create_scroll_value(parent, scroll_data, length)

Widget parent;
ScrollStruct *scroll_data;
int    length;
{
        int i;
        Arg args[MaxArgs];

        XtTranslations  scroll_trans;
        static char scroll_trans_table[] =
                        "<Key>0xff0d:   update_scroll() \n\
                        Ctrl<Key>x:    beginning-of-file()";

        static XtActionsRec scroll_actionTable[] = {
                  { "update_scroll",  update_scroll}, };

        /*
         *  Create the scroll's value widget.
         */
        i = 0;
        XtSetArg(args[i], XtNeditType,XawtextEdit);                     i++;
        XtSetArg(args[i], XtNtype,XawAsciiString);                      i++;
        XtSetArg(args[i], XtNstring, scroll_data->string);              i++;
        XtSetArg(args[i], XtNfromVert, NULL);                           i++;
        XtSetArg(args[i], XtNfromHoriz, scroll_data->scrollbar);        i++;
        XtSetArg(args[i], XtNinsertPosition, 
			  xvf_strlen(scroll_data->string)); 		i++;
        XtSetArg(args[i], XtNwidth, length*xvf_font_width);             i++;
        XtSetArg(args[i], XtNforeground, black);                        i++;
        XtSetArg(args[i], XtNbackground, white);                        i++;
        XtSetArg(args[i], XtNborderColor, black);                       i++;
        scroll_data->value = XtCreateManagedWidget("value", 
			     asciiTextWidgetClass, parent, args, i);

        XtAppAddActions(xvf_app_context, scroll_actionTable,
                        XtNumber(scroll_actionTable));

        scroll_trans = XtParseTranslationTable(scroll_trans_table);
        XtOverrideTranslations(scroll_data->value, scroll_trans);
}


/****************************************************************
*
* Routine Name:  update_scroll
*
*      Purpose:  This is the Action Procedure that gets called when
*		 the user hits <cr> in the value widget of the scroll
*		 selection.  It updates the scroll bar according to 
*		 the value entered.
*
*        Input:  widget     - the value widget
*		 event, params, num_params - not used
*		
*       Output:  updates the scroll bar
*
*   Written By:  Danielle Argiro
*
****************************************************************/

void update_scroll(widget, event, params, num_params)
Widget widget;
XEvent *event;
String *params;
Cardinal *num_params;
{
    	int i;
    	double  value, atof();
    	ScrollStruct *scroll_data, *ident_legend_scroll();
    	Arg args[MaxArgs];
	char *string_return;

	scroll_data = ident_legend_scroll(widget);

	i = 0;
        XtSetArg(args[i], XtNstring, &string_return);    i++;
        XtGetValues(scroll_data->value, args, i);
        value = atof(string_return);

	set_scroll_thumb_to_value(scroll_data, value);
	
	scroll_data->string = xvf_strcpy(string_return);
	update_legend_color(scroll_data->id,  scroll_data->num, True);
}


/****************************************************************
*
* Routine Name:  set_scroll_thumb_to_value
*
*      Purpose:  given a value, sets the scroll thumb to that value
*
*        Input:  scroll_data - pointer to structure of scroll bar in question
*		 value - value to set thumb to
*
*       Output:  updates position of scroll bar thumb
*
*   Written By:  Danielle Argiro
*
****************************************************************/

set_scroll_thumb_to_value(scroll_data, value)
ScrollStruct *scroll_data;
double value;
{
	float percent;

	scroll_data->num = value;

        if (spc_color_model == SpcRGB || spc_color_model == SpcCMY ||
            spc_color_model == SpcGREY)
        {
	    if (scroll_data->num < 0.0) scroll_data->num = 0.0;
	    else if (scroll_data->num > spc_max_colors-1.0) 
		scroll_data->num = spc_max_colors-1.0;
	    percent = (1.0 - ((float) scroll_data->num /
		      (float) (spc_max_colors-1)));
	    XawScrollbarSetThumb(scroll_data->scrollbar, percent, 1.0);
	}
	else
	{
	    if (scroll_data->num < 0.0) scroll_data->num = 0.0;
	    else if (scroll_data->num > 1.0) scroll_data->num = 1.0;
	    XawScrollbarSetThumb(scroll_data->scrollbar, 
				(1.0 - scroll_data->num), 1.0);
	}
}

/****************************************************************
*
* Routine Name:  update_legend_incr
*
*      Purpose:  Updates the colors of the colorbox and corresponding
*		 clusters in image as the user moves the slider on
*		 the color scroll bars incrementally using left or right
*		 mouse buttons.
*
*        Input:  widget - the scrollbar widget to be identified
*                clientData -  not used
*                event      -  the event
*		
*       Output:  none
*
*   Written By:  Danielle Argiro
*
****************************************************************/

#define SpcScrollIncr 10

void update_legend_incr(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
        int     direction = (int) callData;
        ScrollStruct *scroll_data = (ScrollStruct *) clientData;
	float percent;

	if (direction < 0)
	{
	    if (spc_color_model == SpcRGB || spc_color_model == SpcCMY ||
                spc_color_model == SpcGREY)
            {
	        scroll_data->num -= SpcScrollIncr;
	        if (scroll_data->num < 0.0) scroll_data->num = 0.0;
	        percent = (1.0 - ((float) scroll_data->num /
			  (float)(spc_max_colors-1)));
	        XawScrollbarSetThumb(scroll_data->scrollbar, percent, 1.0);
	    }
	    else
	    {
		scroll_data->num -= SpcScrollIncr/256.0;
                if (scroll_data->num < 0.0) scroll_data->num = 0.0;
	        XawScrollbarSetThumb(scroll_data->scrollbar, 
				     (1.0 - scroll_data->num), 1.0);
	    }
	}
	else if (direction > 0)
	{
	    if (spc_color_model == SpcRGB || spc_color_model == SpcCMY ||
                spc_color_model == SpcGREY)
            {
	        scroll_data->num += SpcScrollIncr;
                if (scroll_data->num > spc_max_colors - 1)
                     scroll_data->num = spc_max_colors - 1;
	        percent = (1.0 - ((float) scroll_data->num /
			  (float)(spc_max_colors-1)));
	        XawScrollbarSetThumb(scroll_data->scrollbar, percent, 1.0);
	    }
	    else
	    {
	        scroll_data->num += SpcScrollIncr/256.0;
                if (scroll_data->num > 1.0) scroll_data->num = 1.0;
	        XawScrollbarSetThumb(scroll_data->scrollbar, 
				     (1.0 - scroll_data->num), 1.0);
	    }
	}

        set_scroll_value_displayed(scroll_data, scroll_data->num);
	update_legend_color(scroll_data->id, scroll_data->num, False);
}


/****************************************************************
*
* Routine Name:  set_scroll_value_displayed
*
*      Purpose:  sets the value displayed in the text widget to specified value
*
*        Input:  scroll_data - pointer to structure of scroll bar in question
*		 value - value to set thumb to
*
*       Output:  updates number displayed in scroll bar text widget
*
*   Written By:  Danielle Argiro
*
****************************************************************/

set_scroll_value_displayed(scroll_data, value)
ScrollStruct *scroll_data;
double value;
{
	char temp[MaxLength];
	XawTextBlock text_block;
	int status;

        if (spc_color_model == SpcRGB || spc_color_model == SpcCMY ||
            spc_color_model == SpcGREY)
        {
            sprintf(temp,"%d", (int) scroll_data->num);
        }
	else
	{
            sprintf(temp,"%0.3f", scroll_data->num);
	}

	text_block.firstPos = 0;
   	text_block.length = xvf_strlen(temp);
   	text_block.ptr = temp;
   	text_block.format = FMT8BIT;

	status = XawTextReplace(scroll_data->value, (XawTextPosition)0,
                         (XawTextPosition) xvf_strlen(scroll_data->string),
                         &text_block);
	XawTextDisplay(scroll_data->value);

	if (status == XawPositionError)
   	{
           fprintf(stderr, "\nupdate_legend_incr:\n");
           fprintf(stderr,"      ERROR: XawPositionError\n");
   	}
   	else if (status == XawEditError)
   	{
       	    fprintf(stderr, "\nupdate_legend_incr:\n");
       	    fprintf(stderr,"      ERROR: XawEditError\n");
   	}
	scroll_data->string = xvf_strcpy(temp);
}

/****************************************************************
*
* Routine Name:  update_legend_cont
*
*      Purpose:  Updates the colors of the colorbox and corresponding
*		 clusters in image as the user moves the slider on
*		 the color scroll bars continuously using middle button.
*
*        Input:  widget - the scrollbar widget to be identified
*                clientData -  not used
*                event      -  the event
*		
*       Output:  none
*
*   Written By:  Danielle Argiro
*
****************************************************************/


void update_legend_cont(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
	float *movement = (float *) callData;
        ScrollStruct *scroll_data = (ScrollStruct *) clientData;
        char temp[MaxLength];

	if (spc_color_model == SpcRGB || spc_color_model == SpcCMY ||
            spc_color_model == SpcGREY)
	{
	    scroll_data->num = ((1 - *movement) * (spc_max_colors-1));
	    sprintf(temp,"%d", (int) scroll_data->num);
	}
	else
	{
	    scroll_data->num = (1.0 - *movement);
	    sprintf(temp,"%0.3f", scroll_data->num);
	}
	
	set_scroll_value_displayed(scroll_data, scroll_data->num);
	update_legend_color(scroll_data->id, scroll_data->num, True);

}


/****************************************************************
*
* Routine Name:  ident_legend_scroll
*
*      Purpose:  The problem with Action Procedures under X11R4 is
*		 that we can't figure out how to pass parameters 
*		 correctly.  So this routine is necessary to figure
*		 out (if the scroll bar in question was on the legend display)
*		 which scrollbar initiated the Action Procedure update_scroll()
*
*        Input:  widget - the scrollbar widget to be identified
*		
*       Output:  none
*
*   Written By:  Danielle Argiro
*
****************************************************************/


ScrollStruct *ident_legend_scroll(widget)
Widget widget;
{
	if (widget == display_ptr->rgb[0].value) 
	    return(&display_ptr->rgb[0]);
	else if (widget == display_ptr->rgb[1].value) 
	    return(&display_ptr->rgb[1]);
     	else if (widget == display_ptr->rgb[2].value) 
            return(&display_ptr->rgb[2]);

      	else if (widget == display_ptr->cmy[0].value) 
            return(&display_ptr->cmy[0]);
      	else if (widget == display_ptr->cmy[1].value) 
            return(&display_ptr->cmy[1]);
      	else if (widget == display_ptr->cmy[2].value) 
            return(&display_ptr->cmy[2]);

      	else if (widget == display_ptr->hsv[0].value) 
            return(&display_ptr->hsv[0]);
      	else if (widget == display_ptr->hsv[1].value) 
            return(&display_ptr->hsv[1]);
      	else if (widget == display_ptr->hsv[2].value) 
            return(&display_ptr->hsv[2]);

      	else if (widget == display_ptr->hls[0].value) 
            return(&display_ptr->hls[0]);
      	else if (widget == display_ptr->hls[1].value) 
            return(&display_ptr->hls[1]);
      	else if (widget == display_ptr->hls[2].value) 
            return(&display_ptr->hls[2]);

      	else if (widget == display_ptr->grey[0].value) 
            return(&display_ptr->grey[0]);
}

/****************************************************************
*
* Routine Name:  get_legend_scroll
*
*      Purpose:  The problem with Action Procedures under X11R4 is
*		 that we can't figure out how to pass parameters 
*		 correctly.  So this routine is necessary to figure
*		 out (if the scroll bar in question was on the legend display)
*		 which scrollbar initiated the Action Procedure update_scroll()
*
*        Input:  id
*		
*       Output:  scroll_data
*
*   Written By:  Danielle Argiro
*
****************************************************************/
ScrollStruct *get_legend_scroll(id)
int id;
{
	switch(spc_color_model)
        {
            case SpcRGB:
		 return(&display_ptr->rgb[id]);
		 break;

	    case SpcCMY:
		 return(&display_ptr->cmy[id]);
		 break;
	    
	    case SpcHSV:
                 return(&display_ptr->hsv[id]);
		 break;

	    case SpcHLS:
                 return(&display_ptr->hls[id]);
		 break;

	    case SpcGREY:
                 return(&display_ptr->grey[0]);
		 break;
	}
}
