
#include "WINGsP.h"


typedef struct W_Frame {
    W_Class widgetClass;
    W_View *view;

    char *caption;

    WMReliefType relief;
    WMTitlePosition titlePosition;
    
    struct {
	unsigned int configured:1;
    } flags;
} Frame;



static WMArgument frameArguments[] = {
    {WARG_RELIEF, 	(WMValue)WRGroove},
    {WARG_TITLE_POSITION,(WMValue)WTPAtTop},
};



static void destroyFrame(Frame *fPtr);
static void paintFrame(Frame *fPtr);


static int
configureFrameArg(Frame *fPtr, WMArgument *arg)
{
    switch (arg->argument) {
     case WARG_TITLE_POSITION:
	fPtr->titlePosition = (WMTitlePosition)arg->value;
	break;
	
     case WARG_RELIEF:
	fPtr->relief = (WMReliefType)arg->value;
	break;
	
     case WARG_CAPTION:
	if (fPtr->caption)
	    free(fPtr->caption);
	if (arg->value)
	    fPtr->caption = strdup((char*)arg->value);
	else
	    fPtr->caption = NULL;
	break;
	
     default:
	if (!W_ConfigureViewArg(fPtr->view, arg)) {
	    wWarning("bad argument value %i in configureFrame",  
		     arg->argument);
	    return False;
	}
    }
    return True;
}


int
WMConfigureFrame(WMFrame *fPtr, WMArgument *argv, int argc) 
{
    int i;
    
    CHECK_CLASS(fPtr, WC_Frame);
    
    if (!fPtr->flags.configured) {
	for (i=0; i<sizeof(frameArguments)/sizeof(WMArgument); i++) {
	    if (!configureFrameArg(fPtr, &(frameArguments[i])))
		return False;
	}	
	fPtr->flags.configured = 1;
    }

    for (i=0; i<argc; i++) {
	if (!configureFrameArg(fPtr, &(argv[i])))
	    return False;
    }

    if (fPtr->view->flags.realized) {
	paintFrame(fPtr);
    }

    return True;
}


static void
paintFrame(Frame *fPtr)
{
    W_View *view = fPtr->view;
    W_Screen *scrPtr = view->screen;
    int tx, ty, tw, th;
    int fy, fh;

    if (fPtr->caption!=NULL)
	th = scrPtr->normalFont->height;
    else {
	th = 0;
    }
    
    fh = view->size.height;
    fy = 0;
    
    switch (fPtr->titlePosition) {
     case WTPAboveTop:
	ty = 0;
	fy = th + 4;
	fh = view->size.height - fy;
	break;
	
     case WTPAtTop:
	ty = 0;
	fy = th/2;
	fh = view->size.height - fy;
	break;
	
     case WTPBelowTop:
	ty = 4;
	fy = 0;
	fh = view->size.height;
	break;
	
     case WTPAboveBottom:
	ty = view->size.height - th - 4;
	fy = 0;
	fh = view->size.height;
	break;
	
     case WTPAtBottom:
	ty = view->size.height - th;
	fy = 0;
	fh = view->size.height - th/2;
	break;
	
     case WTPBelowBottom:
	ty = view->size.height - th;
	fy = 0;
	fh = view->size.height - th - 4;
	break;
	
     default:
	ty = 0;
	fy = 0;
	fh = view->size.height;
    }
/*
    XClearArea(scrPtr->display, view->window, fy+2, 2, fh-4, view->size.width-4,
	       False);
 */
    
    W_DrawRelief(scrPtr, view->window, 0, fy, view->size.width, fh, 
		 fPtr->relief);

    if (fPtr->caption!=NULL && fPtr->titlePosition!=WTPNoTitle) {
	
	
	tw = XTextWidth(scrPtr->normalFont->font,
			fPtr->caption, strlen(fPtr->caption));
    	
	tx = (view->size.width - tw) / 2;
    
	XFillRectangle(scrPtr->display, view->window, scrPtr->lightGC,
		       tx, ty, tw, th);

	XDrawString(scrPtr->display, view->window, scrPtr->normalFontGC, tx, 
		    scrPtr->normalFont->y+ty, fPtr->caption, 
		    strlen(fPtr->caption));
    }
}





static void
handleEvents(XEvent *event, void *data)
{
    Frame *fPtr = (Frame*)data;

    CHECK_CLASS(data, WC_Frame);

    switch (event->type) {
     case Expose:
	if (event->xexpose.count!=0)
	    break;
	paintFrame(fPtr);
	break;
	
     case DestroyNotify:
	destroyFrame(fPtr);
	break;
    }
}


WMFrame*
WMCreateFrame(WMWidget *parent, WMArgument *argv, int argc)
{
    Frame *fPtr;
    
    fPtr = wmalloc(sizeof(Frame));
    memset(fPtr, 0, sizeof(Frame));

    fPtr->widgetClass = WC_Frame;

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

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

    return fPtr;
}


static void
destroyFrame(Frame *fPtr)
{
    CHECK_CLASS(fPtr, WC_Frame);
    
    if (fPtr->caption)
	free(fPtr->caption);

    free(fPtr);
}
