/*
 * Copyright 1990 by Baylor College of Medicine ALL RIGHTS RESERVED. 
 *
 * This program is subject to a license agreement between 
 * Baylor College of Medicine and MIT. Any use inconsistent with
 * said license and any use by persons other than the faculty, 
 * students and staff at MIT or any use on a computer not operated 
 * as part of the Athena Computing Environment (ACE) is expressly 
 * prohibited.
 */
/* @(#)Color.c	1.7  4/10/90 */
/*
 *		Text Pane Widget.
 */
#include <X11/Intrinsic.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/CoreP.h>
#include <X11/CompositeP.h>

#include <ColorP.h>

#define TPW(w) (((ColorWidget)(w))->color)

static ClassInitialize();
static Initialize();
static Destroy();
static Resize();
static ReDisplay();
static Boolean SetValues();

#define HIGH_WID 4

static ac_select();
static ac_enter();
static ac_leave();

static char defaultTranslations[] = "\
      <Enter>:	enter()\n\
      <Leave>:	leave()\n\
      <BtnDown>:	select()\n\
" ;

static XtActionsRec actionsList[] =
{
	{"enter",		(XtActionProc) ac_enter},
	{"leave",		(XtActionProc) ac_leave},
	{"select",		(XtActionProc) ac_select},
} ;

static XtResource resources[] =
{
        {XtNcolorName,
                XtCColorName,
                XtRString,
                sizeof(XtPointer),
                XtOffset(ColorWidget, color.color_name),
                XtRString,
                "white"},
        {XtNfont,
                XtCFont,
                XtRFontStruct,
                sizeof(XFontStruct *),
                XtOffset(ColorWidget, color.font),
                XtRString,
                XtDefaultFont},
        {XtNcolorSelect,
                XtCCallback,
                XtRCallback,
                sizeof(XtPointer),
                XtOffset(ColorWidget, color.color_select),
                XtRCallback,
                NULL},
        {XtNcolorSet,
                XtCColorSet,
                XtRBoolean,
                sizeof(Boolean),
                XtOffset(ColorWidget, color.is_selected),
                XtRString,
                "False"},
} ;

ColorClassRec colorWidgetClassRec =
{
	{
		(WidgetClass)&widgetClassRec,			/* superclass */
		"Color",							/* class name */
		sizeof(ColorRec),					/* widget size */
		(XtWidgetClassProc)ClassInitialize,		/* class_initialize */
		NULL,									/* class_part_initialize */
		FALSE,									/* class inited */
		(XtInitProc)Initialize,					/* initialize */
		NULL,									/* initialize_hook */
		XtInheritRealize,						/* realize */
		actionsList,							/* actions */
		XtNumber(actionsList),					/* num_actions */
		resources,								/* resources */
		XtNumber(resources),					/* num_resources */
		NULLQUARK,								/* xrm_class */
		TRUE,									/* compress_motion */
		TRUE,									/* compress_exposure */
		TRUE,									/* compress_enterleave */
		FALSE,									/* visible_interest */
		(XtWidgetProc)Destroy,					/* destroy */
		(XtWidgetProc)Resize,					/* resize */
		(XtExposeProc)ReDisplay,				/* expose */
		SetValues,								/* set_values */
		NULL,									/* set_values_hook */
		XtInheritSetValuesAlmost,				/* set_values_almost */
		NULL,									/* get_values_hook */
		XtInheritAcceptFocus,					/* accept_focus */
		XtVersion,								/* version */
		NULL,									/* callback private */
		defaultTranslations,					/* tm_table */
		NULL,									/* query_geometry */
		XtInheritDisplayAccelerator,			/* display_accelerator */
		NULL									/* extension */
	},
	{
		0,
	}
} ;

WidgetClass colorWidgetClass = (WidgetClass)&colorWidgetClassRec ;

/*ARGSUSED*/
static
ClassInitialize()
{
}

static
make_gcs(w)
	Widget w ;
{
#include "grey.xbm"
	XColor col1,col2 ;
	unsigned long black = BlackPixelOfScreen(XtScreen(w)) ;
	XGCValues values ;
	XtGCMask mask ;

	XAllocNamedColor(XtDisplay(w),DefaultColormapOfScreen(XtScreen(w)),
		TPW(w).color_name,&col1,&col2) ;
	if (col1.pixel == black)
	{
		black = WhitePixelOfScreen(XtScreen(w)) ;
	}

	TPW(w).pix = XCreatePixmapFromBitmapData(XtDisplay(w),
		DefaultRootWindow(XtDisplay(w)),
		grey_bits,grey_width,grey_height,
		col1.pixel,black,
		w->core.depth) ;

	mask =
		(unsigned long)GCTile |
		(unsigned long)GCFillStyle ;
	values.tile = TPW(w).pix ;
	values.fill_style = FillTiled ;
	TPW(w).gc_highlighted = XtGetGC(w,mask,&values) ;

	values.foreground = black ;
	mask = (unsigned long)GCForeground ;
	TPW(w).gc_selected = XtGetGC(w,mask,&values) ;

	values.foreground = col1.pixel ;
	mask = (unsigned long)GCForeground ;
	TPW(w).gc_background = XtGetGC(w,mask,&values) ;

	values.foreground = black ;
	values.font = TPW(w).font->fid ;
	mask = (unsigned long)GCForeground | (unsigned long)GCFont ;
	TPW(w).gc_text = XtGetGC(w,mask,&values) ;
}

static
free_gcs(w)
	Widget w ;
{
	XtReleaseGC(w,TPW(w).gc_highlighted) ;
	XtReleaseGC(w,TPW(w).gc_selected) ;
	XtReleaseGC(w,TPW(w).gc_background) ;
	XtReleaseGC(w,TPW(w).gc_text) ;
	XFreePixmap(XtDisplay(w),TPW(w).pix);
}

/*ARGSUSED*/
static
Initialize(request,new)
	Widget request ;
	Widget new ;
{
	if (!new->core.width)
	{
		new->core.width = XTextWidth(TPW(new).font,TPW(new).color_name,
			strlen(TPW(new).color_name)) + 2 * HIGH_WID ;
	}
	if (!new->core.height)
	{
		new->core.height = TPW(new).font->ascent + TPW(new).font->descent +
			2 * HIGH_WID ;
	}
	make_gcs(new) ;
	TPW(new).is_highlighted = False ;
}

/*ARGSUSED*/
static
Destroy(w)
	Widget w ;
{
	free_gcs(w) ;
}

/*ARGSUSED*/
static
Resize(w)
	Widget w ;
{
}

/*ARGSUSED*/
static
redisplay(w)
	Widget w ;
{
	if (w->core.window)
	{
		XPoint points[10] ;
		points[0].x = 0 ;
		points[0].y = 0 ;
		points[1].x = HIGH_WID ;
		points[1].y = HIGH_WID ;
		points[2].x = w->core.width - HIGH_WID ;
		points[2].y = HIGH_WID ;
		points[3].x = w->core.width - HIGH_WID ;
		points[3].y = w->core.height - HIGH_WID ;
		points[4].x = HIGH_WID ;
		points[4].y = w->core.height - HIGH_WID ;
		points[5] = points[1] ;
		points[6] = points[0] ;
		points[7].x = 0 ;
		points[7].y = w->core.height ;
		points[8].x = w->core.width ;
		points[8].y = w->core.height ;
		points[9].x = w->core.width ;
		points[9].y = 0 ;
		if (TPW(w).is_selected)
		{
			XFillPolygon(XtDisplay(w),XtWindow(w),TPW(w).gc_selected,points,10,Nonconvex,CoordModeOrigin) ;
			XFillRectangle(XtDisplay(w),XtWindow(w),TPW(w).gc_background,
				HIGH_WID,HIGH_WID,w->core.width - 2 * HIGH_WID,w->core.height - 2 * HIGH_WID) ;
		}
		else if (TPW(w).is_highlighted)
		{
			XFillPolygon(XtDisplay(w),XtWindow(w),TPW(w).gc_highlighted,points,10,Nonconvex,CoordModeOrigin) ;
			XFillRectangle(XtDisplay(w),XtWindow(w),TPW(w).gc_background,
				HIGH_WID,HIGH_WID,w->core.width - 2 * HIGH_WID,w->core.height - 2 * HIGH_WID) ;
		}
		else
		{
			XFillRectangle(XtDisplay(w),XtWindow(w),TPW(w).gc_background,
				0,0,w->core.width,w->core.height) ;
		}
		{
			int l = XTextWidth(TPW(w).font,TPW(w).color_name,strlen(TPW(w).color_name)) ;
			int x = (w->core.width - l) / 2 ;
			int th = TPW(w).font->ascent + TPW(w).font->descent ;
			int y = TPW(w).font->ascent + (w->core.height - th) / 2 ;
			XDrawString(XtDisplay(w),XtWindow(w),TPW(w).gc_text,x,y,TPW(w).color_name,
				strlen(TPW(w).color_name)) ;
		}
	}
}

/*ARGSUSED*/
static
ReDisplay(w, event)
	Widget w ;
	XExposeEvent *event ;
{
	redisplay(w) ;
}

/*ARGSUSED*/
static
Boolean
SetValues(old, request, new)
	Widget old ;
	Widget request ;
	Widget new ;
{
	if (TPW(request).is_selected)
	{
		Widget parent = new->core.parent ;
		Widget *children = ((CompositeWidget)parent)->composite.children ;
		int nchildren = ((CompositeWidget)parent)->composite.num_children ;
		int i ;
		for(i = 0; i < nchildren; i++)
		{
			Widget child = children[i] ;
			if (XtIsSubclass(child,colorWidgetClass))
			{
				TPW(child).is_selected = False ;
				redisplay(child) ;
			}
		}
		TPW(new).is_selected = True;
		redisplay(new) ;
		if (TPW(new).is_selected)
		{
			XtCallCallbacks(new,XtNcolorSelect,(XtPointer)new->core.background_pixel) ;
		}
	}
	return True ;
}

/*ARGSUSED*/
static
ac_select(w, event)
	Widget w ;
	XButtonEvent *event ;
{
	Boolean new = TPW(w).is_selected ? False : True ;
	if (new)
	{
		Widget parent = w->core.parent ;
		Widget *children = ((CompositeWidget)parent)->composite.children ;
		int nchildren = ((CompositeWidget)parent)->composite.num_children ;
		int i ;
		for(i = 0; i < nchildren; i++)
		{
			Widget child = children[i] ;
			if (XtIsSubclass(child,colorWidgetClass))
			{
				TPW(child).is_selected = False ;
				redisplay(child) ;
			}
		}
	}
	TPW(w).is_selected = new ;
	redisplay(w) ;
	if (new)
	{
		XtCallCallbacks(w,XtNcolorSelect,(XtPointer)w->core.background_pixel) ;
	}
}

/*ARGSUSED*/
static
ac_enter(w, event)
	Widget w ;
	XButtonEvent *event ;
{
	TPW(w).is_highlighted = True ;
	redisplay(w) ;
}

/*ARGSUSED*/
static
ac_leave(w, event)
	Widget w ;
	XButtonEvent *event ;
{
	TPW(w).is_highlighted = False ;
	redisplay(w) ;
}
