/*
 * Copyright(c) 1992 Bell Communications Research, Inc. (Bellcore)
 *                        All rights reserved
 * Permission to use, copy, modify and distribute this material for
 * any purpose and without fee is hereby granted, provided that the
 * above copyright notice and this permission notice appear in all
 * copies, and that the name of Bellcore not be used in advertising
 * or publicity pertaining to this material without the specific,
 * prior written permission of an authorized representative of
 * Bellcore.
 *
 * BELLCORE MAKES NO REPRESENTATIONS AND EXTENDS NO WARRANTIES, EX-
 * PRESS OR IMPLIED, WITH RESPECT TO THE SOFTWARE, INCLUDING, BUT
 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR ANY PARTICULAR PURPOSE, AND THE WARRANTY AGAINST IN-
 * FRINGEMENT OF PATENTS OR OTHER INTELLECTUAL PROPERTY RIGHTS.  THE
 * SOFTWARE IS PROVIDED "AS IS", AND IN NO EVENT SHALL BELLCORE OR
 * ANY OF ITS AFFILIATES BE LIABLE FOR ANY DAMAGES, INCLUDING ANY
 * LOST PROFITS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES RELAT-
 * ING TO THE SOFTWARE.
 *
 * $Id: colors.c,v 1.3 1999/10/22 21:10:44 amai Exp $
 */

#ifdef HAVE_CONFIG_H
#include <XbaeConfig.h>
#endif

#include <stdlib.h>
#include <stdio.h>
#include <X11/StringDefs.h>
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
#include <Xm/ToggleB.h>
#include <Xbae/Matrix.h>

/*
 * Interactively set row, column and cell colors.
 * Consists of an option menu to select row, column or cell orientation.
 * Then when a color name is entered in a cell, that row, column or cell
 * (depending on the orientation) is set to the color entered.
 */

void SetColorCB();
void RowOrientationCB();
void ColumnOrientationCB();
void CellOrientationCB();
void modeCB();
void ResetCB();
void LoadMatrix();

typedef enum {
    CellOrientation,
    RowOrientation,
    ColumnOrientation
} ColorOrientation;

typedef enum {
    textForeground,
    textBackground
} ColorMode;

typedef struct {
    Widget matrix;
    ColorOrientation orientation;
    ColorMode mode; 
} ColorDataRec, *ColorData;


int
main(argc, argv)
int argc;
char *argv[];
{
    Widget toplevel, form, menu, row, column, cell, reset, option, mode;
    XtAppContext app;
    ColorDataRec colorData;
    Arg args[2];
    int n;
#ifdef USE_EDITRES
    extern void _XEditResCheckMessages();
#endif

    toplevel = XtVaAppInitialize(&app, "Colors",
				 NULL, 0,
				 &argc, argv,
				 NULL,
				 NULL);
#ifdef USE_EDITRES
    XtAddEventHandler( toplevel, (EventMask)0, True,
                       _XEditResCheckMessages, NULL);
#endif

    /*
     * Create a Form to hold everything
     */
    form = XtCreateManagedWidget("form",
                                 xmFormWidgetClass,     toplevel,
                                 NULL, 0);

    /*
     * Create a menu for use in an OptionMenu
     */
    menu = XmCreatePulldownMenu(form, "menu", NULL, 0);

    /*
     * Create a menu button to select cell orientation
     */
    cell = XtVaCreateManagedWidget("cell",
				   xmPushButtonWidgetClass,	menu,
				   NULL);
    XtAddCallback(cell, XmNactivateCallback, CellOrientationCB,
		  (XtPointer)&colorData);

    /*
     * Create a menu button to select row orientation
     */
    row = XtVaCreateManagedWidget("row",
				  xmPushButtonWidgetClass,	menu,
				  NULL);
    XtAddCallback(row, XmNactivateCallback, RowOrientationCB,
		  (XtPointer)&colorData);

    /*
     * Create a menu button to select column orientation
     */
    column = XtVaCreateManagedWidget("column",
				     xmPushButtonWidgetClass,   menu,
				     NULL);
    XtAddCallback(column, XmNactivateCallback, ColumnOrientationCB,
		  (XtPointer)&colorData);

    /*
     * Setup and create the option menu
     */
    n = 0;
    XtSetArg(args[n], XmNsubMenuId, menu);		n++;
    XtSetArg(args[n], XmNmenuHistory, cell);		n++;
    option = XmCreateOptionMenu(form, "option", args, n);
    XtManageChild(option);


    colorData.orientation = CellOrientation;
    colorData.mode = textForeground;

    /*
     * Create a Matrix widget.  Add a callback to get the color entered
     * in a cell.
     */
    colorData.matrix =
	XtVaCreateManagedWidget("mw",
				xbaeMatrixWidgetClass,	form,
				XmNtopAttachment,	XmATTACH_WIDGET,
				XmNtopWidget,		option,
				XmNleftAttachment,	XmATTACH_FORM,
				XmNrightAttachment,	XmATTACH_FORM,
				XmNbottomAttachment,	XmATTACH_FORM,
				NULL);
    XtAddCallback(colorData.matrix, XmNleaveCellCallback, SetColorCB,
		  (XtPointer)&colorData);
    /*
     * Create a button to reset XmNcolors
     */
    reset = XtVaCreateManagedWidget("reset",
				    xmPushButtonWidgetClass, form,
				    XmNleftAttachment, XmATTACH_WIDGET,
				    XmNleftWidget, option,
				    NULL);
    XtAddCallback(reset, XmNactivateCallback, ResetCB,
		  (XtPointer)colorData.matrix);

    mode = XtVaCreateManagedWidget("mode",
				   xmToggleButtonWidgetClass, form,
				   XmNleftAttachment, XmATTACH_WIDGET,
				   XmNleftWidget, reset,
				   XmNset, False,
				   NULL);
    XtAddCallback(mode, XmNvalueChangedCallback, modeCB,
		  (XtPointer)&colorData);
  
    /*
     * Load the matrix with default values
     */
    LoadMatrix(colorData.matrix);

    XtRealizeWidget(toplevel);
    XtAppMainLoop(app);
    exit(0);
}

/* ARGSUSED */
void
CellOrientationCB(w, colorData, call_data)
Widget w;
ColorData colorData;
XtPointer call_data;
{
    colorData->orientation = CellOrientation;
}

/* ARGSUSED */
void
RowOrientationCB(w, colorData, call_data)
Widget w;
ColorData colorData;
XtPointer call_data;
{
    colorData->orientation = RowOrientation;
}

/* ARGSUSED */
void
ColumnOrientationCB(w, colorData, call_data)
Widget w;
ColorData colorData;
XtPointer call_data;
{
    colorData->orientation = ColumnOrientation;
}

/* ARGSUSED */
void
modeCB(w, colorData, cbs)
Widget w;
ColorData colorData;
XmToggleButtonCallbackStruct *cbs;
{
    if( cbs->set )
	colorData->mode = textBackground;
    else
	colorData->mode = textForeground;
}

/* ARGSUSED */
void
SetColorCB(w, colorData, call_data)
Widget w;
ColorData colorData;
XbaeMatrixLeaveCellCallbackStruct *call_data;
{
    XrmValue fromVal, toVal;
    Pixel color;

    /*
     * If the color is "X" or "Z", ignore it since that is what we load
     * the matrix with
     */
    if (call_data->value[0] == 'X' || call_data->value[0] == 'Z')
	return;

    /*
     * Attempt to convert the string in this cell to a Pixel
     */
    fromVal.size = strlen(call_data->value) + 1;
    fromVal.addr = call_data->value;
    toVal.size = sizeof(Pixel);
    toVal.addr = (XtPointer) &color;
    if (!XtConvertAndStore(w, XtRString, &fromVal, XtRPixel, &toVal))
	return;

    /*
     * Set the current row/column to the specified color based on our
     * current orientation.
     */
    if( colorData->mode == textForeground )
    {
	switch (colorData->orientation) {
	case CellOrientation:
	    XbaeMatrixSetCellColor(colorData->matrix,
				   call_data->row, call_data->column, color);
	    break;
	case RowOrientation:
	    XbaeMatrixSetRowColors(colorData->matrix, call_data->row,
				   &color, 1);
	    break;
	case ColumnOrientation:
	    XbaeMatrixSetColumnColors(colorData->matrix, call_data->column,
				      &color, 1);
	    break;
	}
    }
    else
    {
	switch (colorData->orientation) {
	case CellOrientation:
	    XbaeMatrixSetCellBackground(
		colorData->matrix, call_data->row, call_data->column, color);
	    break;
	case RowOrientation:
	    XbaeMatrixSetRowBackgrounds(
		colorData->matrix, call_data->row, &color, 1);
	    break;
	case ColumnOrientation:
	    XbaeMatrixSetColumnBackgrounds(
		colorData->matrix, call_data->column, &color, 1);
	    break;
	}
    }
}

/* ARGSUSED */
void
ResetCB(w, matrix, client_data)
Widget w;
Widget matrix;
XtPointer client_data;
{
    XtVaSetValues(matrix,
		  XmNcolors, NULL,
		  XmNcellBackgrounds, NULL,
		  NULL);
    LoadMatrix(matrix);
}

void
LoadMatrix(w)
Widget w;
{
    int rows, columns;
    int i, j;
    String *rowArrays, **cells;

    XtVaGetValues(w,
		  XmNrows,	&rows,
		  XmNcolumns,	&columns,
		  NULL);

    cells = (String **)XtMalloc(rows * sizeof(String *));
    rowArrays = (String *)XtMalloc(rows * columns * sizeof(String));

    for (i = 0; i < rows; i++) {
	cells[i] = &rowArrays[i * columns];
	if (i % 2)
	    for (j = 0; j < columns; j++)
		rowArrays[i * columns + j] = "X";
	else
	    for (j = 0; j < columns; j++)
		rowArrays[i * columns + j] = "Z";
    }

    XtVaSetValues(w,
		  XmNcells,	cells,
		  NULL);

    XtFree((XtPointer) rowArrays);
    XtFree((XtPointer) cells);
}

