1917 lines
41 KiB
C
1917 lines
41 KiB
C
/*
|
|
* Widget.c
|
|
*
|
|
* The main interface functions to the widget library
|
|
*/
|
|
|
|
|
|
#include "lib/framework/frame.h"
|
|
#include "lib/framework/frameint.h"
|
|
|
|
#include "widget.h"
|
|
#include "widgint.h"
|
|
|
|
#include "form.h"
|
|
#include "label.h"
|
|
#include "button.h"
|
|
#include "editbox.h"
|
|
#include "bar.h"
|
|
#include "slider.h"
|
|
|
|
#include "tip.h"
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
/* The initial and extension number of strings to allocate in the string heap */
|
|
#define WIDG_STRINIT 100
|
|
#define WIDG_STREXT 10
|
|
|
|
/* the widget to be returned by widgRunScreen */
|
|
static WIDGET *psRetWidget;
|
|
|
|
static BOOL bWidgetsActive = TRUE;
|
|
|
|
/* The widget the mouse is over this update */
|
|
static WIDGET *psMouseOverWidget;
|
|
|
|
static UDWORD pressed, released;
|
|
|
|
|
|
|
|
static WIDGET_AUDIOCALLBACK AudioCallback = NULL;
|
|
static SWORD HilightAudioID = -1;
|
|
static SWORD ClickedAudioID = -1;
|
|
|
|
|
|
/* Function prototypes */
|
|
void widgHiLite(WIDGET *psWidget, W_CONTEXT *psContext);
|
|
void widgHiLiteLost(WIDGET *psWidget, W_CONTEXT *psContext);
|
|
static void widgClicked(WIDGET *psWidget, UDWORD key, W_CONTEXT *psContext);
|
|
static void widgReleased(WIDGET *psWidget, UDWORD key, W_CONTEXT *psContext);
|
|
static void widgRun(WIDGET *psWidget, W_CONTEXT *psContext);
|
|
static void widgDisplayForm(W_FORM *psForm, UDWORD xOffset, UDWORD yOffset);
|
|
|
|
/* The heap for widget strings */
|
|
static OBJ_HEAP *psStrHeap;
|
|
|
|
/* Buffer to return strings in */
|
|
static STRING aStringRetBuffer[WIDG_MAXSTR];
|
|
|
|
/* Initialise the widget module */
|
|
BOOL widgInitialise(W_HEAPINIT *psInit)
|
|
{
|
|
#if W_USE_STRHEAP
|
|
// Create the string heap
|
|
if (!HEAP_CREATE(&psStrHeap, WIDG_MAXSTR, WIDG_STRINIT, WIDG_STREXT))
|
|
{
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
tipInitialise();
|
|
|
|
#if W_USE_MALLOC
|
|
psInit = psInit;
|
|
#else
|
|
// Create the widget heaps
|
|
if (!HEAP_CREATE(&psBarHeap, sizeof(W_BARGRAPH), psInit->barInit, psInit->barExt))
|
|
{
|
|
return FALSE;
|
|
}
|
|
if (!HEAP_CREATE(&psButHeap, sizeof(W_BUTTON), psInit->butInit, psInit->butExt))
|
|
{
|
|
return FALSE;
|
|
}
|
|
if (!HEAP_CREATE(&psEdbHeap, sizeof(W_EDITBOX), psInit->edbInit, psInit->edbExt))
|
|
{
|
|
return FALSE;
|
|
}
|
|
if (!HEAP_CREATE(&psFormHeap, sizeof(W_FORM), psInit->formInit, psInit->formExt))
|
|
{
|
|
return FALSE;
|
|
}
|
|
if (!HEAP_CREATE(&psCFormHeap, sizeof(W_CLICKFORM), psInit->cFormInit, psInit->cFormExt))
|
|
{
|
|
return FALSE;
|
|
}
|
|
if (!HEAP_CREATE(&psTFormHeap, sizeof(W_TABFORM), psInit->tFormInit, psInit->tFormExt))
|
|
{
|
|
return FALSE;
|
|
}
|
|
if (!HEAP_CREATE(&psLabHeap, sizeof(W_LABEL), psInit->labInit, psInit->labExt))
|
|
{
|
|
return FALSE;
|
|
}
|
|
if (!HEAP_CREATE(&psSldHeap, sizeof(W_SLIDER), psInit->sldInit, psInit->sldExt))
|
|
{
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Reset the widgets.
|
|
//
|
|
void widgReset(void)
|
|
{
|
|
tipInitialise();
|
|
}
|
|
|
|
|
|
/* Shut down the widget module */
|
|
void widgShutDown(void)
|
|
{
|
|
#if W_USE_STRHEAP
|
|
HEAP_DESTROY(psStrHeap);
|
|
#endif
|
|
|
|
#if !W_USE_MALLOC
|
|
HEAP_DESTROY(psBarHeap);
|
|
HEAP_DESTROY(psButHeap);
|
|
HEAP_DESTROY(psEdbHeap);
|
|
HEAP_DESTROY(psFormHeap);
|
|
HEAP_DESTROY(psCFormHeap);
|
|
HEAP_DESTROY(psTFormHeap);
|
|
HEAP_DESTROY(psLabHeap);
|
|
HEAP_DESTROY(psSldHeap);
|
|
#endif
|
|
}
|
|
|
|
|
|
/* Get a string from the string heap */
|
|
BOOL widgAllocString(STRING **ppStr)
|
|
{
|
|
if (!HEAP_ALLOC(psStrHeap, (void**) ppStr))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Copy one string to another
|
|
* The string to copy will be truncated if it is longer than WIDG_MAXSTR.
|
|
*/
|
|
void widgCopyString(STRING *pDest, STRING *pSrc)
|
|
{
|
|
/* See if we need to clip the string, then copy */
|
|
if (strlen(pSrc) >= WIDG_MAXSTR)
|
|
{
|
|
memcpy(pDest, pSrc, WIDG_MAXSTR - 1);
|
|
*(pDest + WIDG_MAXSTR-1) = 0;
|
|
}
|
|
else
|
|
{
|
|
strcpy(pDest, pSrc);
|
|
}
|
|
}
|
|
|
|
/* Get a string from the heap and copy in some data.
|
|
* The string to copy will be truncated if it is too long.
|
|
*/
|
|
BOOL widgAllocCopyString(STRING **ppDest, STRING *pSrc)
|
|
{
|
|
if (!HEAP_ALLOC(psStrHeap, (void**) ppDest))
|
|
{
|
|
*ppDest = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
widgCopyString(*ppDest, pSrc);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* Return a string to the string heap */
|
|
void widgFreeString(STRING *pStr)
|
|
{
|
|
HEAP_FREE(psStrHeap, pStr);
|
|
}
|
|
|
|
/* Create an empty widget screen */
|
|
BOOL widgCreateScreen(W_SCREEN **ppsScreen)
|
|
{
|
|
W_FORM *psForm;
|
|
W_FORMINIT sInit;
|
|
|
|
*ppsScreen = (W_SCREEN *)MALLOC(sizeof(W_SCREEN));
|
|
if (*ppsScreen == NULL)
|
|
{
|
|
ASSERT( FALSE, "Out of memory" );
|
|
return FALSE;
|
|
}
|
|
|
|
memset(&sInit, 0, sizeof(W_FORMINIT));
|
|
sInit.id = 0;
|
|
sInit.style = WFORM_PLAIN | WFORM_INVISIBLE;
|
|
sInit.x = 0;
|
|
sInit.y = 0;
|
|
sInit.width = (UWORD)(screenWidth - 1);
|
|
sInit.height = (UWORD)(screenHeight - 1);
|
|
if (!formCreate(&psForm, &sInit))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
(*ppsScreen)->psForm = (WIDGET *)psForm;
|
|
(*ppsScreen)->psFocus = NULL;
|
|
(*ppsScreen)->TipFontID = 0;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* Release a list of widgets */
|
|
void widgReleaseWidgetList(WIDGET *psWidgets)
|
|
{
|
|
WIDGET *psCurr, *psNext;
|
|
|
|
for(psCurr = psWidgets; psCurr; psCurr = psNext)
|
|
{
|
|
psNext = psCurr->psNext;
|
|
switch(psCurr->type)
|
|
{
|
|
case WIDG_FORM:
|
|
formFree((W_FORM *)psCurr);
|
|
break;
|
|
case WIDG_LABEL:
|
|
labelFree((W_LABEL *)psCurr);
|
|
break;
|
|
case WIDG_BUTTON:
|
|
buttonFree((W_BUTTON *)psCurr);
|
|
break;
|
|
case WIDG_EDITBOX:
|
|
editBoxFree((W_EDITBOX *)psCurr);
|
|
break;
|
|
case WIDG_BARGRAPH:
|
|
barGraphFree((W_BARGRAPH *)psCurr);
|
|
break;
|
|
case WIDG_SLIDER:
|
|
sliderFree((W_SLIDER *)psCurr);
|
|
break;
|
|
default:
|
|
ASSERT( FALSE,"widgReleaseWidgetList: Unknown widget type" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* Release a screen and all its associated data */
|
|
void widgReleaseScreen(W_SCREEN *psScreen)
|
|
{
|
|
ASSERT( PTRVALID(psScreen, sizeof(W_SCREEN)),
|
|
"widgReleaseScreen: Invalid screen pointer" );
|
|
|
|
formFree((W_FORM *)psScreen->psForm);
|
|
|
|
FREE(psScreen);
|
|
}
|
|
|
|
|
|
/* Release a widget */
|
|
void widgRelease(WIDGET *psWidget)
|
|
{
|
|
switch(psWidget->type)
|
|
{
|
|
case WIDG_FORM:
|
|
formFree((W_FORM *)psWidget);
|
|
break;
|
|
case WIDG_LABEL:
|
|
labelFree((W_LABEL *)psWidget);
|
|
break;
|
|
case WIDG_BUTTON:
|
|
buttonFree((W_BUTTON *)psWidget);
|
|
break;
|
|
case WIDG_EDITBOX:
|
|
editBoxFree((W_EDITBOX *)psWidget);
|
|
break;
|
|
case WIDG_BARGRAPH:
|
|
barGraphFree((W_BARGRAPH *)psWidget);
|
|
break;
|
|
case WIDG_SLIDER:
|
|
sliderFree((W_SLIDER *)psWidget);
|
|
break;
|
|
default:
|
|
ASSERT( FALSE,"widgRelease: Unknown widget type" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Check whether an ID has been used on a form */
|
|
static BOOL widgCheckIDForm(W_FORM *psForm, UDWORD id)
|
|
{
|
|
WIDGET *psCurr;
|
|
W_FORMGETALL sGetAll;
|
|
|
|
/* Check the widgets on the form */
|
|
formInitGetAllWidgets(psForm, &sGetAll);
|
|
psCurr = formGetAllWidgets(&sGetAll);
|
|
while (psCurr != NULL)
|
|
{
|
|
if (psCurr->id == id)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
if (psCurr->type == WIDG_FORM)
|
|
{
|
|
/* Another form so recurse */
|
|
if (widgCheckIDForm((W_FORM *)psCurr, id))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
psCurr = psCurr->psNext;
|
|
if (!psCurr)
|
|
{
|
|
/* Got to the end of this list see if there is another */
|
|
psCurr = formGetAllWidgets(&sGetAll);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
#if 0
|
|
/* Check whether an ID number has been used on a screen */
|
|
static BOOL widgCheckID(W_SCREEN *psScreen, UDWORD id)
|
|
{
|
|
return widgCheckIDForm((W_FORM *)psScreen->psForm, id);
|
|
}
|
|
#endif
|
|
|
|
|
|
///* Set the tool tip font for a screen */
|
|
//void widgSetTipFont(W_SCREEN *psScreen, PROP_FONT *psFont)
|
|
//{
|
|
// ASSERT( PTRVALID(psScreen, sizeof(W_SCREEN)),
|
|
// "widgSetTipFont: Invalid screen pointer" );
|
|
// ASSERT( psFont == NULL || PTRVALID(psFont, sizeof(PROP_FONT)),
|
|
// "widgSetTipFont: Invalid font pointer" );
|
|
//
|
|
// psScreen->psTipFont = psFont;
|
|
//}
|
|
|
|
|
|
/* Set the tool tip font for a screen */
|
|
void widgSetTipFont(W_SCREEN *psScreen, int FontID)
|
|
{
|
|
ASSERT( PTRVALID(psScreen, sizeof(W_SCREEN)),
|
|
"widgSetTipFont: Invalid screen pointer" );
|
|
// ASSERT( psFont == NULL || PTRVALID(psFont, sizeof(PROP_FONT)),
|
|
// "widgSetTipFont: Invalid font pointer" );
|
|
|
|
psScreen->TipFontID = FontID;
|
|
}
|
|
|
|
|
|
|
|
/* Add a form to the widget screen */
|
|
BOOL widgAddForm(W_SCREEN *psScreen, W_FORMINIT *psInit)
|
|
{
|
|
W_FORM *psParent, *psForm;
|
|
|
|
ASSERT( PTRVALID(psScreen, sizeof(W_SCREEN)),
|
|
"widgAddForm: Invalid screen pointer" );
|
|
|
|
if (widgCheckIDForm((W_FORM *)psScreen->psForm,psInit->id))
|
|
{
|
|
ASSERT( FALSE, "widgAddForm: ID number has already been used (%d)", psInit->id );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Find the form to add the widget to */
|
|
if (psInit->formID == 0)
|
|
{
|
|
/* Add to the base form */
|
|
psParent = (W_FORM *)psScreen->psForm;
|
|
}
|
|
else
|
|
{
|
|
psParent = (W_FORM *)widgGetFromID(psScreen, psInit->formID);
|
|
if (!psParent || psParent->type != WIDG_FORM)
|
|
{
|
|
ASSERT( FALSE,
|
|
"widgAddForm: Could not find parent form from formID" );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* Create the form structure */
|
|
if (!formCreate(&psForm, psInit))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Add it to the screen */
|
|
if (!formAddWidget(psParent, (WIDGET *)psForm, (W_INIT *)psInit))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* Add a label to the widget screen */
|
|
BOOL widgAddLabel(W_SCREEN *psScreen, W_LABINIT *psInit)
|
|
{
|
|
W_LABEL *psLabel;
|
|
W_FORM *psForm;
|
|
|
|
ASSERT( PTRVALID(psScreen, sizeof(W_SCREEN)),
|
|
"widgAddLabel: Invalid screen pointer" );
|
|
|
|
if (widgCheckIDForm((W_FORM *)psScreen->psForm,psInit->id))
|
|
{
|
|
ASSERT( FALSE, "widgAddLabel: ID number has already been used (%d)", psInit->id );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Find the form to put the button on */
|
|
if (psInit->formID == 0)
|
|
{
|
|
psForm = (W_FORM *)psScreen->psForm;
|
|
}
|
|
else
|
|
{
|
|
psForm = (W_FORM *)widgGetFromID(psScreen, psInit->formID);
|
|
if (psForm == NULL || psForm->type != WIDG_FORM)
|
|
{
|
|
ASSERT( FALSE,
|
|
"widgAddLabel: Could not find parent form from formID" );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* Create the button structure */
|
|
if (!labelCreate(&psLabel, psInit))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Add it to the form */
|
|
if (!formAddWidget(psForm, (WIDGET *)psLabel, (W_INIT *)psInit))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* Add a button to the widget screen */
|
|
BOOL widgAddButton(W_SCREEN *psScreen, W_BUTINIT *psInit)
|
|
{
|
|
W_BUTTON *psButton;
|
|
W_FORM *psForm;
|
|
|
|
ASSERT( PTRVALID(psScreen, sizeof(W_SCREEN)),
|
|
"widgAddButton: Invalid screen pointer" );
|
|
|
|
if (widgCheckIDForm((W_FORM *)psScreen->psForm,psInit->id))
|
|
{
|
|
ASSERT( FALSE, "widgAddButton: ID number has already been used(%d)", psInit->id );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Find the form to put the button on */
|
|
if (psInit->formID == 0)
|
|
{
|
|
psForm = (W_FORM *)psScreen->psForm;
|
|
}
|
|
else
|
|
{
|
|
psForm = (W_FORM *)widgGetFromID(psScreen, psInit->formID);
|
|
if (psForm == NULL || psForm->type != WIDG_FORM)
|
|
{
|
|
ASSERT( FALSE,
|
|
"widgAddButton: Could not find parent form from formID" );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* Create the button structure */
|
|
if (!buttonCreate(&psButton, psInit))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Add it to the form */
|
|
if (!formAddWidget(psForm, (WIDGET *)psButton, (W_INIT *)psInit))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* Add an edit box to the widget screen */
|
|
BOOL widgAddEditBox(W_SCREEN *psScreen, W_EDBINIT *psInit)
|
|
{
|
|
W_EDITBOX *psEdBox;
|
|
W_FORM *psForm;
|
|
|
|
ASSERT( PTRVALID(psScreen, sizeof(W_SCREEN)),
|
|
"widgAddEditBox: Invalid screen pointer" );
|
|
|
|
if (widgCheckIDForm((W_FORM *)psScreen->psForm,psInit->id))
|
|
{
|
|
ASSERT( FALSE, "widgAddEditBox: ID number has already been used (%d)", psInit->id );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Find the form to put the edit box on */
|
|
if (psInit->formID == 0)
|
|
{
|
|
psForm = (W_FORM *)psScreen->psForm;
|
|
}
|
|
else
|
|
{
|
|
psForm = (W_FORM *)widgGetFromID(psScreen, psInit->formID);
|
|
if (!psForm || psForm->type != WIDG_FORM)
|
|
{
|
|
ASSERT( FALSE,
|
|
"widgAddEditBox: Could not find parent form from formID" );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* Create the edit box structure */
|
|
if (!editBoxCreate(&psEdBox, psInit))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Add it to the form */
|
|
if (!formAddWidget(psForm, (WIDGET *)psEdBox, (W_INIT *)psInit))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* Add a bar graph to the widget screen */
|
|
BOOL widgAddBarGraph(W_SCREEN *psScreen, W_BARINIT *psInit)
|
|
{
|
|
W_BARGRAPH *psBarGraph;
|
|
W_FORM *psForm;
|
|
|
|
ASSERT( PTRVALID(psScreen, sizeof(W_SCREEN)),
|
|
"widgAddEditBox: Invalid screen pointer" );
|
|
|
|
if (widgCheckIDForm((W_FORM *)psScreen->psForm,psInit->id))
|
|
{
|
|
ASSERT( FALSE, "widgAddBarGraph: ID number has already been used (%d)", psInit->id );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Find the form to put the bar graph on */
|
|
if (psInit->formID == 0)
|
|
{
|
|
psForm = (W_FORM *)psScreen->psForm;
|
|
}
|
|
else
|
|
{
|
|
psForm = (W_FORM *)widgGetFromID(psScreen, psInit->formID);
|
|
if (!psForm || psForm->type != WIDG_FORM)
|
|
{
|
|
ASSERT( FALSE,
|
|
"widgAddBarGraph: Could not find parent form from formID" );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* Create the bar graph structure */
|
|
if (!barGraphCreate(&psBarGraph, psInit))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Add it to the form */
|
|
if (!formAddWidget(psForm, (WIDGET *)psBarGraph, (W_INIT *)psInit))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* Add a slider to a form */
|
|
BOOL widgAddSlider(W_SCREEN *psScreen, W_SLDINIT *psInit)
|
|
{
|
|
W_SLIDER *psSlider;
|
|
W_FORM *psForm;
|
|
|
|
ASSERT( PTRVALID(psScreen, sizeof(W_SCREEN)),
|
|
"widgAddEditBox: Invalid screen pointer" );
|
|
|
|
if (widgCheckIDForm((W_FORM *)psScreen->psForm, psInit->id))
|
|
{
|
|
ASSERT( FALSE, "widgSlider: ID number has already been used (%d)", psInit->id );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Find the form to put the slider on */
|
|
if (psInit->formID == 0)
|
|
{
|
|
psForm = (W_FORM *)psScreen->psForm;
|
|
}
|
|
else
|
|
{
|
|
psForm = (W_FORM *)widgGetFromID(psScreen, psInit->formID);
|
|
if (!psForm || psForm->type != WIDG_FORM)
|
|
{
|
|
ASSERT( FALSE,
|
|
"widgAddSlider: Could not find parent form from formID" );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* Create the slider structure */
|
|
if (!sliderCreate(&psSlider, psInit))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Add it to the form */
|
|
if (!formAddWidget(psForm, (WIDGET *)psSlider, (W_INIT *)psInit))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* Delete a widget from a form */
|
|
static BOOL widgDeleteFromForm(W_FORM *psForm, UDWORD id, W_CONTEXT *psContext)
|
|
{
|
|
WIDGET *psPrev = NULL, *psCurr, *psNext;
|
|
W_TABFORM *psTabForm;
|
|
UDWORD minor,major;
|
|
W_MAJORTAB *psMajor;
|
|
W_MINORTAB *psMinor;
|
|
W_CONTEXT sNewContext;
|
|
|
|
/* Clear the last hilite if necessary */
|
|
if ((psForm->psLastHiLite != NULL) && (psForm->psLastHiLite->id == id))
|
|
{
|
|
widgHiLiteLost(psForm->psLastHiLite, psContext);
|
|
psForm->psLastHiLite = NULL;
|
|
}
|
|
|
|
if (psForm->style & WFORM_TABBED)
|
|
{
|
|
psTabForm = (W_TABFORM *)psForm;
|
|
ASSERT( PTRVALID(psTabForm, sizeof(W_TABFORM)),
|
|
"widgDeleteFromForm: Invalid form pointer" );
|
|
|
|
/* loop through all the tabs */
|
|
psMajor = psTabForm->asMajor;
|
|
for(major=0; major < psTabForm->numMajor; major++)
|
|
{
|
|
psMinor = psMajor->asMinor;
|
|
for(minor=0; minor < psMajor->numMinor; minor++)
|
|
{
|
|
if (psMinor->psWidgets && psMinor->psWidgets->id == id)
|
|
{
|
|
/* The widget is the first on this tab */
|
|
psNext = psMinor->psWidgets->psNext;
|
|
widgRelease(psMinor->psWidgets);
|
|
psMinor->psWidgets = psNext;
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
for(psCurr = psMinor->psWidgets; psCurr; psCurr = psCurr->psNext)
|
|
{
|
|
if (psCurr->id == id)
|
|
{
|
|
psPrev->psNext = psCurr->psNext;
|
|
widgRelease(psCurr);
|
|
|
|
return TRUE;
|
|
}
|
|
if (psCurr->type == WIDG_FORM)
|
|
{
|
|
/* Recurse down to other form */
|
|
sNewContext.psScreen = psContext->psScreen;
|
|
sNewContext.psForm = (W_FORM *)psCurr;
|
|
sNewContext.xOffset = psContext->xOffset - psCurr->x;
|
|
sNewContext.yOffset = psContext->yOffset - psCurr->y;
|
|
sNewContext.mx = psContext->mx - psCurr->x;
|
|
sNewContext.my = psContext->my - psCurr->y;
|
|
if (widgDeleteFromForm((W_FORM *)psCurr, id, &sNewContext))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
psPrev = psCurr;
|
|
}
|
|
}
|
|
psMinor++;
|
|
}
|
|
psMajor++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT( PTRVALID(psForm, sizeof(W_FORM)),
|
|
"widgDeleteFromForm: Invalid form pointer" );
|
|
|
|
/* Delete from a normal form */
|
|
if (psForm->psWidgets && psForm->psWidgets->id == id)
|
|
{
|
|
/* The widget is the first in the list */
|
|
psNext = psForm->psWidgets->psNext;
|
|
widgRelease(psForm->psWidgets);
|
|
psForm->psWidgets = psNext;
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* Search the rest of the list */
|
|
for(psCurr = psForm->psWidgets; psCurr; psCurr = psCurr->psNext)
|
|
{
|
|
if (psCurr->id == id)
|
|
{
|
|
psPrev->psNext = psCurr->psNext;
|
|
widgRelease(psCurr);
|
|
|
|
return TRUE;
|
|
}
|
|
if (psCurr->type == WIDG_FORM)
|
|
{
|
|
/* Recurse down to other form */
|
|
sNewContext.psScreen = psContext->psScreen;
|
|
sNewContext.psForm = (W_FORM *)psCurr;
|
|
sNewContext.xOffset = psContext->xOffset - psCurr->x;
|
|
sNewContext.yOffset = psContext->yOffset - psCurr->y;
|
|
sNewContext.mx = psContext->mx - psCurr->x;
|
|
sNewContext.my = psContext->my - psCurr->y;
|
|
if (widgDeleteFromForm((W_FORM *)psCurr, id, &sNewContext))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
psPrev = psCurr;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/* Delete a widget from the screen */
|
|
void widgDelete(W_SCREEN *psScreen, UDWORD id)
|
|
{
|
|
W_CONTEXT sContext;
|
|
|
|
ASSERT( PTRVALID(psScreen, sizeof(W_SCREEN)),
|
|
"widgDelete: Invalid screen pointer" );
|
|
|
|
/* Clear the keyboard focus if necessary */
|
|
if ((psScreen->psFocus != NULL) && (psScreen->psFocus->id == id))
|
|
{
|
|
screenClearFocus(psScreen);
|
|
}
|
|
|
|
/* Set up the initial context */
|
|
sContext.psScreen = psScreen;
|
|
sContext.psForm = (W_FORM *)psScreen->psForm;
|
|
sContext.xOffset = 0;
|
|
sContext.yOffset = 0;
|
|
sContext.mx = mouseX();
|
|
sContext.my = mouseY();
|
|
(void)widgDeleteFromForm((W_FORM *)psScreen->psForm, id, &sContext);
|
|
}
|
|
|
|
|
|
/* Initialise a form and all it's widgets */
|
|
static void widgStartForm(W_FORM *psForm)
|
|
{
|
|
WIDGET *psCurr;
|
|
W_FORMGETALL sGetAll;
|
|
|
|
/* Initialise this form */
|
|
formInitialise(psForm);
|
|
|
|
/*Initialise the widgets on the form */
|
|
formInitGetAllWidgets(psForm, &sGetAll);
|
|
psCurr = formGetAllWidgets(&sGetAll);
|
|
while (psCurr != NULL)
|
|
{
|
|
switch (psCurr->type)
|
|
{
|
|
case WIDG_FORM:
|
|
widgStartForm((W_FORM *)psCurr);
|
|
break;
|
|
case WIDG_LABEL:
|
|
break;
|
|
case WIDG_BUTTON:
|
|
buttonInitialise((W_BUTTON *)psCurr);
|
|
break;
|
|
case WIDG_EDITBOX:
|
|
editBoxInitialise((W_EDITBOX *)psCurr);
|
|
break;
|
|
case WIDG_BARGRAPH:
|
|
break;
|
|
case WIDG_SLIDER:
|
|
sliderInitialise((W_SLIDER *)psCurr);
|
|
break;
|
|
default:
|
|
ASSERT( FALSE,"widgStartScreen: Unknown widget type" );
|
|
break;
|
|
}
|
|
|
|
psCurr = psCurr->psNext;
|
|
if (!psCurr)
|
|
{
|
|
/* Got to the end of this list see if there is another */
|
|
psCurr = formGetAllWidgets(&sGetAll);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Initialise the set of widgets that make up a screen */
|
|
void widgStartScreen(W_SCREEN *psScreen)
|
|
{
|
|
psScreen->psFocus = NULL;
|
|
widgStartForm((W_FORM *)psScreen->psForm);
|
|
}
|
|
|
|
/* Clean up after a screen has been run */
|
|
void widgEndScreen(W_SCREEN *psScreen)
|
|
{
|
|
(void)psScreen;
|
|
}
|
|
|
|
/* Find a widget on a form from it's id number */
|
|
static WIDGET *widgFormGetFromID(W_FORM *psForm, UDWORD id)
|
|
{
|
|
WIDGET *psCurr, *psFound;
|
|
W_FORMGETALL sGetAll;
|
|
|
|
/* See if the form matches the ID */
|
|
if (psForm->id == id)
|
|
{
|
|
return (WIDGET *)psForm;
|
|
}
|
|
|
|
/* Now search the widgets on the form */
|
|
psFound = NULL;
|
|
formInitGetAllWidgets(psForm,&sGetAll);
|
|
psCurr = formGetAllWidgets(&sGetAll);
|
|
while (psCurr && !psFound)
|
|
{
|
|
if (psCurr->id == id)
|
|
{
|
|
psFound = psCurr;
|
|
}
|
|
else if (psCurr->type == WIDG_FORM)
|
|
{
|
|
psFound = widgFormGetFromID((W_FORM *)psCurr, id);
|
|
}
|
|
|
|
psCurr = psCurr->psNext;
|
|
if (!psCurr)
|
|
{
|
|
/* Got to the end of this list see if there is another */
|
|
psCurr = formGetAllWidgets(&sGetAll);
|
|
}
|
|
}
|
|
|
|
return psFound;
|
|
}
|
|
|
|
/* Find a widget in a screen from its ID number */
|
|
WIDGET *widgGetFromID(W_SCREEN *psScreen, UDWORD id)
|
|
{
|
|
ASSERT( PTRVALID(psScreen, sizeof(W_SCREEN)),
|
|
"widgGetFromID: Invalid screen pointer" );
|
|
|
|
return widgFormGetFromID((W_FORM *)psScreen->psForm, id);
|
|
}
|
|
|
|
|
|
/* Hide a widget */
|
|
void widgHide(W_SCREEN *psScreen, UDWORD id)
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
ASSERT( PTRVALID(psWidget, sizeof(WIDGET)),
|
|
"widgHide: couldn't find widget from id" );
|
|
if (psWidget)
|
|
{
|
|
psWidget->style |= WIDG_HIDDEN;
|
|
}
|
|
}
|
|
|
|
|
|
/* Reveal a widget */
|
|
void widgReveal(W_SCREEN *psScreen, UDWORD id)
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
ASSERT( PTRVALID(psWidget, sizeof(WIDGET)),
|
|
"widgReveal: couldn't find widget from id" );
|
|
if (psWidget)
|
|
{
|
|
psWidget->style &= ~WIDG_HIDDEN;
|
|
}
|
|
}
|
|
|
|
|
|
/* Get the current position of a widget */
|
|
void widgGetPos(W_SCREEN *psScreen, UDWORD id, SWORD *pX, SWORD *pY)
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
/* Find the widget */
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
if (psWidget != NULL)
|
|
{
|
|
*pX = psWidget->x;
|
|
*pY = psWidget->y;
|
|
}
|
|
else
|
|
{
|
|
ASSERT( FALSE, "widgGetPos: Couldn't find widget from ID" );
|
|
*pX = 0;
|
|
*pY = 0;
|
|
}
|
|
}
|
|
|
|
/* Return the ID of the widget the mouse was over this frame */
|
|
UDWORD widgGetMouseOver(W_SCREEN *psScreen)
|
|
{
|
|
/* Don't actually need the screen parameter at the moment - but it might be
|
|
handy if psMouseOverWidget needs to stop being a static and moves into
|
|
the screen structure */
|
|
(void)psScreen;
|
|
|
|
if (psMouseOverWidget == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return psMouseOverWidget->id;
|
|
}
|
|
|
|
|
|
/* Return the user data for a widget */
|
|
void *widgGetUserData(W_SCREEN *psScreen, UDWORD id)
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
if (psWidget)
|
|
{
|
|
return psWidget->pUserData;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/* Return the user data for a widget */
|
|
UDWORD widgGetUserData2(W_SCREEN *psScreen, UDWORD id)
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
if (psWidget)
|
|
{
|
|
return psWidget->UserData;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Set user data for a widget */
|
|
void widgSetUserData(W_SCREEN *psScreen, UDWORD id,void *UserData)
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
if (psWidget)
|
|
{
|
|
psWidget->pUserData = UserData;
|
|
}
|
|
}
|
|
|
|
/* Set user data for a widget */
|
|
void widgSetUserData2(W_SCREEN *psScreen, UDWORD id,UDWORD UserData)
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
if (psWidget)
|
|
{
|
|
psWidget->UserData = UserData;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* Return the user data for the returned widget */
|
|
void *widgGetLastUserData(W_SCREEN *psScreen)
|
|
{
|
|
/* Don't actually need the screen parameter at the moment - but it might be
|
|
handy if psRetWidget needs to stop being a static and moves into
|
|
the screen structure */
|
|
(void)psScreen;
|
|
|
|
if (psRetWidget)
|
|
{
|
|
return psRetWidget->pUserData;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* Set tip string for a widget */
|
|
void widgSetTip( W_SCREEN *psScreen, UDWORD id, STRING *pTip )
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
if ( psWidget )
|
|
{
|
|
switch (psWidget->type)
|
|
{
|
|
case WIDG_FORM:
|
|
if (psWidget->style & WFORM_CLICKABLE)
|
|
{
|
|
((W_CLICKFORM *) psWidget)->pTip = pTip;
|
|
}
|
|
else if (psWidget->style & WFORM_TABBED)
|
|
{
|
|
ASSERT( FALSE, "widgSetTip: tabbed forms do not have a tip" );
|
|
}
|
|
else
|
|
{
|
|
ASSERT( FALSE, "widgSetTip: plain forms do not have a tip" );
|
|
}
|
|
break;
|
|
|
|
case WIDG_LABEL:
|
|
((W_LABEL *) psWidget)->pTip = pTip;
|
|
break;
|
|
|
|
case WIDG_BUTTON:
|
|
((W_BUTTON *) psWidget)->pTip = pTip;
|
|
break;
|
|
|
|
case WIDG_BARGRAPH:
|
|
((W_BARGRAPH *) psWidget)->pTip = pTip;
|
|
break;
|
|
|
|
case WIDG_SLIDER:
|
|
((W_SLIDER *) psWidget)->pTip = pTip;
|
|
break;
|
|
|
|
case WIDG_EDITBOX:
|
|
ASSERT( FALSE, "widgSetTip: edit boxes do not have a tip" );
|
|
break;
|
|
|
|
default:
|
|
ASSERT( FALSE,"widgSetTip: Unknown widget type" );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Return which key was used to press the last returned widget */
|
|
UDWORD widgGetButtonKey(W_SCREEN *psScreen)
|
|
{
|
|
/* Don't actually need the screen parameter at the moment - but it might be
|
|
handy if released needs to stop being a static and moves into
|
|
the screen structure */
|
|
(void)psScreen;
|
|
|
|
return released;
|
|
}
|
|
|
|
|
|
/* Get a button or clickable form's state */
|
|
UDWORD widgGetButtonState(W_SCREEN *psScreen, UDWORD id)
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
/* Get the button */
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
if (psWidget == NULL)
|
|
{
|
|
ASSERT( FALSE, "widgGetButtonState: Couldn't find button/click form from ID" );
|
|
}
|
|
else if (psWidget->type == WIDG_BUTTON)
|
|
{
|
|
return buttonGetState((W_BUTTON *)psWidget);
|
|
}
|
|
else if ((psWidget->type == WIDG_FORM) && (psWidget->style & WFORM_CLICKABLE))
|
|
{
|
|
return formGetClickState((W_CLICKFORM *)psWidget);
|
|
}
|
|
else
|
|
{
|
|
ASSERT( FALSE, "widgGetButtonState: Couldn't find button/click form from ID" );
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
void widgSetButtonFlash(W_SCREEN *psScreen, UDWORD id)
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
/* Get the button */
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
if (psWidget == NULL)
|
|
{
|
|
ASSERT( FALSE, "widgSetButtonFlash: Couldn't find button/click form from ID" );
|
|
}
|
|
else if (psWidget->type == WIDG_BUTTON)
|
|
{
|
|
buttonSetFlash((W_BUTTON *)psWidget);
|
|
}
|
|
else if ((psWidget->type == WIDG_FORM) && (psWidget->style & WFORM_CLICKABLE))
|
|
{
|
|
formSetFlash((W_FORM *)psWidget);
|
|
}
|
|
else if ((psWidget->type == WIDG_EDITBOX))
|
|
{
|
|
// editBoxSetState((W_EDITBOX *)psWidget, state);
|
|
}
|
|
else
|
|
{
|
|
ASSERT( FALSE, "widgSetButtonFlash: Couldn't find button/click form from ID" );
|
|
}
|
|
}
|
|
|
|
|
|
void widgClearButtonFlash(W_SCREEN *psScreen, UDWORD id)
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
/* Get the button */
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
if (psWidget == NULL)
|
|
{
|
|
ASSERT( FALSE, "widgSetButtonFlash: Couldn't find button/click form from ID" );
|
|
}
|
|
else if (psWidget->type == WIDG_BUTTON)
|
|
{
|
|
buttonClearFlash((W_BUTTON *)psWidget);
|
|
}
|
|
else if ((psWidget->type == WIDG_FORM) && (psWidget->style & WFORM_CLICKABLE))
|
|
{
|
|
formClearFlash((W_FORM *)psWidget);
|
|
}
|
|
else if ((psWidget->type == WIDG_EDITBOX))
|
|
{
|
|
}
|
|
else
|
|
{
|
|
ASSERT( FALSE, "widgClearButtonFlash: Couldn't find button/click form from ID" );
|
|
}
|
|
}
|
|
|
|
|
|
/* Set a button or clickable form's state */
|
|
void widgSetButtonState(W_SCREEN *psScreen, UDWORD id, UDWORD state)
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
/* Get the button */
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
if (psWidget == NULL)
|
|
{
|
|
ASSERT( FALSE, "widgSetButtonState: Couldn't find button/click form from ID" );
|
|
}
|
|
else if (psWidget->type == WIDG_BUTTON)
|
|
{
|
|
buttonSetState((W_BUTTON *)psWidget, state);
|
|
}
|
|
else if ((psWidget->type == WIDG_FORM) && (psWidget->style & WFORM_CLICKABLE))
|
|
{
|
|
formSetClickState((W_CLICKFORM *)psWidget, state);
|
|
}
|
|
else if ((psWidget->type == WIDG_EDITBOX))
|
|
{
|
|
editBoxSetState((W_EDITBOX *)psWidget, state);
|
|
}
|
|
else
|
|
{
|
|
ASSERT( FALSE, "widgSetButtonState: Couldn't find button/click form from ID" );
|
|
}
|
|
}
|
|
|
|
|
|
/* Return a pointer to a buffer containing the current string of a widget.
|
|
* NOTE: The string must be copied out of the buffer
|
|
*/
|
|
STRING *widgGetString(W_SCREEN *psScreen, UDWORD id)
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
ASSERT( PTRVALID(psScreen, sizeof(W_SCREEN)),
|
|
"widgGetString: Invalid screen pointer" );
|
|
|
|
/* Get the widget */
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
if (psWidget != NULL)
|
|
{
|
|
switch (psWidget->type)
|
|
{
|
|
case WIDG_FORM:
|
|
ASSERT( FALSE, "widgGetString: Forms do not have a string" );
|
|
aStringRetBuffer[0]=0;
|
|
break;
|
|
case WIDG_LABEL:
|
|
strcpy(aStringRetBuffer, ((W_LABEL *)psWidget)->aText);
|
|
break;
|
|
case WIDG_BUTTON:
|
|
if (((W_BUTTON *)psWidget)->pText)
|
|
{
|
|
strcpy(aStringRetBuffer, ((W_BUTTON *)psWidget)->pText);
|
|
}
|
|
else
|
|
{
|
|
aStringRetBuffer[0]=0;
|
|
}
|
|
break;
|
|
case WIDG_EDITBOX:
|
|
strcpy(aStringRetBuffer, ((W_EDITBOX *)psWidget)->aText);
|
|
break;
|
|
case WIDG_BARGRAPH:
|
|
ASSERT( FALSE, "widgGetString: Bar Graphs do not have a string" );
|
|
aStringRetBuffer[0]=0;
|
|
break;
|
|
case WIDG_SLIDER:
|
|
ASSERT( FALSE, "widgGetString: Sliders do not have a string" );
|
|
aStringRetBuffer[0]=0;
|
|
break;
|
|
default:
|
|
ASSERT( FALSE,"widgGetString: Unknown widget type" );
|
|
aStringRetBuffer[0]=0;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT( FALSE, "widgGetString: couldn't get widget from id" );
|
|
aStringRetBuffer[0]=0;
|
|
}
|
|
|
|
return aStringRetBuffer;
|
|
}
|
|
|
|
|
|
/* Set the text in a widget */
|
|
void widgSetString(W_SCREEN *psScreen, UDWORD id, STRING *pText)
|
|
{
|
|
WIDGET *psWidget;
|
|
|
|
ASSERT( PTRVALID(psScreen, sizeof(W_SCREEN)),
|
|
"widgSetString: Invalid screen pointer" );
|
|
|
|
/* Get the widget */
|
|
psWidget = widgGetFromID(psScreen, id);
|
|
if (psWidget != NULL)
|
|
{
|
|
switch (psWidget->type)
|
|
{
|
|
case WIDG_FORM:
|
|
ASSERT( FALSE, "widgSetString: forms do not have a string" );
|
|
break;
|
|
case WIDG_LABEL:
|
|
widgCopyString(((W_LABEL *)psWidget)->aText, pText);
|
|
break;
|
|
case WIDG_BUTTON:
|
|
#if W_USE_STRHEAP
|
|
if (((W_BUTTON *)psWidget)->pText)
|
|
{
|
|
widgCopyString(((W_BUTTON *)psWidget)->pText, pText);
|
|
}
|
|
else
|
|
{
|
|
widgAllocCopyString(&((W_BUTTON *)psWidget)->pText, pText);
|
|
}
|
|
#else
|
|
((W_BUTTON *)psWidget)->pText = pText;
|
|
#endif
|
|
break;
|
|
case WIDG_EDITBOX:
|
|
if (psScreen->psFocus == psWidget)
|
|
{
|
|
screenClearFocus(psScreen);
|
|
}
|
|
editBoxSetString((W_EDITBOX *)psWidget, pText);
|
|
break;
|
|
case WIDG_BARGRAPH:
|
|
ASSERT( FALSE, "widgGetString: Bar graphs do not have a string" );
|
|
break;
|
|
case WIDG_SLIDER:
|
|
ASSERT( FALSE, "widgGetString: Sliders do not have a string" );
|
|
break;
|
|
default:
|
|
ASSERT( FALSE,"widgSetString: Unknown widget type" );
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT( FALSE, "widgSetString: couldn't get widget from id" );
|
|
}
|
|
}
|
|
|
|
|
|
/* Call any callbacks for the widgets on a form */
|
|
static void widgProcessCallbacks(W_CONTEXT *psContext)
|
|
{
|
|
WIDGET *psCurr;
|
|
W_CONTEXT sFormContext, sWidgContext;
|
|
SDWORD xOrigin, yOrigin;
|
|
W_FORMGETALL sFormCtl;
|
|
|
|
/* Initialise the form context */
|
|
sFormContext.psScreen = psContext->psScreen;
|
|
|
|
/* Initialise widget context */
|
|
formGetOrigin(psContext->psForm, &xOrigin, &yOrigin);
|
|
sWidgContext.psScreen = psContext->psScreen;
|
|
sWidgContext.psForm = psContext->psForm;
|
|
sWidgContext.mx = psContext->mx - xOrigin;
|
|
sWidgContext.my = psContext->my - yOrigin;
|
|
sWidgContext.xOffset = psContext->xOffset + xOrigin;
|
|
sWidgContext.yOffset = psContext->yOffset + yOrigin;
|
|
|
|
/* Go through all the widgets on the form */
|
|
formInitGetAllWidgets(psContext->psForm, &sFormCtl);
|
|
psCurr = formGetAllWidgets(&sFormCtl);
|
|
while (psCurr)
|
|
{
|
|
for(;psCurr; psCurr = psCurr->psNext)
|
|
{
|
|
|
|
/* Skip any hidden widgets */
|
|
/* Not sure if we want to skip hidden widgets or not ....
|
|
if (psCurr->style & WIDG_HIDDEN)
|
|
{
|
|
continue;
|
|
}*/
|
|
|
|
/* Call the callback */
|
|
if (psCurr->callback)
|
|
{
|
|
psCurr->callback(psCurr, &sWidgContext);
|
|
}
|
|
|
|
/* and then recurse */
|
|
if (psCurr->type == WIDG_FORM)
|
|
{
|
|
sFormContext.psForm = (W_FORM *)psCurr;
|
|
sFormContext.mx = sWidgContext.mx - psCurr->x;
|
|
sFormContext.my = sWidgContext.my - psCurr->y;
|
|
sFormContext.xOffset = sWidgContext.xOffset + psCurr->x;
|
|
sFormContext.yOffset = sWidgContext.yOffset + psCurr->y;
|
|
widgProcessCallbacks(&sFormContext);
|
|
}
|
|
}
|
|
|
|
/* See if the form has any more widgets on it */
|
|
psCurr = formGetAllWidgets(&sFormCtl);
|
|
}
|
|
}
|
|
|
|
|
|
/* Process all the widgets on a form.
|
|
* mx and my are the coords of the mouse relative to the form origin.
|
|
*/
|
|
static void widgProcessForm(W_CONTEXT *psContext)
|
|
{
|
|
WIDGET *psCurr, *psOver;
|
|
SDWORD mx,my, omx,omy, xOffset,yOffset, xOrigin,yOrigin;
|
|
W_FORM *psForm;
|
|
W_CONTEXT sFormContext, sWidgContext;
|
|
|
|
/* Note current form */
|
|
psForm = psContext->psForm;
|
|
|
|
// if(psForm->disableChildren == TRUE) {
|
|
// return;
|
|
// }
|
|
|
|
/* Note the current mouse position */
|
|
mx = psContext->mx;
|
|
my = psContext->my;
|
|
|
|
/* Note the current offset */
|
|
xOffset = psContext->xOffset;
|
|
yOffset = psContext->yOffset;
|
|
|
|
/* Initialise the form context */
|
|
sFormContext.psScreen = psContext->psScreen;
|
|
|
|
/* Initialise widget context */
|
|
formGetOrigin(psForm, &xOrigin, &yOrigin);
|
|
sWidgContext.psScreen = psContext->psScreen;
|
|
sWidgContext.psForm = psForm;
|
|
sWidgContext.mx = mx - xOrigin;
|
|
sWidgContext.my = my - yOrigin;
|
|
sWidgContext.xOffset = xOffset + xOrigin;
|
|
sWidgContext.yOffset = yOffset + yOrigin;
|
|
|
|
/* Process the form's widgets */
|
|
psOver = NULL;
|
|
for(psCurr = formGetWidgets(psForm); psCurr; psCurr = psCurr->psNext)
|
|
{
|
|
/* Skip any hidden widgets */
|
|
if (psCurr->style & WIDG_HIDDEN)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (psCurr->type == WIDG_FORM)
|
|
{
|
|
/* Found a sub form, so set up the context */
|
|
sFormContext.psForm = (W_FORM *)psCurr;
|
|
sFormContext.mx = mx - psCurr->x - xOrigin;
|
|
sFormContext.my = my - psCurr->y - yOrigin;
|
|
sFormContext.xOffset = xOffset + psCurr->x + xOrigin;
|
|
sFormContext.yOffset = yOffset + psCurr->y + yOrigin;
|
|
|
|
/* Process it */
|
|
widgProcessForm(&sFormContext);
|
|
}
|
|
else
|
|
{
|
|
/* Run the widget */
|
|
widgRun(psCurr, &sWidgContext);
|
|
}
|
|
}
|
|
|
|
/* Now check for mouse clicks */
|
|
omx = mx - xOrigin;
|
|
omy = my - yOrigin;
|
|
if (mx >= 0 && mx <= psForm->width &&
|
|
my >= 0 && my <= psForm->height)
|
|
{
|
|
/* Update for the origin */
|
|
|
|
/* Mouse is over the form - is it over any of the widgets */
|
|
for(psCurr = formGetWidgets(psForm); psCurr; psCurr = psCurr->psNext)
|
|
{
|
|
/* Skip any hidden widgets */
|
|
if (psCurr->style & WIDG_HIDDEN)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (omx >= psCurr->x &&
|
|
omy >= psCurr->y &&
|
|
omx <= psCurr->x + psCurr->width &&
|
|
omy <= psCurr->y + psCurr->height)
|
|
{
|
|
/* Note the widget the mouse is over */
|
|
if (!psMouseOverWidget)
|
|
{
|
|
psMouseOverWidget = (WIDGET *)psCurr;
|
|
}
|
|
psOver = psCurr;
|
|
|
|
/* Don't check the widgets if it is a clickable form */
|
|
if (!(psForm->style & WFORM_CLICKABLE))
|
|
{
|
|
if (pressed != WKEY_NONE && psCurr->type != WIDG_FORM)
|
|
{
|
|
/* Tell the widget it has been clicked */
|
|
widgClicked(psCurr, pressed, &sWidgContext);
|
|
}
|
|
if (released != WKEY_NONE && psCurr->type != WIDG_FORM)
|
|
{
|
|
/* Tell the widget the mouse button has gone up */
|
|
widgReleased(psCurr, released, &sWidgContext);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* Note that the mouse is over this form */
|
|
if (!psMouseOverWidget)
|
|
{
|
|
psMouseOverWidget = (WIDGET *)psForm;
|
|
}
|
|
|
|
/* Only send the Clicked or Released messages if a widget didn't get the message */
|
|
if (pressed != WKEY_NONE &&
|
|
(psOver == NULL || (psForm->style & WFORM_CLICKABLE)))
|
|
{
|
|
/* Tell the form it has been clicked */
|
|
widgClicked((WIDGET *)psForm, pressed, psContext);
|
|
}
|
|
if (released != WKEY_NONE &&
|
|
(psOver == NULL || (psForm->style & WFORM_CLICKABLE)))
|
|
{
|
|
/* Tell the form the mouse button has gone up */
|
|
widgReleased((WIDGET *)psForm, released, psContext);
|
|
}
|
|
}
|
|
|
|
/* See if the mouse has moved onto or off a widget */
|
|
if (psForm->psLastHiLite != psOver)
|
|
{
|
|
if (psOver != NULL)
|
|
{
|
|
widgHiLite(psOver, &sWidgContext);
|
|
}
|
|
if (psForm->psLastHiLite != NULL)
|
|
{
|
|
widgHiLiteLost(psForm->psLastHiLite, &sWidgContext);
|
|
}
|
|
psForm->psLastHiLite = psOver;
|
|
}
|
|
|
|
/* Run this form */
|
|
widgRun((WIDGET *)psForm, psContext);
|
|
}
|
|
|
|
|
|
|
|
/* Execute a set of widgets for one cycle.
|
|
* Return the id of the widget that was activated, or 0 for none.
|
|
*/
|
|
UDWORD widgRunScreen(W_SCREEN *psScreen)
|
|
{
|
|
W_CONTEXT sContext;
|
|
UDWORD returnID;
|
|
|
|
psRetWidget = NULL;
|
|
|
|
// Note which keys have been pressed
|
|
pressed = WKEY_NONE;
|
|
if(getWidgetsStatus())
|
|
{
|
|
|
|
if (mousePressed(MOUSE_LMB))
|
|
{
|
|
pressed = WKEY_PRIMARY;
|
|
}
|
|
else if (mousePressed(MOUSE_RMB))
|
|
{
|
|
pressed = WKEY_SECONDARY;
|
|
}
|
|
released = WKEY_NONE;
|
|
if (mouseReleased(MOUSE_LMB))
|
|
{
|
|
released = WKEY_PRIMARY;
|
|
}
|
|
else if (mouseReleased(MOUSE_RMB))
|
|
{
|
|
released = WKEY_SECONDARY;
|
|
}
|
|
}
|
|
/* Initialise the context */
|
|
sContext.psScreen = psScreen;
|
|
sContext.psForm = (W_FORM *)psScreen->psForm;
|
|
sContext.xOffset = 0;
|
|
sContext.yOffset = 0;
|
|
sContext.mx = mouseX();
|
|
sContext.my = mouseY();
|
|
psMouseOverWidget = NULL;
|
|
|
|
/* Process the screen's widgets */
|
|
widgProcessForm(&sContext);
|
|
|
|
/* Process any user callback functions */
|
|
widgProcessCallbacks(&sContext);
|
|
|
|
/* Return the ID of a pressed button or finished edit box if any */
|
|
if (psRetWidget)
|
|
{
|
|
returnID = psRetWidget->id;
|
|
}
|
|
else
|
|
{
|
|
returnID = 0;
|
|
}
|
|
return returnID;
|
|
}
|
|
|
|
|
|
/* Set the id number for widgRunScreen to return */
|
|
void widgSetReturn(WIDGET *psWidget)
|
|
{
|
|
psRetWidget = psWidget;
|
|
}
|
|
|
|
|
|
/* Display the widgets on a form */
|
|
static void widgDisplayForm(W_FORM *psForm, UDWORD xOffset, UDWORD yOffset)
|
|
{
|
|
WIDGET *psCurr = NULL;
|
|
SDWORD xOrigin = 0, yOrigin = 0;
|
|
|
|
|
|
/* Display the form */
|
|
psForm->display( (WIDGET *)psForm, xOffset, yOffset, psForm->aColours );
|
|
if(psForm->disableChildren == TRUE) {
|
|
return;
|
|
}
|
|
|
|
/* Update the offset from the current form's position */
|
|
formGetOrigin(psForm, &xOrigin, &yOrigin);
|
|
xOffset += psForm->x + xOrigin;
|
|
yOffset += psForm->y + yOrigin;
|
|
|
|
/* If this is a clickable form, the widgets on it have to move when it's down */
|
|
if(!(psForm->style & WFORM_NOCLICKMOVE)) {
|
|
if ((psForm->style & WFORM_CLICKABLE) &&
|
|
(((W_CLICKFORM *)psForm)->state &
|
|
(WCLICK_DOWN | WCLICK_LOCKED | WCLICK_CLICKLOCK)))
|
|
{
|
|
xOffset += 1;
|
|
yOffset += 1;
|
|
}
|
|
}
|
|
|
|
/* Display the widgets on the form */
|
|
for(psCurr = formGetWidgets(psForm); psCurr; psCurr = psCurr->psNext)
|
|
{
|
|
/* Skip any hidden widgets */
|
|
if (psCurr->style & WIDG_HIDDEN)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (psCurr->type == WIDG_FORM)
|
|
{
|
|
widgDisplayForm((W_FORM *)psCurr, xOffset, yOffset);
|
|
}
|
|
else
|
|
{
|
|
psCurr->display(psCurr, xOffset, yOffset, psForm->aColours);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* Display the screen's widgets in their current state
|
|
* (Call after calling widgRunScreen, this allows the input
|
|
* processing to be seperated from the display of the widgets).
|
|
*/
|
|
void widgDisplayScreen(W_SCREEN *psScreen)
|
|
{
|
|
/* Display the widgets */
|
|
widgDisplayForm((W_FORM *)psScreen->psForm, 0,0);
|
|
|
|
/* Display the tool tip if there is one */
|
|
tipDisplay();
|
|
}
|
|
|
|
|
|
/* Set the keyboard focus for the screen */
|
|
void screenSetFocus(W_SCREEN *psScreen, WIDGET *psWidget)
|
|
{
|
|
if (psScreen->psFocus != NULL)
|
|
{
|
|
widgFocusLost(psScreen->psFocus);
|
|
}
|
|
psScreen->psFocus = psWidget;
|
|
}
|
|
|
|
|
|
/* Clear the keyboard focus */
|
|
void screenClearFocus(W_SCREEN *psScreen)
|
|
{
|
|
if (psScreen->psFocus != NULL)
|
|
{
|
|
widgFocusLost(psScreen->psFocus);
|
|
psScreen->psFocus = NULL;
|
|
}
|
|
}
|
|
|
|
/* Call the correct function for loss of focus */
|
|
void widgFocusLost(WIDGET *psWidget)
|
|
{
|
|
switch (psWidget->type)
|
|
{
|
|
case WIDG_FORM:
|
|
break;
|
|
case WIDG_LABEL:
|
|
break;
|
|
case WIDG_BUTTON:
|
|
break;
|
|
case WIDG_EDITBOX:
|
|
editBoxFocusLost((W_EDITBOX *)psWidget);
|
|
break;
|
|
case WIDG_BARGRAPH:
|
|
break;
|
|
case WIDG_SLIDER:
|
|
break;
|
|
default:
|
|
ASSERT( FALSE,"widgFocusLost: Unknown widget type" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Call the correct function for mouse over */
|
|
void widgHiLite(WIDGET *psWidget, W_CONTEXT *psContext)
|
|
{
|
|
(void)psContext;
|
|
switch (psWidget->type)
|
|
{
|
|
case WIDG_FORM:
|
|
formHiLite((W_FORM *)psWidget, psContext);
|
|
break;
|
|
case WIDG_LABEL:
|
|
labelHiLite((W_LABEL *)psWidget, psContext);
|
|
break;
|
|
case WIDG_BUTTON:
|
|
buttonHiLite((W_BUTTON *)psWidget, psContext);
|
|
break;
|
|
case WIDG_EDITBOX:
|
|
editBoxHiLite((W_EDITBOX *)psWidget);
|
|
break;
|
|
case WIDG_BARGRAPH:
|
|
barGraphHiLite((W_BARGRAPH *)psWidget, psContext);
|
|
break;
|
|
case WIDG_SLIDER:
|
|
sliderHiLite((W_SLIDER *)psWidget);
|
|
break;
|
|
default:
|
|
ASSERT( FALSE,"widgHiLite: Unknown widget type" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* Call the correct function for mouse moving off */
|
|
void widgHiLiteLost(WIDGET *psWidget, W_CONTEXT *psContext)
|
|
{
|
|
(void)psContext;
|
|
switch (psWidget->type)
|
|
{
|
|
case WIDG_FORM:
|
|
formHiLiteLost((W_FORM *)psWidget, psContext);
|
|
break;
|
|
case WIDG_LABEL:
|
|
labelHiLiteLost((W_LABEL *)psWidget);
|
|
break;
|
|
case WIDG_BUTTON:
|
|
buttonHiLiteLost((W_BUTTON *)psWidget);
|
|
break;
|
|
case WIDG_EDITBOX:
|
|
editBoxHiLiteLost((W_EDITBOX *)psWidget);
|
|
break;
|
|
case WIDG_BARGRAPH:
|
|
barGraphHiLiteLost((W_BARGRAPH *)psWidget);
|
|
break;
|
|
case WIDG_SLIDER:
|
|
sliderHiLiteLost((W_SLIDER *)psWidget);
|
|
break;
|
|
default:
|
|
ASSERT( FALSE,"widgHiLiteLost: Unknown widget type" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Call the correct function for mouse pressed */
|
|
static void widgClicked(WIDGET *psWidget, UDWORD key, W_CONTEXT *psContext)
|
|
{
|
|
switch (psWidget->type)
|
|
{
|
|
case WIDG_FORM:
|
|
formClicked((W_FORM *)psWidget, key);
|
|
break;
|
|
case WIDG_LABEL:
|
|
break;
|
|
case WIDG_BUTTON:
|
|
buttonClicked((W_BUTTON *)psWidget, key);
|
|
break;
|
|
case WIDG_EDITBOX:
|
|
editBoxClicked((W_EDITBOX *)psWidget, psContext);
|
|
break;
|
|
case WIDG_BARGRAPH:
|
|
break;
|
|
case WIDG_SLIDER:
|
|
sliderClicked((W_SLIDER *)psWidget, psContext);
|
|
break;
|
|
default:
|
|
ASSERT( FALSE,"widgClicked: Unknown widget type" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* Call the correct function for mouse released */
|
|
static void widgReleased(WIDGET *psWidget, UDWORD key, W_CONTEXT *psContext)
|
|
{
|
|
switch (psWidget->type)
|
|
{
|
|
case WIDG_FORM:
|
|
formReleased((W_FORM *)psWidget, key, psContext);
|
|
break;
|
|
case WIDG_LABEL:
|
|
break;
|
|
case WIDG_BUTTON:
|
|
buttonReleased((W_BUTTON *)psWidget, key);
|
|
break;
|
|
case WIDG_EDITBOX:
|
|
editBoxReleased((W_EDITBOX *)psWidget);
|
|
break;
|
|
case WIDG_BARGRAPH:
|
|
break;
|
|
case WIDG_SLIDER:
|
|
sliderReleased((W_SLIDER *)psWidget);
|
|
break;
|
|
default:
|
|
ASSERT( FALSE,"widgReleased: Unknown widget type" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* Call the correct function to run a widget */
|
|
static void widgRun(WIDGET *psWidget, W_CONTEXT *psContext)
|
|
{
|
|
switch (psWidget->type)
|
|
{
|
|
case WIDG_FORM:
|
|
formRun((W_FORM *)psWidget, psContext);
|
|
break;
|
|
case WIDG_LABEL:
|
|
break;
|
|
case WIDG_BUTTON:
|
|
buttonRun((W_BUTTON *)psWidget);
|
|
break;
|
|
case WIDG_EDITBOX:
|
|
editBoxRun((W_EDITBOX *)psWidget, psContext);
|
|
break;
|
|
case WIDG_BARGRAPH:
|
|
break;
|
|
case WIDG_SLIDER:
|
|
sliderRun((W_SLIDER *)psWidget, psContext);
|
|
break;
|
|
default:
|
|
ASSERT( FALSE,"widgRun: Unknown widget type" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void WidgSetAudio(WIDGET_AUDIOCALLBACK Callback,SWORD HilightID,SWORD ClickedID)
|
|
{
|
|
AudioCallback = Callback;
|
|
HilightAudioID = HilightID;
|
|
ClickedAudioID = ClickedID;
|
|
}
|
|
|
|
|
|
WIDGET_AUDIOCALLBACK WidgGetAudioCallback(void)
|
|
{
|
|
return AudioCallback;
|
|
}
|
|
|
|
|
|
SWORD WidgGetHilightAudioID(void)
|
|
{
|
|
return HilightAudioID;
|
|
}
|
|
|
|
|
|
SWORD WidgGetClickedAudioID(void)
|
|
{
|
|
return ClickedAudioID;
|
|
}
|
|
|
|
|
|
void setWidgetsStatus(BOOL var)
|
|
{
|
|
bWidgetsActive = var;
|
|
}
|
|
|
|
BOOL getWidgetsStatus( void )
|
|
{
|
|
return(bWidgetsActive);
|
|
}
|