diff --git a/Makefile.am b/Makefile.am index d270486..5466ca5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -30,8 +30,8 @@ cmSRC += src/libcm/cmMidiFilePlay.c src/libcm/cmMidiPort.c src/libcm/cmMidiFile. cmHDR += src/libcm/cmAudioFile.h src/libcm/cmAudioFileMgr.h src/libcm/cmMsgProtocol.h src/libcm/cmAudioSys.h src/libcm/cmAudioPortFile.h src/libcm/cmAudioFileDev.h cmSRC += src/libcm/cmAudioFile.c src/libcm/cmAudioFileMgr.c src/libcm/cmMsgProtocol.c src/libcm/cmAudioSys.c src/libcm/cmAudioPortFile.c src/libcm/cmAudioFileDev.c -cmHDR += src/libcm/cmDevCfg.h -cmSRC += src/libcm/cmDevCfg.c +cmHDR += src/libcm/cmDevCfg.h src/libcm/cmUi.h src/libcm/cmUiDrvr.h +cmSRC += src/libcm/cmDevCfg.c src/libcm/cmUi.c cmHDR += src/libcm/cmFrameFile.h src/libcm/cmFeatFile.h src/libcm/cmCsv.h src/libcm/cmAudLabelFile.h src/libcm/cmTagFile.h cmSRC += src/libcm/cmFrameFile.c src/libcm/cmFeatFile.c src/libcm/cmCsv.c src/libcm/cmAudLabelFile.c src/libcm/cmTagFile.c @@ -68,7 +68,6 @@ cmSRC += src/libcm/cmProcObj.c src/libcm/cmProc.c src/libcm/cmProc2.c src/libcm/ cmHDR += src/libcm/app/cmOnset.h src/libcm/app/cmTimeLine.h src/libcm/app/cmScore.h src/libcm/app/cmPickup.h src/libcm/cmRbm.h cmSRC += src/libcm/app/cmOnset.c src/libcm/app/cmTimeLine.c src/libcm/app/cmScore.c src/libcm/app/cmPickup.c src/libcm/cmRbm.c - if OS_LINUX cmSRC += src/libcm/linux/cmFileSysLinux.c src/libcm/linux/cmAudioPortAlsa.c src/libcm/linux/cmMidiAlsa.c cmHDR += src/libcm/linux/cmFileSysLinux.h src/libcm/linux/cmAudioPortAlsa.h diff --git a/cmUi.c b/cmUi.c new file mode 100644 index 0000000..7d2095c --- /dev/null +++ b/cmUi.c @@ -0,0 +1,1701 @@ +#include "cmGlobal.h" +#include "cmRpt.h" +#include "cmErr.h" +#include "cmCtx.h" +#include "cmMem.h" +#include "cmMallocDebug.h" +#include "cmArray.h" +#include "cmJson.h" +#include "cmUiDrvr.h" +#include "cmUi.h" + + +typedef struct +{ + int x; + int y; + int w; + int h; +} cmUiRect_t; + +enum +{ + kUseRectUiFl = 0x01, + kPlaceRightUiFl = 0x02, // place only next control to right of prev control + kPlaceBelowUiFl = 0x04, // place only next control to below prev control + kPlaceBaseRowUiFl = 0x08, // place only next control at base row + kNextWHUiFl = 0x10, // size next control according to nextW,nextH + kFillRowsUiFl = 0x20, // current dflt fill direction +}; + +typedef struct cmUiApp_str +{ + unsigned appId; // app id and index into cmUI_t.appArrH[]. + bool activeFl; // true if this app recd is active and valid + cmArrayH_t ctlArrH; // cmUiCtl_t[] + cmArrayH_t pnlArrH; // cmUiPanel_t[] +} cmUiApp_t; + +typedef struct cmUiPanel_str +{ + cmUiApp_t* appPtr; // owner app. + unsigned flags; // See kXXXUiFl above + unsigned usrId; // app. supplied id + cmUiRect_t rect; // rect to position next control (only used if kUseRectUiFl is set) + cmUiRect_t prevRect; + int baseCol; + int baseRow; + int dfltW; + int dfltH; + int nextW; + int nextH; + int dfltHBorder; + int dfltVBorder; + int nextHBorder; + int nextVBorder; + +} cmUiPanel_t; + + +typedef struct cmUiCtl_str +{ + cmUiCId_t cId; // control type and used to decode the value union below. + unsigned usrId; // control instance id and index into cmUiApp_t.ctlArrH[]. + unsigned panelId; // panel this ctl belongs to + cmArrayH_t idArrH; // id's associated with each sub-element of this control (used by menu's, list's, etc...) + + // current value of this control + union + { + int ival; + double fval; + cmChar_t* sval; + cmUiPanel_t* pnl; + } u; + + int (*getInt)( struct cmUiCtl_str* c ); + double (*getDbl)( struct cmUiCtl_str* c ); + const cmChar_t* (*getStr)( struct cmUiCtl_str* c ); + + void (*setInt)( struct cmUiCtl_str* c, int v ); + void (*setDbl)( struct cmUiCtl_str* c, double v ); + void (*setStr)( struct cmUiCtl_str* c, const cmChar_t* s ); + +} cmUiCtl_t; + + +typedef struct +{ + cmErr_t err; // + cmCtx_t* ctx; // Global context. + cmUiDriverFunc_t drvr; // Driver callback function + void* drvrArg; // Driver callback function arg. + int panelW; // Panel width. + int panelH; // Panel height + unsigned curAppId; // Id of application currently receiveing commands/queries. + cmUiDriverFunc_t cbFunc; // Client callback function + void * cbArg; // + cmArrayH_t appArrH; // cmUiApp_t[] +} cmUi_t; + +cmUiH_t cmUiNullHandle = cmSTATIC_NULL_HANDLE; + +cmUi_t* _cmUiHandleToPtr( cmUiH_t h ) +{ + cmUi_t* p = (cmUi_t*)h.h; + assert(p != NULL ); + return p; +} + +void _cmUiDriverArgInit( cmUiDriverArg_t* a, cmUi_t* p, cmUiDId_t dId, cmUiCId_t cId, unsigned panelId, unsigned usrId ) +{ + memset(a,0,sizeof(*a)); + a->cbArg = p->drvrArg; + a->dId = dId; + a->cId = cId; + a->appId = p->curAppId; + a->panelId = panelId; + a->usrId = usrId; + a->flags = 0; + a->x = -1; + a->y = -1; + a->w = -1; + a->h = -1; + a->ival = 0; + a->fval = 0; + a->sval = NULL; +} + +//--------------------------------------------------------------- +// int accessors + +int _cmUiGetIntFromInt( cmUiCtl_t* ctl ) +{ return ctl->u.ival; } + +double _cmUiGetDblFromInt( cmUiCtl_t* ctl ) +{ return ctl->u.ival; } + +const cmChar_t* _cmUiGetStrFromInt( cmUiCtl_t* ctl ) +{ assert(0); return ""; } + +void _cmUiSetIntFromInt( cmUiCtl_t* ctl, int v ) +{ ctl->u.ival = v; } + +void _cmUiSetIntFromDbl( cmUiCtl_t* ctl, double v ) +{ ctl->u.ival = round(v); } + +void _cmUiSetIntFromStr( cmUiCtl_t* ctl, const cmChar_t* v ) +{ assert(0); } + +void _cmUiSetIntAccessors( cmUiCtl_t* ctl ) +{ + ctl->getInt = _cmUiGetIntFromInt; + ctl->getDbl = _cmUiGetDblFromInt; + ctl->getStr = _cmUiGetStrFromInt; + + ctl->setInt = _cmUiSetIntFromInt; + ctl->setDbl = _cmUiSetIntFromDbl; + ctl->setStr = _cmUiSetIntFromStr; +} + +//--------------------------------------------------------------- +// double accessors + +int _cmUiGetIntFromDbl( cmUiCtl_t* ctl ) +{ return round(ctl->u.fval); } + +double _cmUiGetDblFromDbl( cmUiCtl_t* ctl ) +{ return ctl->u.fval; } + +const cmChar_t* _cmUiGetStrFromDbl( cmUiCtl_t* ctl ) +{ assert(0); return ""; } + +void _cmUiSetDblFromInt( cmUiCtl_t* ctl, int v ) +{ ctl->u.fval = v; } + +void _cmUiSetDblFromDbl( cmUiCtl_t* ctl, double v ) +{ ctl->u.fval = v; } + +void _cmUiSetDblFromStr( cmUiCtl_t* ctl, const cmChar_t* v ) +{ assert(0); } + +void _cmUiSetDblAccessors( cmUiCtl_t* ctl ) +{ + ctl->getInt = _cmUiGetIntFromDbl; + ctl->getDbl = _cmUiGetDblFromDbl; + ctl->getStr = _cmUiGetStrFromDbl; + + ctl->setInt = _cmUiSetDblFromInt; + ctl->setDbl = _cmUiSetDblFromDbl; + ctl->setStr = _cmUiSetDblFromStr; +} + +//--------------------------------------------------------------- +// string accessors + +int _cmUiGetIntFromStr( cmUiCtl_t* ctl ) +{ assert(0); return -1; } + +double _cmUiGetDblFromStr( cmUiCtl_t* ctl ) +{ assert(0); return -1; } + +const cmChar_t* _cmUiGetStrFromStr( cmUiCtl_t* ctl ) +{ return ctl->u.sval; } + +void _cmUiSetStrFromInt( cmUiCtl_t* ctl, int v ) +{ assert(0); } + +void _cmUiSetStrFromDbl( cmUiCtl_t* ctl, double v ) +{ assert(0); } + +void _cmUiSetStrFromStr( cmUiCtl_t* ctl, const cmChar_t* v ) +{ ctl->u.sval = cmMemResizeStr(ctl->u.sval, v==NULL ? "" : v); } + +void _cmUiSetStrAccessors( cmUiCtl_t* ctl ) +{ + ctl->getInt = _cmUiGetIntFromStr; + ctl->getDbl = _cmUiGetDblFromStr; + ctl->getStr = _cmUiGetStrFromStr; + + ctl->setInt = _cmUiSetStrFromInt; + ctl->setDbl = _cmUiSetStrFromDbl; + ctl->setStr = _cmUiSetStrFromStr; +} + +//--------------------------------------------------------------- + +cmUiRC_t _cmUiFindApp( cmUi_t* p, unsigned appId, cmUiApp_t** appRef, bool errFl ) +{ + cmUiRC_t rc = kOkUiRC; + cmUiApp_t* ap = NULL; + + // verify that the appId is a valid index + if( appId < cmArrayCount(p->appArrH) ) + ap = cmArrayPtr(cmUiApp_t,p->appArrH,appId); + + // if the app record was not already allocated + if( ap != NULL && ap->activeFl == false ) + ap = NULL; + + // report errors + if( ap == NULL ) + { + rc = kAppNotFoundUiRC; + + if( errFl ) + cmErrMsg(&p->err,rc,"App %i not found.", appId ); + + } + + *appRef = ap; + + return rc; +} + + +cmUiRC_t _cmUiFindCtl( cmUi_t* p, unsigned usrId, cmUiCtl_t** ctlRef, bool errFl ) +{ + cmUiRC_t rc = kOkUiRC; + cmUiApp_t* ap = NULL; + cmUiCtl_t* ctl = NULL; + + // find the app this ctl belongs to + if(( rc =_cmUiFindApp(p,p->curAppId,&ap,errFl)) != kOkUiRC ) + goto errLabel; + + // verify that the usrId is a valid index + if( usrId < cmArrayCount(ap->ctlArrH) ) + ctl = cmArrayPtr(cmUiCtl_t,ap->ctlArrH,usrId); + + // verify that the usrId of the recd matches the requested usr id + if( ctl!=NULL && ctl->usrId != usrId ) + ctl = NULL; + + // report errors + if( ctl==NULL ) + { + rc = kCtlNotFoundUiRC; + + if( errFl ) + cmErrMsg(&p->err,rc,"Control %i not found.",usrId); + } + errLabel: + + *ctlRef = ctl; + + return rc; +} + +cmUiRC_t _cmUiFastFindCtl( cmUi_t* p, unsigned usrId, cmUiCtl_t** ctlRef, bool errFl ) +{ + assert( p->curAppId < cmArrayCount(p->appArrH) ); + + cmUiApp_t* ap = cmArrayPtr(cmUiApp_t,p->appArrH,p->curAppId); + + assert( ap->activeFl && usrId < cmArrayCount(ap->ctlArrH) ); + + *ctlRef = cmArrayPtr(cmUiCtl_t,ap->ctlArrH,usrId); + + assert( (*ctlRef)->usrId == usrId ); + + return kOkUiRC; +} + +cmUiRC_t _cmUiFindPanel( cmUi_t* p, unsigned panelId, cmUiPanel_t** ppRef, bool errFl ) + +{ + cmUiRC_t rc = kOkUiRC; + cmUiApp_t* ap = NULL; + unsigned i,n; + + *ppRef = NULL; + + // find the app this ctl belongs to + if(( rc =_cmUiFindApp(p,p->curAppId,&ap,errFl)) != kOkUiRC ) + goto errLabel; + + n = cmArrayCount(ap->pnlArrH); + for(i=0; ipnlArrH,i))->usrId == panelId ) + break; + + errLabel: + + if(*ppRef == NULL) + { + rc = kPanelNotFoundUiRC; + + if( errFl ) + cmErrMsg(&p->err,rc,"Panel %i was not found.",panelId); + } + + + return rc; +} + +cmUiRC_t _cmUiCallDriver( cmUi_t* p, cmUiDriverArg_t* a ) +{ + cmUiRC_t rc = kOkUiRC; + if( p->drvr != NULL ) + if((rc = p->drvr(a)) != kOkUiRC ) + rc = cmErrMsg(&p->err,kDrvrErrUiRC,"UI manager driver error."); + return rc; +} + +cmUiRC_t _cmUiDestroyDrvrCtl( cmUi_t* p, cmUiCId_t cId, unsigned panelId, unsigned usrId ) +{ + cmUiDriverArg_t a; + _cmUiDriverArgInit(&a, p, kDestroyCtlDId, cId, panelId, usrId ); + + + return _cmUiCallDriver(p,&a); +} + +cmUiRC_t _cmUiDestroyCtl( cmUi_t* p, cmUiCtl_t* ctl ) +{ + cmUiRC_t rc = kOkUiRC; + + rc =_cmUiDestroyDrvrCtl(p,ctl->cId,ctl->panelId,ctl->usrId); + + switch(ctl->cId) + { + case kLabelUiCId: + case kTextUiCId: + case kFilenameUiCId: + case kDirUiCId: + cmMemFree(ctl->u.sval); + break; + + default: + break; + } + + ctl->usrId = cmInvalidId; + ctl->panelId = cmInvalidId; + cmArrayRelease(&ctl->idArrH); + + return rc; +} + +cmUiRC_t _cmUiDestroyPanel( cmUi_t* p, unsigned panelId ) +{ + cmUiRC_t rc = kOkUiRC; + cmUiPanel_t* pp = NULL; + + // get the panel recd ptr + if((rc = _cmUiFindPanel(p,panelId,&pp,true)) != kOkUiRC ) + return rc; + + cmUiApp_t* ap = pp->appPtr; + + // notify the driver to destroy the panel + if((rc = _cmUiDestroyDrvrCtl(p,kPanelUiCId,panelId,panelId)) != kOkUiRC ) + return rc; + + cmUiCtl_t* ctl = NULL; + unsigned i = 0; + unsigned n = cmArrayCount(ap->ctlArrH); + cmUiRC_t rc0; + + // Destroy all controls that belong to this panel. + // Notice that _cmUiDestroyCtl() does not need to call the driver + // because destroying the drivers panel has implicitely also + // destroyed all the contols assigned to it. + for(i=0; ipanelId == panelId) + if((rc0 = _cmUiDestroyCtl(p,ctl)) != kOkUiRC ) + rc = rc0; + + // release the panel record + pp->appPtr = NULL; + pp->usrId = cmInvalidId; + + return rc; +} + +cmUiRC_t _cmUiDestroyApp( cmUi_t* p, unsigned appId, bool errFl ) +{ + cmUiRC_t rc = kOkUiRC; + cmUiRC_t rc0; + cmUiApp_t* ap; + unsigned orgAppId = p->curAppId; + + p->curAppId = appId; + + // find the app to destroy + if( _cmUiFindApp(p,appId,&ap,false) != kOkUiRC ) + { + if( errFl ) + rc = cmErrMsg(&p->err,kAppNotFoundUiRC,"The app %i was not found for destruction.",appId); + + goto errLabel; + } + + assert( ap != NULL ); + + // destroy all panels owned by this app + unsigned i; + unsigned n = cmArrayCount(ap->pnlArrH); + for(i=0; ipnlArrH,i); + if( pp->usrId != cmInvalidId ) + if((rc0 = _cmUiDestroyPanel(p,pp->usrId)) != kOkUiRC ) + rc = rc0; + } + + ap->appId = -1; + ap->activeFl = false; + cmArrayRelease(&ap->ctlArrH); + cmArrayRelease(&ap->pnlArrH); + + errLabel: + p->curAppId = orgAppId; + + return rc; +} + +cmUiRC_t _cmUiDestroyAllApps( cmUi_t* p ) +{ + cmUiRC_t rc = kOkUiRC; + unsigned n = cmArrayCount(p->appArrH); + unsigned i; + for(i=0; iappArrH,false); + + return rc; +} + + +cmUiRC_t _cmUiGetCtlXYWH( cmUi_t* p, cmUiDriverArg_t* a, cmUiPanel_t* pp ) +{ + if( cmIsFlag(pp->flags,kUseRectUiFl ) ) + { + pp->flags = cmClrFlag(pp->flags,kUseRectUiFl); + a->x = pp->rect.x; + a->y = pp->rect.y; + a->w = pp->rect.w; + a->h = pp->rect.h; + return kOkUiRC; + } + + if( pp->prevRect.x == -1 ) + pp->prevRect.x = pp->baseCol; + + if( pp->prevRect.y == -1 ) + pp->prevRect.y = pp->baseRow; + + if( pp->prevRect.w == -1 ) + pp->prevRect.w = 0; + + if( pp->prevRect.h == -1 ) + pp->prevRect.h = 0; + + // Get direction flag. Fill across rows? or down columns? + bool fillRowFl = cmIsFlag(pp->flags,kFillRowsUiFl); + + // the 'place to right' flag overrides the directon flag for just this instance + if( cmIsFlag(pp->flags,kPlaceRightUiFl ) ) + fillRowFl = true; + + // the 'place under' flag overides the direction flag for just this instance + if( cmIsFlag(pp->flags,kPlaceBelowUiFl ) ) + fillRowFl = false; + + // set x coord - if filling acros rows ... + if( fillRowFl ) + a->x = pp->prevRect.x + pp->prevRect.w + pp->nextHBorder; + else + a->x = pp->baseCol; // ... or down columns + + // if a new column was set then move to the base row + if( cmIsFlag(pp->flags,kPlaceBaseRowUiFl) ) + a->y = pp->baseRow; + else + { + // set y coord - if filling acros rows ... + if( fillRowFl ) + a->y = pp->prevRect.y; + else + a->y = pp->prevRect.y + pp->prevRect.h + pp->nextVBorder; // ... or down columns + } + + a->w = pp->nextW; + a->h = pp->nextH; + + pp->prevRect.x = a->x; + pp->prevRect.y = a->y; + pp->prevRect.w = a->w; + pp->prevRect.h = a->h; + + pp->nextW = pp->dfltW; + pp->nextH = pp->dfltH; + pp->nextHBorder= pp->dfltHBorder; + pp->nextVBorder= pp->dfltVBorder; + + pp->flags = cmClrFlag(pp->flags,kNextWHUiFl | kPlaceRightUiFl | kPlaceBelowUiFl | kPlaceBaseRowUiFl ); + + return kOkUiRC; +} + + +cmUiRC_t _cmUiCreateCtl( cmUi_t* p, cmUiDriverArg_t* a, unsigned panelId, cmUiCId_t cId, unsigned usrId, const cmChar_t* label, unsigned flags, cmUiCtl_t** ctlRef ) +{ + cmUiRC_t rc; + cmUiPanel_t* pp = NULL; + cmUiApp_t* ap = NULL; + + if( ctlRef != NULL ) + *ctlRef = NULL; + + // initialize the driver arg record + _cmUiDriverArgInit(a, p, kCreateCtlDId, cId, panelId, usrId ); + + // locate the app + if((rc = _cmUiFindApp(p,p->curAppId,&ap,true)) != kOkUiRC ) + return rc; + + // locate the panel the control belongs to + if((rc = _cmUiFindPanel(p,panelId,&pp,true)) != kOkUiRC ) + return rc; + + // calc the control location - for non-panel controls or + // for panel controls using the custom 'next rect'. + if( cId != kPanelUiCId || cmIsFlag(pp->flags,kUseRectUiFl ) ) + if((rc = _cmUiGetCtlXYWH(p,a,pp)) != kOkUiRC ) + return rc; + + // get the new ctl record + cmUiCtl_t* ctl = cmArrayClr(cmUiCtl_t,ap->ctlArrH,usrId); + + // setup the new ctl record + ctl->cId = cId; + ctl->usrId = usrId; + ctl->panelId = panelId; + cmArrayAlloc(p->ctx,&ctl->idArrH,sizeof(unsigned)); + + a->sval = label; + a->flags = flags; + + if( ctlRef != NULL ) + *ctlRef = ctl; + + return _cmUiCallDriver(p,a); +} + + +cmUiRC_t cmUiAlloc( + cmCtx_t* ctx, + cmUiH_t* uiHPtr, + cmUiDriverFunc_t drvrFunc, + void* drvrArg, + cmUiDriverFunc_t cbFunc, + void * cbArg) +{ + cmUiRC_t rc; + if((rc = cmUiFree(uiHPtr)) != kOkUiRC ) + return rc; + + cmUi_t* p = cmMemAllocZ(cmUi_t,1); + cmErrSetup(&p->err,&ctx->rpt,"cmUi"); + + p->ctx = ctx; + p->drvr = drvrFunc; + p->drvrArg = drvrArg; + p->cbFunc = cbFunc; + p->cbArg = cbArg; + p->panelW = 1000; + p->panelH = 500; + + cmArrayAlloc(p->ctx,&p->appArrH,sizeof(cmUiApp_t)); + + uiHPtr->h = p; + + return rc; +} + +cmUiRC_t cmUiFree( cmUiH_t* hp ) +{ + cmUiRC_t rc = kOkUiRC; + + if( hp == NULL || cmUiIsValid(*hp)==false ) + return kOkUiRC; + + cmUi_t* p = _cmUiHandleToPtr(*hp); + + + if((rc = _cmUiDestroyAllApps(p)) != kOkUiRC ) + return rc; + + cmArrayRelease(&p->appArrH); + cmMemFree(p); + + hp->h = NULL; + + return rc; +} + + +bool cmUiIsValid( cmUiH_t h ) +{ return h.h != NULL; } + +void cmUiSetDriver( cmUiH_t h, cmUiDriverFunc_t drvrFunc, void* drvrArg ) +{ + cmUi_t* p = _cmUiHandleToPtr(h); + p->drvr = drvrFunc; + p->drvrArg = drvrArg; +} + + +cmUiRC_t cmUiCreateApp( cmUiH_t h, unsigned appId ) +{ + cmUiRC_t rc = kOkUiRC; + + if( cmUiIsValid(h)==false) + return rc; + + cmUi_t* p = _cmUiHandleToPtr(h); + cmUiApp_t* ap = NULL; + + // verify that the requested app does not exist + if( _cmUiFindApp(p,appId, &ap, false ) == kOkUiRC ) + return cmErrMsg(&p->err,kInvalidIdUiRC,"The id (%i) of the new application is already in use.",appId); + + ap = cmArrayClr(cmUiApp_t,p->appArrH,appId); + ap->appId = appId; + ap->activeFl = true; + cmArrayAlloc(p->ctx,&ap->ctlArrH,sizeof(cmUiCtl_t)); + cmArrayAlloc(p->ctx,&ap->pnlArrH,sizeof(cmUiPanel_t)); + + + return rc; +} + +cmUiRC_t cmUiDestroyApp( cmUiH_t h, unsigned appId ) +{ + if( cmUiIsValid(h)==false) + return kOkUiRC; + + cmUi_t* p = _cmUiHandleToPtr(h); + return _cmUiDestroyApp(p,appId,true); +} + + +cmUiRC_t cmUiDestroyAllApps( cmUiH_t h ) +{ + if( cmUiIsValid(h)==false) + return kOkUiRC; + + cmUi_t* p = _cmUiHandleToPtr(h); + return _cmUiDestroyAllApps(p); +} + +cmUiRC_t cmUiSetAppId( cmUiH_t h, unsigned appId ) +{ + cmUiRC_t rc = kOkUiRC; + + if( cmUiIsValid(h)==false) + return rc; + + cmUi_t* p = _cmUiHandleToPtr(h); + cmUiApp_t* ap = NULL; + + // verify that the requested app exists + if( appId != cmInvalidId ) + if((rc = _cmUiFindApp(p,appId, &ap, true )) != kOkUiRC ) + return rc; + + p->curAppId = appId; + return rc; +} + +unsigned cmUiAppCount( cmUiH_t h ) +{ + if( cmUiIsValid(h)==false) + return 0; + + cmUi_t* p = _cmUiHandleToPtr(h); + + return cmArrayCount(p->appArrH); +} + + + +cmUiRC_t cmUiOnDriverEvent( cmUiH_t h, const cmUiDriverArg_t* arg ) +{ + cmUiRC_t rc = kOkUiRC; + cmUi_t* p = _cmUiHandleToPtr(h); + cmUiDriverArg_t a = *arg; + cmUiCtl_t* ctl; + + if((rc = cmUiSetAppId(h,arg->appId)) != kOkUiRC ) + return rc; + + a.cbArg = p->cbArg; + + if((rc = _cmUiFindCtl(p,a.usrId,&ctl,true)) != kOkUiRC ) + goto errLabel; + + switch( a.cId ) + { + case kInvalidUiCId: break; + case kPanelUiCId: break; + case kBtnUiCId: break; + case kCheckUiCId: + ctl->u.ival = a.ival; + break; + + case kMenuBtnUiCId: + case kListUiCId: + { + ctl->u.ival = a.ival; + if(a.ival >= cmArrayCount(ctl->idArrH)) + { + rc = cmErrMsg(&p->err,kInvalidIdUiRC,"Invalid menu or list driver element id=%i element count:%i.",a.ival,cmArrayCount(ctl->idArrH)); + goto errLabel; + } + + a.ival = cmArrayEle(unsigned,ctl->idArrH,a.ival); + //a.ival = ctl->id_arr[ a.ival ]; + } + break; + + case kLabelUiCId: + ctl->u.sval = cmMemResizeStr(ctl->u.sval,cmStringNullGuard(a.sval)); + break; + + case kTextUiCId: + ctl->u.sval = cmMemResizeStr(ctl->u.sval,cmStringNullGuard(a.sval)); + break; + + case kSliderUiCId: + case kNumberUiCId: + ctl->u.fval = a.fval; + a.cId = kNumberUiCId; // sliders callback the client as numbers + break; + + case kProgressUiCId: + ctl->u.ival = a.ival; + break; + + case kMeterUiCId: + ctl->u.fval = a.fval; + break; + + case kFilenameUiCId: + ctl->u.sval = cmMemResizeStr(ctl->u.sval,cmStringNullGuard(a.sval)); + break; + + case kDirUiCId: + ctl->u.sval = cmMemResizeStr(ctl->u.sval,cmStringNullGuard(a.sval)); + break; + } + + rc = p->cbFunc(&a); + + errLabel: + cmUiSetAppId(h,cmInvalidId); + + return rc; +} + +cmUiRC_t cmUiCreatePanel( cmUiH_t uiH, unsigned newPanelId, const cmChar_t* label ) +{ + cmUiRC_t rc; + cmUiDriverArg_t a; + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiCtl_t* ctl = NULL; + cmUiApp_t* ap = NULL; + + if(( rc = _cmUiFindApp(p,p->curAppId,&ap,true)) != kOkUiRC ) + return rc; + + cmUiPanel_t* pp = cmArrayPush(ap->pnlArrH,NULL,1); + assert( pp != NULL ); + + pp->appPtr = ap; + pp->usrId = newPanelId; + pp->baseCol = 2; + pp->baseRow = 0; + pp->dfltW = 150; + pp->dfltH = 25; + pp->nextW = pp->dfltW; + pp->nextH = pp->dfltH; + pp->dfltHBorder= 2; + pp->dfltVBorder= 2; + pp->nextHBorder= pp->dfltHBorder; + pp->nextVBorder= pp->dfltVBorder; + pp->prevRect.x = -1; + pp->prevRect.y = -1; + pp->prevRect.w = -1; + pp->prevRect.h = -1; + + + if((rc = _cmUiCreateCtl(p, &a, newPanelId, kPanelUiCId, newPanelId, label, 0, NULL )) != kOkUiRC ) + { + // TODO - destroy panel record here + return rc; + } + + _cmUiFindCtl(p,newPanelId,&ctl,true); + + assert(ctl!=NULL); + ctl->u.pnl = pp; + return rc; +} + + +cmUiRC_t cmUiCreateBtn( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags ) +{ + cmUiRC_t rc; + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiDriverArg_t a; + cmUiCtl_t* c; + + if((rc = _cmUiCreateCtl(p,&a,panelId,kBtnUiCId,id,label,flags,&c)) == kOkUiRC ) + { + _cmUiSetIntAccessors(c); + } + return rc; +} + +cmUiRC_t cmUiCreateCheck( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, bool dflt ) +{ + cmUiRC_t rc; + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiDriverArg_t a; + cmUiCtl_t* c; + + a.ival = dflt; + if((rc = _cmUiCreateCtl(p,&a,panelId,kCheckUiCId,id,label,flags,&c)) == kOkUiRC ) + _cmUiSetIntAccessors(c); + return rc; +} + +cmUiRC_t cmUiCreateLabel( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags ) +{ + cmUiRC_t rc; + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiDriverArg_t a; + cmUiCtl_t* c; + + if((rc = _cmUiCreateCtl(p,&a,panelId,kLabelUiCId,id,label,flags,&c)) == kOkUiRC ) + _cmUiSetStrAccessors(c); + return rc; +} + +cmUiRC_t cmUiCreateText( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, const cmChar_t* text ) +{ + cmUiRC_t rc = kOkUiRC; + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiDriverArg_t a; + cmUiCtl_t* c; + + if(( rc = _cmUiCreateCtl(p,&a,panelId,kTextUiCId,id,label,flags,&c)) == kOkUiRC ) + { + _cmUiSetStrAccessors(c); + + a.dId = kSetValDId; + a.flags = kValUiFl; + a.sval = text; + rc = _cmUiCallDriver(p,&a); + } + + return rc; +} + +cmUiRC_t _cmUiCreateNumber( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, double min, double max, double incr, double dflt ) +{ + cmUiRC_t rc = kOkUiRC; + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiDriverArg_t a; + cmUiCId_t cid = kNumberUiCId; + cmUiCtl_t* c; + cmUiPanel_t* pp; + + if( cmIsFlag(flags,kVertUiFl|kHorzUiFl) ) + { + if( cmIsFlag(flags,kVertUiFl) ) + { + if((rc = _cmUiFindPanel(p,panelId,&pp,true)) != kOkUiRC ) + return rc; + + // if the size of the control was not excplicitly set + // then swap width and height + if( cmIsNotFlag(pp->flags,kNextWHUiFl) && cmIsNotFlag(pp->flags,kUseRectUiFl) ) + cmUiSetNextWH( uiH, panelId, cmUiH(uiH,panelId), cmUiW(uiH,panelId) ); + } + + cid = kSliderUiCId; + } + + if(( rc = _cmUiCreateCtl(p,&a,panelId,cid,id,label,flags,&c)) == kOkUiRC ) + { + cmUiRC_t rc0; + + _cmUiSetDblAccessors(c); + + a.dId = kSetValDId; + a.flags = kMinUiFl; + a.fval = min; + if((rc0 = _cmUiCallDriver(p,&a)) != kOkUiRC ) + rc = rc0; + + a.flags = kMaxUiFl; + a.fval = max; + if((rc0 = _cmUiCallDriver(p,&a)) != kOkUiRC ) + rc = rc0; + + a.flags = kIncUiFl; + a.fval = incr; + if((rc0 = _cmUiCallDriver(p,&a)) != kOkUiRC ) + rc = rc0; + + a.flags = kValUiFl; + a.fval = dflt; + if((rc0 = _cmUiCallDriver(p,&a)) != kOkUiRC ) + rc = rc0; + + } + + return rc; +} + +cmUiRC_t cmUiCreateNumber( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, double min, double max, double incr, double dflt ) +{ + return _cmUiCreateNumber(uiH,panelId,id,label,flags,min,max,incr,dflt); +} + +cmUiRC_t cmUiCreateHSlider( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, double min, double max, double incr, double dflt ) +{ + return _cmUiCreateNumber(uiH,panelId,id,label,flags | kHorzUiFl, min,max,incr,dflt); +} + +cmUiRC_t cmUiCreateVSlider( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, double min, double max, double incr, double dflt ) +{ + return _cmUiCreateNumber(uiH,panelId,id,label,flags | kVertUiFl, min,max,incr,dflt); +} + + +cmUiRC_t cmUiCreateProgress(cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, int min, int max, int dflt ) +{ + cmUiRC_t rc = kOkUiRC; + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiDriverArg_t a; + cmUiCtl_t* c; + + if(( rc = _cmUiCreateCtl(p,&a,panelId,kProgressUiCId,id,label,flags,&c)) == kOkUiRC ) + { + cmUiRC_t rc0; + + _cmUiSetIntAccessors(c); + + a.dId = kSetValDId; + + a.flags = kMinUiFl; + a.ival = min; + if((rc0 = _cmUiCallDriver(p,&a)) != kOkUiRC ) + rc = rc0; + + a.flags = kMaxUiFl; + a.ival = max; + if((rc0 = _cmUiCallDriver(p,&a)) != kOkUiRC ) + rc = rc0; + + a.flags = kValUiFl; + a.ival = dflt; + if((rc0 = _cmUiCallDriver(p,&a)) != kOkUiRC ) + rc = rc0; + + } + + return rc; +} + +cmUiRC_t _cmUiCreateMeter( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, int min, int max, int dflt) +{ + cmUiRC_t rc; + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiDriverArg_t a; + cmUiCtl_t* c; + cmUiPanel_t* pp; + + if( cmIsFlag(flags,kVertUiFl) ) + { + if((rc = _cmUiFindPanel(p,panelId,&pp,true)) != kOkUiRC ) + return rc; + + // if the size of the control has not been explicitely set + // then swap height and width for vertical meters. + if( cmIsNotFlag(pp->flags,kNextWHUiFl) && cmIsNotFlag(pp->flags,kUseRectUiFl) ) + cmUiSetNextWH( uiH, panelId, cmUiH(uiH,panelId), cmUiW(uiH,panelId) ); + } + + if((rc = _cmUiCreateCtl(p,&a,panelId,kMeterUiCId,id,label,flags,&c)) == kOkUiRC ) + { + cmUiRC_t rc0; + + _cmUiSetIntAccessors(c); + + a.dId = kSetValDId; + + a.flags = kMinUiFl; + a.ival = min; + if((rc0 = _cmUiCallDriver(p,&a)) != kOkUiRC ) + rc = rc0; + + a.flags = kMaxUiFl; + a.ival = max; + if((rc0 = _cmUiCallDriver(p,&a)) != kOkUiRC ) + rc = rc0; + + a.flags = kValUiFl; + a.ival = dflt; + if((rc0 = _cmUiCallDriver(p,&a)) != kOkUiRC ) + rc = rc0; + + } + return rc; +} + + +cmUiRC_t cmUiCreateHMeter( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, int min, int max, int dflt ) +{ + return _cmUiCreateMeter(uiH,panelId,id,label,flags | kHorzUiFl,min,max,dflt); +} + +cmUiRC_t cmUiCreateVMeter( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, int min, int max, int dflt ) +{ + return _cmUiCreateMeter(uiH,panelId,id,label,flags | kVertUiFl,min,max,dflt); +} + +cmUiRC_t cmUiCreateFileBtn(cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, const cmChar_t* dfltDir, const cmChar_t* patStr ) +{ + cmUiRC_t rc = kOkUiRC; + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiDriverArg_t a; + cmUiCtl_t* c; + + if(( rc = _cmUiCreateCtl(p,&a,panelId,kFilenameUiCId,id,label,flags,&c)) == kOkUiRC ) + { + cmUiRC_t rc0; + + _cmUiSetStrAccessors(c); + + if( dfltDir != NULL ) + { + a.dId = kSetValDId; + a.flags = kValUiFl; + a.sval = dfltDir; + if((rc0 = _cmUiCallDriver(p,&a)) != kOkUiRC ) + rc = rc0; + } + + if( patStr != NULL ) + { + a.dId = kSetValDId; + a.flags = kFnPatUiFl; + a.sval = patStr; + if((rc0 = _cmUiCallDriver(p,&a)) != kOkUiRC ) + rc = rc0; + } + } + return rc; +} + +cmUiRC_t cmUiCreateDirBtn( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, const cmChar_t* dfltDir ) +{ + cmUiRC_t rc = kOkUiRC; + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiDriverArg_t a; + cmUiCtl_t* c; + + if(( rc = _cmUiCreateCtl(p,&a,panelId,kDirUiCId,id,label,flags,&c)) == kOkUiRC ) + { + cmUiRC_t rc0; + + _cmUiSetStrAccessors(c); + + if( dfltDir != NULL ) + { + a.dId = kSetValDId; + a.flags = kValUiFl; + a.sval = dfltDir; + if((rc0 = _cmUiCallDriver(p,&a)) != kOkUiRC ) + rc = rc0; + } + } + return rc; +} + +cmUiRC_t cmUiCreateMenuBtn( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags ) +{ + cmUiRC_t rc; + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiDriverArg_t a; + cmUiCtl_t* c; + + if((rc = _cmUiCreateCtl(p,&a,panelId,kMenuBtnUiCId,id,label,flags,&c)) == kOkUiRC ) + _cmUiSetIntAccessors(c); + return rc; +} + +cmUiRC_t cmUiCreateMenuBtnV(cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, const cmChar_t* label0, unsigned id0, va_list vl ) +{ + cmUiRC_t rc = kOkUiRC; + // TODO: + return rc; +} + +cmUiRC_t cmUiCreateMenuBtnA(cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, const cmChar_t* label0, unsigned id0, ... ) +{ + va_list vl; + va_start(vl,id0); + cmUiRC_t rc = cmUiCreateMenuBtnV(uiH,panelId,id,label,flags,label0,id0,vl); + va_end(vl); + return rc; +} + +cmUiRC_t cmUiCreateMenuBtnJson(cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* lavel, unsigned flags, const cmJsonNode_t* root, const cmChar_t* memberLabel ) +{ + cmUiRC_t rc = kOkUiRC; + // TODO: + return rc; +} + +cmUiRC_t cmUiCreateList(cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, unsigned visibleRowCnt ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiRC_t rc; + cmUiDriverArg_t a; + cmUiCtl_t* c; + cmUiPanel_t* pp; + + if((rc = _cmUiFindPanel(p,panelId,&pp,true)) != kOkUiRC ) + return rc; + + if( cmIsNotFlag(pp->flags,kNextWHUiFl) ) + cmUiSetNextWH( uiH, panelId, cmUiNextW(uiH,panelId), cmUiH(uiH,panelId) * visibleRowCnt ); + + if((rc = _cmUiCreateCtl(p,&a,panelId,kListUiCId,id,label,flags,&c)) == kOkUiRC ) + _cmUiSetIntAccessors(c); + + return rc; +} + +cmUiRC_t cmUiCreateListV( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, unsigned visibleRowCnt, const cmChar_t* label0, unsigned id0, va_list vl ) +{ + cmUiRC_t rc = kOkUiRC; + // TODO: + return rc; +} + +cmUiRC_t cmUiCreateListA( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, unsigned visibleRowCnt, const cmChar_t* label0, unsigned id0, ... ) +{ + va_list vl; + va_start(vl,id0); + cmUiRC_t rc = cmUiCreateListV(uiH,panelId,id,label,flags,visibleRowCnt,label0,id0,vl); + va_end(vl); + return rc; +} + +cmUiRC_t cmUiCreateListJson( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, unsigned visibleRowCnt, const cmJsonNode_t* root, const cmChar_t* memberLabel ) +{ + cmUiRC_t rc = kOkUiRC; + // TODO: + return rc; +} + +cmUiRC_t cmUiAppendListEle( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* text, unsigned eleId ) +{ + cmUiRC_t rc = kOkUiRC; + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiCtl_t* ctl = NULL; + cmUiDriverArg_t a; + + if((rc = _cmUiFindCtl(p,id,&ctl,true)) != kOkUiRC ) + return rc; + + if( ctl->cId != kListUiCId && ctl->cId != kMenuBtnUiCId ) + return cmErrMsg(&p->err,kInvalidCtlOpUiRC,"List elements may only be set on 'list' and 'menu button' controls."); + + _cmUiDriverArgInit(&a, p, kSetValDId, ctl->cId, panelId, id ); + + + //if( ctl->id_arr == NULL || ctl->id_cnt == ctl->id_alloc ) + // ctl->id_arr = cmMemResizeZ(unsigned,ctl->id_arr,ctl->id_alloc+=10); + + //ctl->id_arr[ ctl->id_cnt++ ] = eleId; + + cmArrayPush(ctl->idArrH,&eleId,1); + + //a.dId = kSetValDId; + //a.cId = ctl->cId; + //a.panelId = panelId; + //a.usrId = id; + a.flags = kAppendUiFl; + a.sval = text; + a.ival = eleId; + + return _cmUiCallDriver(p,&a); +} + +cmUiRC_t cmUiDestroyCtl( cmUiH_t uiH, unsigned id ) +{ + cmUiRC_t rc = kOkUiRC; + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiCtl_t* ctl = NULL; + + if((rc = _cmUiFindCtl(p,id,&ctl,true)) == kOkUiRC ) + { + if( ctl->cId == kPanelUiCId ) + _cmUiDestroyPanel(p,ctl->usrId); + else + rc = _cmUiDestroyCtl(p,ctl); + } + return rc; +} + +bool cmUiCtlExists( cmUiH_t uiH, unsigned panelId, unsigned id ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + + if( panelId == id ) + { + cmUiPanel_t* pp=NULL; + return _cmUiFindPanel(p, panelId, &pp, false ) == kOkUiRC; + } + + cmUiCtl_t* ctl=NULL; + return _cmUiFindCtl(p,id,&ctl,false) == kOkUiRC; +} + +cmUiRC_t cmUiClearPanel( cmUiH_t uiH, unsigned panelId ) +{ + cmUiRC_t rc = kOkUiRC; + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp = NULL; + + // get the panel recd ptr + if((rc = _cmUiFindPanel(p,panelId,&pp,true)) != kOkUiRC ) + return rc; + + cmUiApp_t* ap = pp->appPtr; + cmUiCtl_t* ctl = NULL; + unsigned i = 0; + unsigned n = cmArrayCount(ap->ctlArrH); + cmUiRC_t rc0; + + // Destroy all controls that belong to this panel. + for(i=0; ipanelId == panelId && ctl->usrId != panelId) + if((rc0 = _cmUiDestroyCtl(p,ctl)) != kOkUiRC ) + rc = rc0; + + return rc; +} + +cmUiRC_t cmUiNextRect( cmUiH_t uiH, unsigned panelId, int x, int y, int w, int h ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + cmUiRC_t rc; + + if((rc = _cmUiFindPanel(p, panelId, &pp, true)) != kOkUiRC ) + return rc; + + pp->rect.x = x; + pp->rect.y = y; + pp->rect.w = w; + pp->rect.h = h; + pp->flags = cmSetFlag(pp->flags,kUseRectUiFl); + + return rc; +} + +bool cmUiFillRows( cmUiH_t uiH, unsigned panelId ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if( _cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return false; + + return cmIsFlag(pp->flags,kFillRowsUiFl); +} + +bool cmUiSetFillRows( cmUiH_t uiH, unsigned panelId, bool enableFl ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if( _cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return false; + + bool retFl = cmIsFlag(pp->flags,kFillRowsUiFl); + + pp->flags = cmEnaFlag(pp->flags,kFillRowsUiFl,enableFl); + + return retFl; +} + +int cmUiBaseCol( cmUiH_t uiH, unsigned panelId, int x ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if( _cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return -1; + + int bc = pp->baseCol; + pp->baseCol = x; + pp->flags = cmSetFlag(pp->flags,kPlaceBaseRowUiFl); + return bc; +} + +void cmUiPlaceRight( cmUiH_t uiH, unsigned panelId ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return; + + pp->flags = cmClrFlag(pp->flags,kPlaceBelowUiFl); + pp->flags = cmSetFlag(pp->flags,kPlaceRightUiFl); +} + +void cmUiPlaceBelow( cmUiH_t uiH, unsigned panelId ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return; + + pp->flags = cmClrFlag(pp->flags,kPlaceRightUiFl); + pp->flags = cmSetFlag(pp->flags,kPlaceBelowUiFl); +} + +int cmUiBaseRow( cmUiH_t uiH, unsigned panelId, int y ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + cmUiRC_t rc; + + if((rc = _cmUiFindPanel(p, panelId, &pp, true)) != kOkUiRC ) + return -1; + + int br = pp->baseRow; + pp->baseRow = y; + return br; +} + +int cmUiW( cmUiH_t uiH, unsigned panelId ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return -1; + + return pp->dfltW; +} + +int cmUiH( cmUiH_t uiH, unsigned panelId ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return -1; + + return pp->dfltH; +} + +void cmUiSetWH( cmUiH_t uiH, unsigned panelId, int w, int h ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return; + + pp->dfltW = w; + pp->dfltH = h; +} + +int cmUiNextW( cmUiH_t uiH, unsigned panelId ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return -1; + + return pp->nextW; +} + +int cmUiNextH( cmUiH_t uiH, unsigned panelId ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return -1; + + return pp->nextH; +} + +void cmUiSetNextWH( cmUiH_t uiH, unsigned panelId, int w, int h ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return; + + pp->nextW = w; + pp->nextH = h; + pp->flags = cmSetFlag(pp->flags,kNextWHUiFl); +} + +int cmUiHBorder( cmUiH_t uiH, unsigned panelId ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return -1; + + return pp->dfltHBorder; +} + +int cmUiVBorder( cmUiH_t uiH, unsigned panelId ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return -1; + + return pp->dfltVBorder; +} + +int cmUiSetHBorder( cmUiH_t uiH, unsigned panelId, int w ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return -1; + + int rv = pp->dfltHBorder; + pp->dfltHBorder = w; + return rv; +} + +int cmUiSetVBorder( cmUiH_t uiH, unsigned panelId, int h ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return -1; + + int rv = pp->dfltVBorder; + pp->dfltVBorder = h; + return rv; +} + +int cmUiNextHBorder( cmUiH_t uiH, unsigned panelId ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return -1; + + return pp->nextHBorder; +} + +int cmUiNextVBorder( cmUiH_t uiH, unsigned panelId ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return -1; + + return pp->nextVBorder; +} + +int cmUiSetNextHBorder( cmUiH_t uiH, unsigned panelId, int w ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return -1; + + int rv = pp->nextHBorder; + pp->nextHBorder = w; + return rv; +} + +int cmUiSetNextVBorder( cmUiH_t uiH, unsigned panelId, int h ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiPanel_t* pp; + + if(_cmUiFindPanel(p, panelId, &pp, true) != kOkUiRC ) + return -1; + + int rv = pp->nextVBorder; + pp->nextVBorder = h; + return rv; +} + + +cmUiRC_t cmUiSetInt( cmUiH_t uiH, unsigned id, int v ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiCtl_t* ctl; + cmUiRC_t rc; + cmUiDriverArg_t a; + + if((rc = _cmUiFastFindCtl(p,id,&ctl,true)) != kOkUiRC ) + return rc; + + // TODO: cache the cmUiDriverArg_t for this control in the ctl_t + // object to avoid having to recreate the arg. recd on every call. + _cmUiDriverArgInit(&a, p, kSetValDId, ctl->cId, ctl->panelId, id ); + + a.ival = v; + a.flags |= kValUiFl; + + return _cmUiCallDriver(p,&a); + +} + +cmUiRC_t cmUiSetUInt( cmUiH_t uiH, unsigned id, unsigned v ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiCtl_t* ctl; + cmUiRC_t rc; + cmUiDriverArg_t a; + + if((rc = _cmUiFastFindCtl(p,id,&ctl,true)) != kOkUiRC ) + return rc; + + _cmUiDriverArgInit(&a, p, kSetValDId, ctl->cId, ctl->panelId, id ); + + a.ival = (int)v; + a.flags |= kValUiFl; + + return _cmUiCallDriver(p,&a); +} + +cmUiRC_t cmUiSetDouble( cmUiH_t uiH, unsigned id, double v ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiCtl_t* ctl; + cmUiRC_t rc; + cmUiDriverArg_t a; + + if((rc = _cmUiFastFindCtl(p,id,&ctl,true)) != kOkUiRC ) + return rc; + + _cmUiDriverArgInit(&a, p, kSetValDId, ctl->cId, ctl->panelId, id ); + + a.fval = v; + a.flags |= kValUiFl; + + return _cmUiCallDriver(p,&a); +} + +cmUiRC_t cmUiSetString( cmUiH_t uiH, unsigned id, const cmChar_t* v ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiCtl_t* ctl; + cmUiRC_t rc; + cmUiDriverArg_t a; + + if((rc = _cmUiFastFindCtl(p,id,&ctl,true)) != kOkUiRC ) + return rc; + + _cmUiDriverArgInit(&a, p, kSetValDId, ctl->cId, ctl->panelId, id ); + + a.sval = v; + a.flags |= kValUiFl; + + return _cmUiCallDriver(p,&a); +} + +int cmUiInt( cmUiH_t uiH, unsigned id ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiCtl_t* ctl; + cmUiRC_t rc; + + if((rc = _cmUiFastFindCtl(p,id,&ctl,true)) != kOkUiRC ) + return 0; + + return ctl->getInt(ctl); +} + +unsigned cmUiUInt( cmUiH_t uiH, unsigned id ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiCtl_t* ctl; + cmUiRC_t rc; + + if((rc = _cmUiFastFindCtl(p,id,&ctl,true)) != kOkUiRC ) + return 0; + + return ctl->getInt(ctl); +} + +double cmUiDouble( cmUiH_t uiH, unsigned id ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiCtl_t* ctl; + cmUiRC_t rc; + + if((rc = _cmUiFastFindCtl(p,id,&ctl,true)) != kOkUiRC ) + return 0; + + return ctl->getDbl(ctl); +} + +const cmChar_t* cmUiString( cmUiH_t uiH, unsigned id ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + cmUiCtl_t* ctl; + cmUiRC_t rc; + + if((rc = _cmUiFastFindCtl(p,id,&ctl,true)) != kOkUiRC ) + return 0; + + return ctl->getStr(ctl); +} + + +cmUiRC_t cmUiLastRC( cmUiH_t uiH ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + return cmErrLastRC(&p->err); +} + +cmUiRC_t cmUiSetRC( cmUiH_t uiH, cmUiRC_t rc ) +{ + cmUi_t* p = _cmUiHandleToPtr(uiH); + return cmErrSetRC(&p->err, rc); +} + diff --git a/cmUi.h b/cmUi.h new file mode 100644 index 0000000..5a88ec2 --- /dev/null +++ b/cmUi.h @@ -0,0 +1,346 @@ +#ifndef cmUi_h +#define cmUi_h + +#ifdef __cplusplus +extern "C" { +#endif + /* + cmUI implements a platform independent UI control manager + for multiple simultaneous applications. In this context + an 'application' can be seen as a plug-in style program. + + The goal of the manager is to support the easy construction + of panels of graphic user interface controls. + + + + Operation: + + 1) A cmUi manager is allocated by the master program. See cmUiAlloc(). + + 2) The master program then assigns a 'driver' to implmenent + the commands issued by cmUi. All commands can be + described using the cmUiDriverArg_t record. + + 3) The master program then registers client applications with + the cmUi manager by calling cmUiCreateApp(). + + 4) Prior to calling any of the client application functions + the master or client app. must call cmUiSetAppId(). This + function sets the current application id and thereby slightly + simplifies the client app interface by not requiring the + app id be passed with every client app. function call. + + 5) Once the current app. id is set with cmUiSetAppId() + the client app can make multiple calls to the cmUi manager + to create or query controls. + + 6) Calls to create controls result in callbacks to the + driver function which manages the actual windowing and + initial event handling. + + 7) Events generated by the driver based graphic controls + are routed back to the cmUi manager through calls to + cmUiOnDriverEvent(). + + 8) The cmUiOnDriverEvent() internally caches the + state/value of the control based on the event information + and calls the 'cbFunc' function registered with the + cmUi manager by cmUiAlloc(). This call is intended to + notify the client applications of changes in the state/value + of a user interface control. + + Notes: + 1) Application id's must be unique among all applications. + Control id's must be unique among all controls assigned + to the same application. Both application and control id's + are used internally as array indexes they should therefore + be the low, positive, and densely packed integers. + + 2) All communication between the cmUi and the driver, + and all callbacks from the cmUi to the master app. + use the cmUiDriverArg_t structure + + TODO: + 0) Remove the 'cbArg' from the cmUiDriverArg_t record and + pass it as a separate paramenter in the cmUiDriverFunc_t calls. + + 1) The controls should be based on a multilevel tree model + not the simple two layer panel->controls framework used now. + + 2) Given that access to the control values can be non-blocked + and fast many controls won't need to report changes back to + the client - the client can simply read the control value + as necessary directly from the cmUi manager. To decrease + event processing overhead controls should therefore be + flagged as 'callback/no-callback'. Some controls like + buttons should default to turning the flag on, while other + controls, like numbers, should default to turning it off. + + 3) Implement support for the creation of arrays of controls. + This can be implemented with a scheme similar to 'next rect'. + cmUiSetupArray(uiH,panelId,baseCtlId,cnt). + + 4) Come up with a threading model. For example maybe + control creation should use a blocking scheme since it is + generally to time consuming to do during real-time operation + anyway. If the control flow generated from driver event + callbacks then allows value, but not structural changes, + then non blocking will be necessary. + + 5) The cmUiDriverArg_t structure is used for both + commands to the driver and callbacks from the driver. + Many of the fields are not use for event callbacks. + Which fields are used under which circumstances should + be documented. This would allow decreasing the size + of the record during serialization.7 + + 6) Write a serialization/deserialization routines for cmUiDriverArg_t. + unsigned cmUiDriverArgSerialBufByteCount(const cmUiDriverArg_t* a); + cmUiRC_t cmUiDriverArgSerialize( const cmUiDriverArg_t* a, char* buf, bufByteCnt ); + cmUiRC_t cmUiDriverArgDeserialize( cmUiDriverArg_t* a, const char* buf, bufByteCnt ); + + 7) There is no duplex model for validating and then displaying the + value of a control. + + */ + + typedef cmHandle_t cmUiH_t; + + + extern cmUiH_t cmUiNullHandle; + + //============================================================================================= + // + // Master program API + // + + // Allocate the cmUi manager. If the driver function is not + // yet available then set drvrFunc to NULL and use + // cmUiSetDriver() to set the driver function at a later + // time. cmUiAlloc() stores but does not call the driver + // and so it is not needed when the cmUI manager is + // constructed - however it must be set prior to making + // any other calls to the manager. + cmUiRC_t cmUiAlloc( + cmCtx_t* ctx, + cmUiH_t* hp, + cmUiDriverFunc_t drvrFunc, // UI driver function + void* drvrArg, + cmUiDriverFunc_t cbFunc, // client event callback function + void* cbArg ); + + // Release all apps but assume that the driver has already + // been released. + cmUiRC_t cmUiFree( cmUiH_t* hp ); + + // Validate the cmUiH_t handle. + bool cmUiIsValid( cmUiH_t h ); + + // Set the driver function. This function allows the driver + // set in cmUiAlloc() to be replaced or set following the + // call to cmUiAlloc(). + // + // By setting the driver function to + // NULL the application can prevent callback to the driver. + // This is useful if the driver has been release prior + // to the UI manager begining destroyed. + void cmUiSetDriver( cmUiH_t h, cmUiDriverFunc_t drvrFunc, void* drvrArg ); + + // Register a client application with the cmUi manager. + // 'appId' must not have been used by any other previously registered. + // application. + // Automatically sets and restores the ambient appId. + // In a plug-in context this function is generally called + // just prior a instantiating a plug-in object. + cmUiRC_t cmUiCreateApp( cmUiH_t uiH, unsigned appId ); + + // Notify the cmUi manager that the resources associated + // with a client application can be released. + // Automatically sets and restores the ambient appId. + cmUiRC_t cmUiDestroyApp( cmUiH_t uiH, unsigned appId ); + + // Release all apps. + // Automatically sets and restores the ambient appId. + cmUiRC_t cmUiDestroyAllApps( cmUiH_t h ); + + + // The master program sets the ambient 'appId' prior to passing control + // to a client which will make User API calls. By making the + // 'appId' an ambient parameter the User API calls are slightly + // simplified because they do not have to include it in each of the + // function calls. + cmUiRC_t cmUiSetAppId( cmUiH_t uiH, unsigned appId ); + + // Return the count of app's. + unsigned cmUiAppCount( cmUiH_t uiH ); + + + // Callbacks from the driver arrive via this function. + cmUiRC_t cmUiOnDriverEvent( cmUiH_t uiH, const cmUiDriverArg_t* p ); + + + //============================================================================================= + // + // Client Application API + // + + + cmUiRC_t cmUiCreatePanel( cmUiH_t uiH, unsigned newPanelId, const cmChar_t* label ); + + cmUiRC_t cmUiCreateBtn( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags ); + cmUiRC_t cmUiCreateCheck( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, bool dflt ); + cmUiRC_t cmUiCreateLabel( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags ); + cmUiRC_t cmUiCreateText( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, const cmChar_t* text ); + cmUiRC_t cmUiCreateNumber( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, double min, double max, double incr, double dflt ); + cmUiRC_t cmUiCreateHSlider( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, double min, double max, double incr, double dflt ); + cmUiRC_t cmUiCreateVSlider( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, double min, double max, double incr, double dflt ); + cmUiRC_t cmUiCreateProgress( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, int min, int max, int dflt ); + cmUiRC_t cmUiCreateHMeter( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, int min, int max, int dflt ); + cmUiRC_t cmUiCreateVMeter( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, int min, int max, int dflt ); + cmUiRC_t cmUiCreateFileBtn( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, const cmChar_t* dfltDir, const cmChar_t* patStr ); + cmUiRC_t cmUiCreateDirBtn( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, const cmChar_t* dfltDir ); + cmUiRC_t cmUiCreateMenuBtn( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags ); + cmUiRC_t cmUiCreateMenuBtnV( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* lavel, unsigned flags, const cmChar_t* label0, unsigned id0, va_list vl ); + cmUiRC_t cmUiCreateMenuBtnA( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* lavel, unsigned flags, const cmChar_t* label0, unsigned id0, ... ); + cmUiRC_t cmUiCreateMenuBtnJson( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* lavel, unsigned flags, const cmJsonNode_t* root, const cmChar_t* memberLabel ); + cmUiRC_t cmUiCreateList( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, unsigned visibleRowCnt ); + cmUiRC_t cmUiCreateListV( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, unsigned visibleRowCnt, const cmChar_t* label0, unsigned id0, va_list vl ); + cmUiRC_t cmUiCreateListA( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, unsigned visibleRowCnt, const cmChar_t* label0, unsigned id0, ... ); + cmUiRC_t cmUiCreateListJson( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* label, unsigned flags, unsigned visibleRowCnt, const cmJsonNode_t* root, const cmChar_t* memberLabel ); + + // If 'id' identifies a 'list' control use tabs as column separators. + cmUiRC_t cmUiAppendListEle( cmUiH_t uiH, unsigned panelId, unsigned id, const cmChar_t* text, unsigned eleId ); + + // If 'id' identifies a panel then all control belonging to the panel + // will also be destroyed. + cmUiRC_t cmUiDestroyCtl( cmUiH_t uiH, unsigned id ); + + // Returns true if the control exists. + // For panels set id=panelId. + bool cmUiCtlExists( cmUiH_t uiH, unsigned panelId, unsigned id ); + + // Destroy all the controls in a panel. + cmUiRC_t cmUiClearPanel( cmUiH_t uiH, unsigned panelId ); + + + // Location: + // 1) If a 'next rect' is set the control will be placed according to it. + // 2) If cmUiSetBaseCol() was set then the control will be placed at the + // base col and base row. + // 3) If cmUiPlaceRight() or cmUIPlaceBelow() have been called since the + // previous control was created then the new control will be placed + // accordingly. + // 4) The control will be placed according to the 'fill rows' flag. + // If not set (default) the new control will be placed in the + // base column below the previous control. + // If 'fill rows' is set the new control will be placed on the + // same row to the right of the previous control. + // If there is no previous control then it will be placed + // in the base column and base row. + + // Get/Set the fill directions. If the 'fill columns' flag is enabled + // then the next control is placed below the previous control otherwise + // the next control is placed to the right of the next control. + bool cmUiFillRows( cmUiH_t uiH, unsigned panelId ); + bool cmUiSetFillRows( cmUiH_t uiH, unsigned panelId, bool enableFl ); + + + // Place the next control to the right/below of the previous ctl. + // These flags override the current fill row/col setting. + // Note that 'place right' and 'place below' are mutually + // exclusive. Enabling one disables the other. + void cmUiPlaceRight( cmUiH_t uiH, unsigned panelId ); + void cmUiPlaceBelow( cmUiH_t uiH, unsigned panelId ); + + // Set current base col and return previous value. Place the next + // control on the base row. + int cmUiBaseCol( cmUiH_t uiH, unsigned panelId, int x ); + + + // Set current base row and return previous value. + int cmUiBaseRow( cmUiH_t uiH, unsigned panelId, int y ); + + // Size: + // 1) If a 'next rect' is set the control will be placed according + // to it. + // 2) If a 'next w/h' is set the control will be placed according + // to it. The 'next w/h' setting is only active for the + // next control created. + // 3) The w/h of the new control will be set to the default w/h. + // + + // Get/Set the default control width and height. + // Set returns previous value. + int cmUiW( cmUiH_t uiH, unsigned panelId ); + int cmUiH( cmUiH_t uiH, unsigned panelId ); + void cmUiSetWH( cmUiH_t uiH, unsigned panelId, int w, int h ); + + // Get/Set the control width and height for only the next control. + // Set returns previous value. + int cmUiNextW( cmUiH_t uiH, unsigned panelId ); + int cmUiNextH( cmUiH_t uiH, unsigned panelId ); + void cmUiSetNextWH( cmUiH_t uiH, unsigned panelId, int w, int h ); + + // Get/Set the default inter-control borders + // Set returns previous value. + int cmUiHBorder( cmUiH_t uiH, unsigned panelId ); + int cmUiVBorder( cmUiH_t uiH, unsigned panelId ); + int cmUiSetHBorder( cmUiH_t uiH, unsigned panelId, int w ); + int cmUiSetVBorder( cmUiH_t uiH, unsigned panelId, int h ); + + // Get/Set the 'next' inter-control borders + // Set returns previous value. + int cmUiNextHBorder( cmUiH_t uiH, unsigned panelId ); + int cmUiNextVBorder( cmUiH_t uiH, unsigned panelId ); + int cmUiSetNextHBorder( cmUiH_t uiH, unsigned panelId, int w ); + int cmUiSetNextVBorder( cmUiH_t uiH, unsigned panelId, int h ); + + // Place the next control at the following coordinates. The + // specified coordinates are only active during the next + // cmUiCreateXXX() call. Setting the 'next rect' overrides all + // other layout directives. + cmUiRC_t cmUiNextRect( cmUiH_t uiH, unsigned panelId, int x, int y, int w, int h ); + + + // + // Get/set the value of UI control. + // + + // TODO: + // 1) Still need functions for setting auxilliary values like + // min,max,etc.. + // 2) A coherent model needs to be selected for determining + // how local values get set. As it is local values are + // only set via callbacs from the UI driver. + + // Set the value associated with a control. + // These functions would be better named 'cmUiSendXXX()' since + // they don't actually set the local value but rather call the + // driver to set the UI value. The driver may then respond with + // a callback which will set the local value. One advantage of + // this is that the value will be filtered according to the + // ui's rules (e.g. min, max .... ) + cmUiRC_t cmUiSetInt( cmUiH_t uiH, unsigned id, int v ); + cmUiRC_t cmUiSetUInt( cmUiH_t uiH, unsigned id, unsigned v ); + cmUiRC_t cmUiSetDouble( cmUiH_t uiH, unsigned id, double v ); + cmUiRC_t cmUiSetString( cmUiH_t uiH, unsigned id, const cmChar_t* v ); + + // Get the value associated with a control. These functions return + // the control value cached in the local control, they do not need + // to call the driver and are therefore very fast. + int cmUiInt( cmUiH_t uiH, unsigned id ); + unsigned cmUiUInt( cmUiH_t uiH, unsigned id ); + double cmUiDouble( cmUiH_t uiH, unsigned id ); + const cmChar_t* cmUiString( cmUiH_t uiH, unsigned id ); + + // Query/set the current error state. + cmUiRC_t cmUiLastRC( cmUiH_t uiH ); + cmUiRC_t cmUiSetRC( cmUiH_t uiH, cmUiRC_t rc ); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/cmUiDrvr.h b/cmUiDrvr.h new file mode 100644 index 0000000..c2064e3 --- /dev/null +++ b/cmUiDrvr.h @@ -0,0 +1,114 @@ +#ifndef cmUiDrvr_h +#define cmUiDrvr_h + +#ifdef __cplusplus +extern "C" { +#endif + + typedef unsigned cmUiRC_t; + + enum + { + kOkUiRC = cmOkRC, + kAppNotFoundUiRC, + kCtlNotFoundUiRC, + kPanelNotFoundUiRC, + kPanelFullUiRC, + kDrvrErrUiRC, + kInvalidCtlOpUiRC, + kInvalidColRowUiRC, + kInvalidIdUiRC, + }; + + + typedef enum + { + kInvalidUiCId, + kPanelUiCId, + kBtnUiCId, + kCheckUiCId, + kMenuBtnUiCId, + kListUiCId, + kLabelUiCId, + kTextUiCId, + kNumberUiCId, + kSliderUiCId, + kProgressUiCId, + kMeterUiCId, + kFilenameUiCId, + kDirUiCId, + } cmUiCId_t; + + typedef enum + { + kInvalidDId, + kCreateCtlDId, + kDestroyCtlDId, + kSetValDId, + kDestroyAllDId + } cmUiDId_t; + + enum + { + // All controls recognize kValUiFl and kLblUiFl + kValUiFl = 0x000001, + kLblUiFl = 0x000002, + + // Flags for Number,Progress,Meter + kMinUiFl = 0x00004, + kMaxUiFl = 0x00010, + kIncUiFl = 0x00020, + kNumMask = kValUiFl | kMinUiFl | kMaxUiFl | kIncUiFl, + kHorzUiFl = 0x00040, + kVertUiFl = 0x00080, + + // Flags for Filename and Dir + kFnPatUiFl = 0x00100, // file pattern string + kFnDirUiFl = 0x00200, // toggle file btn type + kFnMask = kFnPatUiFl | kFnDirUiFl, + + // Append list or menu element. + kAppendUiFl = 0x00400, + + kLeftUiFl = 0x01000, + kTopUiFl = 0x02000, + kRightUiFl = 0x04000, + kBottomUiFl = 0x08000, + kHCtrUiFl = 0x10000, + kVCtrUiFl = 0x20000, + kInsideUiFl = 0x40000, + + }; + + + // A control can be uniquely idenfied by + // appId and usrId (appId's are unique among app's) + // (usrId's are unique among ctl's on an app) + // appId's and usrId's should be zero based low numbers + // because they are used internally as indexes. + typedef struct + { + void* cbArg; // + cmUiDId_t dId; // function selector id + unsigned appId; // app id (plug-in instance id) + unsigned usrId; // ctl id + unsigned panelId; // parent panel id + cmUiCId_t cId; // UI control type + unsigned flags; // See kXXXUiFl above. + int x; + int y; + int w; + int h; + int ival; + double fval; + const char* sval; + } cmUiDriverArg_t; + + typedef cmUiRC_t (*cmUiDriverFunc_t)( const cmUiDriverArg_t* a ); + +#ifdef __cplusplus +} +#endif + + +#endif