 /*
  * 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 */

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 >>>>
 >>>>  		        Legend Drivers
 >>>>
 >>>>			run_legend_subform()
 >>>>			run_legend()
 >>>>			hide_or_show()
 >>>>			delete_or_empty()
 >>>>			empty_class()
 >>>>			catch_all()
 >>>>
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/

#include "spectrum.h"


/********************************************************
*
*  Routine Name:  run_legend_subform
*
*       Purpose:  drives the subform 'legend_subform'
*
*         Input:  form - pointer to the form tree 
*		  legend_subform_info  - information structure for subform 'legend_subform'
*        Output:  action of the application program
*
*     Called By:  run_master()
*
*   Automatically Generated By:  conductor -i spectrum.form -l 3 -b
*
********************************************************/


run_legend_subform(form, legend_subform_info)

xvf_form *form;
master_legend_subform *legend_subform_info;
{

	_xvf_get_legend_subform(form, legend_subform_info);

	/*
	 * action came from the 'legend' pane
	 */
	if (legend_subform_info->legend_selected)
	    run_legend(form, legend_subform_info->legend);


}   /* end run_legend_subform */




/********************************************************
*
*  Routine Name:  run_legend
*
*       Purpose:  drives the pane 'legend'
*
*         Input:  form - pointer to the form tree 
*		  legend_info  - information structure for pane 'legend'
*        Output:  action of the application program
*
*     Called By:  run_legend_subform()
*
*   Automatically Generated By:  conductor -i spectrum.form -l 3 -b
*
********************************************************/

#define Delete 1
#define Empty  2

run_legend(form, legend_info)

xvf_form *form;
legend_subform_legend *legend_info;
{
	Widget back;

	_xvf_get_legend(form, legend_info);

	/*
	 * user clicked on 'live' toggle selection 'color_model'
	 */
	if (legend_info->color_model_selected)
	{
	    spc_color_model = legend_info->color_model_val;
	    switch (spc_color_model)
	    {
		case SpcRGB:  back = display_ptr->rgb_back;  break;
		case SpcCMY:  back = display_ptr->cmy_back;  break;
                case SpcHSV:  back = display_ptr->hsv_back;  break;
                case SpcHLS:  back = display_ptr->hls_back;  break;
                case SpcGREY: back = display_ptr->grey_back; break;
	    }
	    XtMapWidget(back);
            XRaiseWindow(display, XtWindow(back));
	}

	/*
	 * user clicked on pane action button 'delete'
	 */
	else if (legend_info->delete)
	{
	    delete_or_empty(Delete);
	}

	/*
	 * user clicked on pane action button 'empty'
	 */
	else if (legend_info->empty)
	{
	    delete_or_empty(Empty);
	}

	/*
	 * user clicked on pane action button 'show'
	 */
	else if (legend_info->show)
	{
	    hide_or_show(SpcDisplayed);
	}

	/*
	 * user clicked on pane action button 'hide'
	 */
	else if (legend_info->hide)
	{
	    hide_or_show(SpcHidden);
	}

	/*
	 * user clicked on pane action button 'catch_all'
	 */
	else if (legend_info->catch_all)
	{
	    catch_all();
	}

	/*
	 * user clicked on pane action button 'transfer'
	 */
	else if (legend_info->transfer)
	{
	    transfer_classes();
	}
}

/********************************************************
*
*  Routine Name:  hide_or_show
*
*       Purpose:  prompts the user for the category(s) to be
*		  either hidden or shown, and either hides or shows them.
*         Input:  flag - indicates whether to Hide or Show a class
*        Output:  none
*     Called By:  run_legend()
*    Written By:  Danielle Argiro
*
********************************************************/

hide_or_show(flag)
int flag;
{
	int  i, size, num, disp_set, cat_flag;
	legend_list *legend_ptr;
        XawListReturnStruct **class_list_return;
	char **classnames;
	char *error_mesg_none, *error_mesg_all, *prompt, *label;
	char *error_mesgNH = "No class categories to hide.",
	     *error_mesgNS = "No class categories to show.",
	     *error_mesgAH = "All class categories already hidden.",
	     *error_mesgAS = "All class categories already shown.",
             *promptH = "Select classes to hide", 
	     *promptS = "Select classes to display",
	     *labelH  = "Currently Displayed Classes",
	     *labelS  = "Currently Hidden Classes";

	/* set relevant I/0 strings */

	if (flag == SpcHidden)
	{
	    error_mesg_none = error_mesgNH;
	    error_mesg_all  = error_mesgAH;
	    prompt = promptH;
	    label  = labelH;
	    disp_set = true;
	    cat_flag = SpcDisplayed;
	}
	else if (flag == SpcDisplayed)
	{
	    error_mesg_none = error_mesgNS;
	    error_mesg_all  = error_mesgAS;
	    prompt = promptS;
	    label  = labelS;
	    disp_set = false;
	    cat_flag = SpcHidden;
	}

	if (spc_legend_list == NULL)
	{
 	    xvf_error_wait(error_mesg_none, "Spectrum", NULL);
	    return;
	}

	classnames = create_category_list(NULL, cat_flag, &size, NULL, 0);
	if (size == 0)
	{
	    xvf_error_wait(error_mesg_all, "Spectrum", NULL);
	    return;
	}

	else if (size == 1)
	{
	    legend_ptr = find_legend_from_text(classnames[0]);
	    legend_ptr->hidden = disp_set;
	    if (flag == SpcHidden)
	        restore_old_values(legend_ptr, -1);
	}
	else
	{
	    class_list_return =  xvf_run_list_multsel_wait(classnames, 
				 size, 1, prompt, label, False, False, &num);
	    if (class_list_return == NULL) return;
	    for (i = 0; i < num; i++)
	    {
		legend_ptr= find_legend_from_text(class_list_return[i]->string);
		legend_ptr->hidden = disp_set; 
	        if (flag == SpcHidden)
		    restore_old_values(legend_ptr, -1);
	    }
	}
	update_xcolors_from_legend();
	free(classnames);
	free(class_list_return);
}


/********************************************************
*
*  Routine Name:  delete_or_empty
*
*       Purpose:  prompts the user for the category(s) to be
*		  either deleted or emptied, and either deletes
*		  or empties them.
*         Input:  flag - indicates whether to Delete or Empty a class  
*        Output:  none
*     Called By:  run_legend()
*    Written By:  Danielle Argiro
*
********************************************************/

delete_or_empty(flag)
int flag;
{
	int  i, size, num, cat_flag;
        legend_list *legend_ptr;
        XawListReturnStruct **class_list_return;
        char **classnames, temp[MaxLength], temp2[MaxLength];
        char *error_mesg_none, *prompt, *label;
        char *error_mesgND = "No class categories to delete",
	     *error_mesgNE = "No class categories to empty",
	     *promptD1 = "Select classes to delete",
             *promptE1 = "Select classes to empty",
	     *promptD2 = "Delete class category(s): ",
	     *promptE2 = "Empty class category(s): ",
             *labelD   = "Current classes",
             *labelE   = "Current Classes w/ Clusters";

	/* delete */
	if (flag == Delete)
        {
            error_mesg_none = error_mesgND;
            prompt = promptD1;
            label  = labelD;
	    cat_flag = SpcAll;
	}
	/* empty */
	else if (flag == Empty)
	{
            error_mesg_none = error_mesgNE;
            prompt = promptE1;
            label  = labelE;
	    cat_flag = SpcNotEmpty;
	}

	if (spc_lgd_classnum == 0)
        {
            xvf_error_wait(error_mesg_none, "Spectrum", NULL);
            return;
	}
	classnames = create_category_list(NULL, cat_flag, &size, NULL, 0);

	if (size == 1)
        {
	    legend_ptr = find_legend_from_text(classnames[0]);
	    if (flag == Delete)
	         delete_legend_entry(legend_ptr, False);
	    else if (flag == Empty)
		empty_class(legend_ptr);
	}
	else
	{
	    class_list_return =  xvf_run_list_multsel_wait(classnames, 
			         size, 1, prompt, label, 
			         False, False, &num);
	    if (class_list_return == NULL) return;

	    if (flag == Delete)     sprintf(temp2, promptD2);
	    else if (flag == Empty) sprintf(temp2, promptE2);

	    for (i = 0; i < num; i++)
	    {
	        sprintf(temp, "%s", class_list_return[i]->string);
	        if (i < num-1) strcat(temp, ", ");
	        strcat(temp2, temp);
	    }
	    strcat(temp2, "?");
	    if (!(xvf_warn_wait(temp2, "Spectrum", NULL, NULL)))
	        return;

	    for (i = 0; i < num; i++)
            {
	        legend_ptr= find_legend_from_text(class_list_return[i]->string);
	        if (flag == Delete)
	    	    delete_legend_entry(legend_ptr, False);
		else if (flag == Empty)
		    empty_class(legend_ptr);
	    }
	}
	/* update w/ remaining colors in legend */
	update_xcolors_from_legend();
	free(classnames);
	free(class_list_return);
}

/********************************************************
*
*  Routine Name:  empty_class
*
*       Purpose:  empties the class represented by the legend_ptr passed in
*         Input:  legend_ptr - represents class to be emptied 
*        Output:  none
*     Called By:  delete_or_empty()
*    Written By:  Danielle Argiro
*
********************************************************/

empty_class(legend_ptr)
legend_list *legend_ptr;
{
	int i, total_clusters;

	restore_old_values(legend_ptr, -1);
	total_clusters = legend_ptr->clusternum;
	for (i = total_clusters-1; i >= 0; i--)
	    delete_cluster_from_class(legend_ptr, legend_ptr->clusters[i]);
	update_colorbox_from_legend(legend_ptr);
}


/********************************************************
*
*  Routine Name:  catch_all
*
*       Purpose:  dumps all unassigned clusters into a 
*		  "catch-all" category.
*         Input:  none
*        Output:  none
*     Called By:  run_legend()
*    Written By:  Danielle Argiro
*
********************************************************/

catch_all()
{
	int  i, cluster;
	legend_list *legend_ptr;
	char *prompt = "Are you sure you want to dump all remaining clusters into a catch-all category?" ;

	if (spc_lgd_classnum == 0)
        {
            xvf_error_wait("No class categories to transfer", "Spectrum", NULL);
            return;
	}

	if (!(xvf_warn_wait(prompt, "Spectrum", NULL, NULL)))
	     return;

	cluster = 0;
	while (spc_legend_lookup[cluster] != NULL)
	   cluster++;

	if ((legend_ptr = find_legend_from_text("Catch-All Category")) == NULL)
	{
            add_legend_entry(cluster, "Catch-All Category");
	    legend_ptr = current_entry->legend_ptr;
	}
	for (i = cluster; i < spc_map_rownum; i++)
	{
	    if (spc_legend_lookup[i] == NULL)
	    {
		add_cluster_to_class(legend_ptr, i);
	        update_colorbox_from_legend(legend_ptr);
	    }
	}
}


/********************************************************
*
*  Routine Name:  transfer_classes
*
*       Purpose:  transfers chosen category(s) into another
*		  category.
*         Input:  none
*        Output:  none
*     Called By:  run_legend()
*    Written By:  Danielle Argiro
*
********************************************************/

transfer_classes()
{
	int  i, j, k, dummy, src_size, dest_size, src_num, transfer_size;
	char **classnames, **destinations, **exclude_list; 
        legend_list *legend_ptr;
        XawListReturnStruct **source_list_return;
        XawListReturnStruct *dest_list_return;
	char *prompt1 = "Select Source Class(s)",
	     *label1  = "Current Class Categories",
	     *prompt2 = "Select Destination Class",
	     *label2  = "Possible Destination Classes";
	int  *transfer_clusters, total_clusters;

	if (spc_legend_list == NULL)
	{
 	    xvf_error_wait("No class categories to transfer", 
			   "Spectrum", NULL);
	    return;
	}
	classnames = create_category_list(NULL, SpcAll, &src_size, NULL, 0);
	if (src_size == 1)
	{
 	    xvf_error_wait("Only one class category, nowhere to transfer", 
			   "Spectrum", NULL);
	    return;
	}
	
	/*
	 *  create list of source classes to choose from (as many)
	 */
	source_list_return =  xvf_run_list_multsel_wait(classnames, 
			     src_size, 1, prompt1, label1, 
			     False, False, &src_num);
	if (source_list_return == NULL) return;

	/*
	 *  exclude source classes from choices of destination classes
	 */
	exclude_list =  (char **) calloc(1, sizeof(char *));
	for (i = 0; i < src_num; i++)
	{
	    exclude_list[i] = xvf_strcpy(source_list_return[i]->string);
	    exclude_list = (caddr_t *) realloc(exclude_list, 
			(i+2)*sizeof(char *));
	}

	/*
	 *  create list of destination classes to choose from 
	 *  (only one, excluding source classes chosen)
	 */
	destinations = create_category_list(NULL, SpcAll, &dest_size, 
					    exclude_list, src_num);
	dest_list_return = xvf_run_list_wait(destinations, dest_size,
                                             1, prompt2, label2, 
					     &dummy, False);
        if (dest_list_return == NULL) return;

	/*
	 *  collect clusters to be transferred from list of source classes
	 *  save clusters in an integer array
	 */
	k = 0;
	transfer_clusters = (int *) malloc(sizeof(int));  transfer_size = 1;
	for (i = 0; i < src_num; i++)
	{
	    legend_ptr = find_legend_from_text(source_list_return[i]->string);
	    transfer_clusters =  (int *) realloc(transfer_clusters, 
				 (transfer_size+legend_ptr->clusternum) *
				 sizeof(int));
	    transfer_size += legend_ptr->clusternum;

	    total_clusters = legend_ptr->clusternum;
	    for (j = 0; j < total_clusters; j++)
	    {
	       transfer_clusters[k] = legend_ptr->clusters[0];
               delete_cluster_from_class(legend_ptr, transfer_clusters[k++]);
	    }
	    update_colorbox_from_legend(legend_ptr);
	}

	/*
	 *  get clusters from integer array, and add them into chosen class  
	 */
	legend_ptr = find_legend_from_text(dest_list_return->string);
	for (i = 0; i < k; i++)
	    add_cluster_to_class(legend_ptr, transfer_clusters[i]);

	update_colorbox_from_img(legend_ptr);
	update_xcolors_from_legend();
	    
	free(classnames);
	free(exclude_list);
	free(destinations);
	free(source_list_return);
	free(dest_list_return);
}
