
/*
 * Widget for testing double-clicks
 * 
 */

#include "WINGsP.h"

#include "double.h"


typedef struct W_DoubleTest {
    W_Class widgetClass;
    WMView *view;

    WMHandlerID timer;
    char on;
    char active;
    char *text;
} _DoubleTest;




/* some forward declarations */

static void destroyDoubleTest(_DoubleTest *dPtr);
static void paintDoubleTest(_DoubleTest *dPtr);


static void handleEvents(XEvent *event, void *data);
static void handleActionEvents(XEvent *event, void *data);



/* our widget class ID */
static W_Class DoubleTestClass = 0;


/*
 * Initializer for our widget. Must be called before creating any
 * instances of the widget.
 */
W_Class
InitDoubleTest(WMScreen *scr)
{
    /* register our widget with WINGs and get our widget class ID */
    if (!DoubleTestClass) {
	DoubleTestClass = W_RegisterUserWidget();
    }

    return DoubleTestClass;
}


/*
 * Our widget fabrication plant.
 */
DoubleTest*
CreateDoubleTest(WMWidget *parent, char *text)
{
    DoubleTest *dPtr;

    if (!DoubleTestClass)
	InitDoubleTest(WMWidgetScreen(parent));
    
    /* allocate some storage for our new widget instance */
    dPtr = wmalloc(sizeof(DoubleTest));
    /* initialize it */
    memset(dPtr, 0, sizeof(DoubleTest));

    /* set the class ID */
    dPtr->widgetClass = DoubleTestClass;
    
    dPtr->view = W_CreateView(W_VIEW(parent));
    if (!dPtr->view) {
	free(dPtr);
	return NULL;
    }
    /* always do this */
    dPtr->view->self = dPtr;
    
    dPtr->text = wstrdup(text);

    WMCreateEventHandler(dPtr->view, ExposureMask /* this allows us to know when we should paint */
			 |StructureNotifyMask, /* this allows us to know things like when we are destroyed */
			 handleEvents, dPtr);

    WMCreateEventHandler(dPtr->view, ButtonPressMask,handleActionEvents, dPtr);

    return dPtr;
}



static void
paintDoubleTest(_DoubleTest *dPtr)
{
    W_Screen *scr = dPtr->view->screen;

    if (dPtr->active) {
	XFillRectangle(scr->display, dPtr->view->window, WMColorGC(scr->white),
		       0, 0, dPtr->view->size.width, dPtr->view->size.height);
    } else {
	XClearWindow(scr->display, dPtr->view->window);
    }
    
    W_DrawRelief(scr, dPtr->view->window, 0, 0, dPtr->view->size.width,
		 dPtr->view->size.height, dPtr->on ? WRSunken : WRRaised);

    if (dPtr->text) {
	int y;
	y = (dPtr->view->size.height-scr->normalFont->height)/2;
	W_PaintText(dPtr->view, dPtr->view->window, scr->normalFont,  
		    dPtr->on, dPtr->on+y, dPtr->view->size.width, WACenter, 
		    WMColorGC(scr->black), False, dPtr->text, strlen(dPtr->text));
    }
}



static void
handleEvents(XEvent *event, void *data)
{
    _DoubleTest *dPtr = (_DoubleTest*)data;


    switch (event->type) {	
     case Expose:
	if (event->xexpose.count!=0)
	    break;
	paintDoubleTest(dPtr);
	break;
	
     case DestroyNotify:
	destroyDoubleTest(dPtr);
	break;
	
    }
}


static void
deactivate(void *data)
{
   _DoubleTest *dPtr = (_DoubleTest*)data;
    
    if (dPtr->active)
	dPtr->active = 0;
    paintDoubleTest(dPtr);
    
    dPtr->timer = NULL;
}


static void
handleActionEvents(XEvent *event, void *data)
{
    _DoubleTest *dPtr = (_DoubleTest*)data;
    extern _WINGsConfiguration WINGsConfiguration;

    switch (event->type) {
     case ButtonPress:
	if (WMIsDoubleClick(event)) {
	    if (dPtr->timer)
		WMDeleteTimerHandler(dPtr->timer);
	    dPtr->timer = NULL;
	    dPtr->on = !dPtr->on;
	    dPtr->active = 0;
	    paintDoubleTest(dPtr);
	} else {
	    dPtr->timer=WMAddTimerHandler(WINGsConfiguration.doubleClickDelay,
					  deactivate, dPtr);
	    dPtr->active = 1;
	    paintDoubleTest(dPtr);
	}
	break;
    }
}



static void
destroyDoubleTest(_DoubleTest *dPtr)
{
    if (dPtr->timer)
	WMDeleteTimerHandler(dPtr->timer);
    if (dPtr->text)
	free(dPtr->text);
    
    free(dPtr);
}


