



#include "WINGsP.h"



typedef struct W_Label {
    W_Class widgetClass;
    W_View *view;
	
    char *caption;
    int captionHeight;

    GC gc;			       /* for the text */
    WMFont *font;		       /* if NULL, use default */
    
    W_Pixmap *image;

    WMReliefType relief;
    WMImagePosition imagePosition;
    WMAlignment alignment;
    struct {    	
	unsigned int configured:1;
	
	unsigned int redrawPending:1;

	unsigned int fontChanged:1;
    } flags;
} Label;



static WMArgument LabelArguments[] = {
    {WARG_WIDTH,	(WMValue)60},
    {WARG_HEIGHT,	(WMValue)14},
    {WARG_ALIGNMENT,	(WMValue)WALeft},
    {WARG_CAPTION,	(WMValue)"Label"},
    {WARG_FONT,		(WMValue)NULL},
    {WARG_RELIEF, 	(WMValue)WRFlat},
};


static void destroyLabel(Label *lPtr);
static void paintLabel(Label *lPtr);


static int configureLabelArg(Label *lPtr, WMArgument *arg);
static void handleEvents(XEvent *event, void *data);


WMLabel*
WMCreateLabel(WMWidget *parent, WMArgument *argv, int argc)
{
    Label *lPtr;
    
    lPtr = wmalloc(sizeof(Label));
    memset(lPtr, 0, sizeof(Label));

    lPtr->widgetClass = WC_Label;
    
    lPtr->view = W_CreateView(W_VIEW(parent));
    if (!lPtr->view) {
	free(lPtr);
	return NULL;
    }
    lPtr->view->attribFlags |= CWBackPixel;
    lPtr->view->attribs.background_pixel = W_VIEW(parent)->screen->lightPixel;
    
    WMCreateEventHandler(lPtr->view, ExposureMask|StructureNotifyMask,
			 handleEvents, lPtr);

    if (!WMConfigureLabel(lPtr, argv, argc)) {
	W_DestroyView(lPtr->view);
	return NULL;
    }

    return lPtr;
}


static int
configureLabelArg(Label *but, WMArgument *arg)
{
    switch (arg->argument) {
     case WARG_IMAGE:
	if (but->image!=NULL)
	    WMReleasePixmap(but->image);
	but->image = WMRetainPixmap((WMPixmap*)arg->value);
	break;

     case WARG_IMAGE_POSITION:
	but->imagePosition = (WMImagePosition)arg->value;
	break;
	
     case WARG_ALIGNMENT:
	but->alignment = (WMAlignment)arg->value;
	break;

     case WARG_RELIEF:
	but->relief = (WMReliefType)arg->value;
	break;
	
     case WARG_CAPTION:
	if (but->caption)
	    free(but->caption);
	if (arg->value)
	    but->caption = strdup((char*)arg->value);
	else
	    but->caption = NULL;
	break;
	
     case WARG_FONT:
	if (but->font!=NULL)
	    WMReleaseFont(but->font);
	but->font = WMRetainFont((WMFont*)arg->value);
	but->flags.fontChanged = 1;
	break;
		
     default:
	if (!W_ConfigureViewArg(but->view, arg)) {
	    wWarning("bad argument value %i in configureLabel",
		     arg->argument);
	    return False;
	}
    }
    return True;
}


int
WMConfigureLabel(Label *lPtr, WMArgument *argv, int argc)
{
    int i;
    W_Screen *scrPtr = lPtr->view->screen;
    
    CHECK_CLASS(lPtr, WC_Label);
    
    if (!lPtr->flags.configured) {
	for (i=0; i<sizeof(LabelArguments)/sizeof(WMArgument); i++) {
	    if (!configureLabelArg(lPtr, &(LabelArguments[i])))
		return False;
	}	
	lPtr->flags.configured = 1;
    }

    for (i=0; i<argc; i++) {
	if (!configureLabelArg(lPtr, &(argv[i])))
	    return False;
    }
    
    if (lPtr->flags.fontChanged) {
	lPtr->flags.fontChanged = 0;
	if (lPtr->font!=NULL) {
	    if (lPtr->gc==NULL) {
		XGCValues gcv;
		gcv.foreground = scrPtr->blackPixel;
		lPtr->gc = XCreateGC(scrPtr->display, scrPtr->rootWin, 
				    GCForeground, &gcv);
	    }
	    XSetFont(scrPtr->display, lPtr->gc, lPtr->font->font->fid);
	} else {
	    if (lPtr->gc != NULL) 
		XFreeGC(scrPtr->display, lPtr->gc);
	    lPtr->gc = NULL;
	}
    }
    
    
    if (lPtr->caption!=NULL) {
	lPtr->captionHeight = 
	    W_GetTextHeight(lPtr->font ? lPtr->font : scrPtr->normalFont,
			    lPtr->caption, lPtr->view->size.width, True);
    } else {
	lPtr->captionHeight = 0;
    }

    if (lPtr->view->flags.realized) {
	paintLabel(lPtr);
    }

    return True;
}




static void
paintLabel(Label *lPtr)
{
    W_Screen *scrPtr = lPtr->view->screen;

    W_PaintTextAndImage(lPtr->view, True,
			(lPtr->gc!=NULL ? lPtr->gc : scrPtr->normalFontGC),
			(lPtr->font!=NULL ? lPtr->font : scrPtr->normalFont),
			lPtr->relief, lPtr->caption, lPtr->captionHeight,
			lPtr->alignment, lPtr->image, lPtr->imagePosition, 
			NULL, 0);
}



static void
handleEvents(XEvent *event, void *data)
{
    Label *lPtr = (Label*)data;

    CHECK_CLASS(data, WC_Label);


    switch (event->type) {
     case Expose:
	if (event->xexpose.count!=0)
	    break;
	paintLabel(lPtr);
	break;
	
     case DestroyNotify:
	destroyLabel(lPtr);
	break;
    }
}


static void
destroyLabel(Label *lPtr)
{
    CHECK_CLASS(lPtr, WC_Label);
    
    if (lPtr->caption)
	free(lPtr->caption);

    if (lPtr->gc)
	XFreeGC(lPtr->view->screen->display, lPtr->gc);
    
    if (lPtr->font)
	WMReleaseFont(lPtr->font);

    if (lPtr->image)
	WMReleasePixmap(lPtr->image);

    free(lPtr);
}
