diff --git a/cwUi.cpp b/cwUi.cpp index 85465ff..d5be4fa 100644 --- a/cwUi.cpp +++ b/cwUi.cpp @@ -34,6 +34,9 @@ namespace cw unsigned uuId; // UI unique id - automatically generated and unique among all elements that are part of this ui_t object. unsigned appId; // application assigned id - application assigned id char* eleName; // javascript id + + object_t* attr; + } ele_t; typedef struct ui_str @@ -50,7 +53,7 @@ namespace cw char* buf; // buf[bufN] output message formatting buffer unsigned bufN; // - unsigned* sessA; + unsigned* sessA; // sessA[ sessN ] array of wsSessId's unsigned sessN; unsigned sessAllocN; @@ -252,9 +255,10 @@ namespace cw return rc; } - - - ele_t* _createEle( ui_t* p, ele_t* parent, unsigned appId, const char* eleName ) + + // Create the base element record. The attributes mut be filled in by the calling function. + // Note that if 'appId' is kInvalidId then this function will attempt to lookup the appId in p->appIdMap[]. + ele_t* _createBaseEle( ui_t* p, ele_t* parent, unsigned appId, const char* eleName, const char* eleTypeStr=nullptr, const char* eleClass=nullptr, const char* eleTitle=nullptr ) { ele_t* e = mem::allocZ(); @@ -269,8 +273,19 @@ namespace cw e->parent = parent; e->uuId = p->eleN; e->appId = appId; - e->eleName = eleName==nullptr ? nullptr : mem::duplStr(eleName); + e->eleName = eleName==nullptr ? nullptr : mem::duplStr(eleName); + e->attr = newObjectDict(); + + if( eleTypeStr != nullptr ) + e->attr->insertPair("type",eleTypeStr); + + if( eleClass != nullptr ) + e->attr->insertPair("class",eleClass); + if( eleTitle != nullptr ) + e->attr->insertPair("title",eleTitle); + + if( p->eleN == p->eleAllocN ) { p->eleAllocN += 100; @@ -306,6 +321,7 @@ namespace cw return e; } + ele_t* _findOrCreateEle( ui_t* p, ele_t* parentEle, const char* eleName, unsigned appId=kInvalidId ) { ele_t* ele = nullptr; @@ -323,7 +339,7 @@ namespace cw } if(ele == nullptr ) - ele = _createEle(p, parentEle, appId, eleName ); + ele = _createBaseEle(p, parentEle, appId, eleName ); return ele; } @@ -361,6 +377,48 @@ namespace cw return format_attributes(buf,n,i,std::forward(args)...); } + + + // terminating condition for format_attributes() + void create_attributes( ele_t* e ) + { } + + template + void create_attributes(ele_t* e, const char* label, T value, ARGS&&... args) + { + e->attr->insertPair(label,value); + + create_attributes(e,std::forward(args)...); + } + + + template< typename... ARGS> + rc_t _createOneEle1( ui_t* p, unsigned& uuIdRef, const char* eleTypeStr, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, ARGS&&... args ) + { + rc_t rc = kOkRC; + ele_t* newEle = nullptr; + ele_t* parentEle = nullptr; + + uuIdRef = kInvalidId; + + if( parentUuId == kInvalidId ) + parentUuId = kRootUuId; + + // get the parent element + if(( parentEle = _uuIdToEle(p, parentUuId )) == nullptr ) + return cwLogError( kInvalidArgRC, "Unable to locate the parent element (id:%i).", parentUuId ); + + // create the base element + newEle = _createBaseEle(p, parentEle, appId, eleName, eleTypeStr, clas, title ); + + // create the attributes + create_attributes(newEle, std::forward(args)...); + + uuIdRef = newEle->uuId; + + return rc; + } + template< typename... ARGS> rc_t _createOneEle( ui_t* p, unsigned& uuIdRef, const char* eleTypeStr, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, ARGS&&... args ) @@ -408,7 +466,6 @@ namespace cw return rc; } - rc_t _createElementsFromChildList( ui_t* p, const object_t* po, unsigned wsSessId, ele_t* parentEle ); // @@ -798,7 +855,7 @@ cw::rc_t cw::ui::create( p->uiRsrc = uiRsrc == nullptr ? nullptr : uiRsrc->duplicate(); // create the root element - if((ele = _createEle(p, nullptr, kRootAppId, "uiDivId" )) == nullptr || ele->uuId != kRootUuId ) + if((ele = _createBaseEle(p, nullptr, kRootAppId, "uiDivId" )) == nullptr || ele->uuId != kRootUuId ) { cwLogError(kOpFailRC,"The UI root element creation failed."); goto errLabel; @@ -1015,18 +1072,29 @@ unsigned cw::ui::findElementAppId( handle_t h, unsigned uuId ) cw::rc_t cw::ui::createFromObject( handle_t h, const object_t* o, unsigned wsSessId, unsigned parentUuId, const char* eleName ) { - ui_t* p = _handleToPtr(h); - rc_t rc = kOkRC; - + ui_t* p = _handleToPtr(h); + rc_t rc = kOkRC; + + //ele_t* parentEle = nullptr; + if( eleName != nullptr ) if((o = o->find(eleName)) == nullptr ) { rc = cwLogError(kSyntaxErrorRC,"Unable to locate the '%s' sub-configuration.",cwStringNullGuard(eleName)); goto errLabel; } + + //if((parentEle = _uuIdToEle(p, parentUuId)) == nullptr ) + //{ + // rc = cwLogError(kInvalidIdRC,"Unable to locate the parent element."); + // goto errLabel; + // } + //if((rc = _createElementsFromChildList( p, o, wsSessId, parentEle )) != kOkRC ) + // goto errLabel; + - if((rc = _createFromObj( p, o, wsSessId, parentUuId )) != kOkRC ) + if((rc = _createFromObj( p, o, wsSessId, parentUuId )) != kOkRC ) goto errLabel; errLabel: @@ -1131,6 +1199,10 @@ cw::rc_t cw::ui::createProg( handle_t h, unsigned& uuIdRef, unsigned wsSessId, cw::rc_t cw::ui::createLog( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title ) { return _createOneEle( _handleToPtr(h), uuIdRef, "log", wsSessId, parentUuId, eleName, appId, clas, title); } +cw::rc_t cw::ui::createList( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title ) +{ return _createOneEle( _handleToPtr(h), uuIdRef, "list", wsSessId, parentUuId, eleName, appId, clas, title); } + + cw::rc_t cw::ui::setNumbRange( handle_t h, unsigned wsSessId, unsigned uuId, double minValue, double maxValue, double stepValue, unsigned decPl, double value ) { rc_t rc = kOkRC; @@ -1264,6 +1336,25 @@ cw::rc_t cw::ui::sendValueString( handle_t h, unsigned wsSessId, unsigned uuId, return _sendValue(p,wsSessId,uuId,"\"%s\"",value,strlen(value)+10); } +void cw::ui::report( handle_t h ) +{ + ui_t* p = _handleToPtr(h); + + for(unsigned i=0; ieleN; ++i) + { + const ele_t* e = p->eleA[i]; + + unsigned parUuId = e->parent==NULL ? kInvalidId : e->parent->uuId; + unsigned parAppId = e->parent==NULL ? kInvalidId : e->parent->appId; + const char* parEleName = e->parent==NULL || e->parent->eleName == NULL ? "" : e->parent->eleName; + + printf("uu:%5i app:%5i %20s : parent uu:%5i app:%5i %20s\n", e->uuId, e->appId, e->eleName == NULL ? "" : e->eleName, parUuId, parAppId, parEleName ); + } + +} + + + namespace cw { namespace ui @@ -1513,7 +1604,6 @@ cw::ui::handle_t cw::ui::ws::uiHandle( handle_t h ) } - namespace cw { diff --git a/cwUi.h b/cwUi.h index 5429a17..498c972 100644 --- a/cwUi.h +++ b/cwUi.h @@ -32,11 +32,16 @@ namespace cw rc_t destroy( handle_t& h ); - unsigned sessionIdCount(handle_t h); - const unsigned* sessionIdArray(handle_t h); + unsigned sessionIdCount(handle_t h); // Count of connected remote UI's + const unsigned* sessionIdArray(handle_t h); // Array of 'sessionIdCount()' remote UI id's + // A new remote UI was connected rc_t onConnect( handle_t h, unsigned wsSessId ); + + // A UI was disconnected rc_t onDisconnect( handle_t h, unsigned wsSessId ); + + // Receive a msg from a remote UI rc_t onReceive( handle_t h, unsigned wsSessId, const void* msg, unsigned byteN ); unsigned findElementAppId( handle_t h, unsigned parentUuId, const char* eleName ); @@ -102,6 +107,7 @@ namespace cw rc_t createProg( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, double minValue, double maxValue ); rc_t createProg( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, double minValue, double maxValue, double value ); rc_t createLog( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title ); + rc_t createList( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title ); rc_t setNumbRange( handle_t h, unsigned wsSessId, unsigned uuId, double minValue, double maxValue, double stepValue, unsigned decPl, double value ); rc_t setProgRange( handle_t h, unsigned wsSessId, unsigned uuId, double minValue, double maxValue, double value ); @@ -119,6 +125,8 @@ namespace cw rc_t sendValueDouble( handle_t h, unsigned wsSessId, unsigned uuId, double value ); rc_t sendValueString( handle_t h, unsigned wsSessId, unsigned uuId, const char* value ); + void report( handle_t h ); + namespace ws @@ -177,9 +185,6 @@ namespace cw websock::handle_t websockHandle( handle_t h ); ui::handle_t uiHandle( handle_t h ); - - - } namespace srv diff --git a/cwUiTest.cpp b/cwUiTest.cpp index 0a80e3e..ab32160 100644 --- a/cwUiTest.cpp +++ b/cwUiTest.cpp @@ -35,6 +35,8 @@ namespace cw unsigned myPanelUuId; unsigned logUuId; + + const object_t* listEleCfg; } ui_test_t; @@ -43,7 +45,6 @@ namespace cw { // Programatically created UI elements kDivId, - kBtnId, kCheckId, kSelectId, kOption0Id, @@ -57,6 +58,7 @@ namespace cw kLogId, // Resource Based elements + kQuitBtnId, kPanelDivId, kPanelBtn1Id, kPanelCheck1Id, @@ -66,7 +68,8 @@ namespace cw kSelId, kOpt1Id, kOpt2Id, - kOpt3Id + kOpt3Id, + kListId }; rc_t _uiTestCreateUi( ui_test_t* p, unsigned wsSessId ) @@ -83,9 +86,6 @@ namespace cw if((rc = createDiv( uiH, p->myPanelUuId, wsSessId, kInvalidId, "myDivId", kDivId, "divClass", "My Panel" )) != kOkRC ) goto errLabel; - if((rc = createButton( uiH, uuid, wsSessId, p->myPanelUuId, "myBtnId", kBtnId, "btnClass", "Quit" )) != kOkRC ) - goto errLabel; - if((rc = createCheck( uiH, uuid, wsSessId, p->myPanelUuId, "myCheckId", kCheckId, "checkClass", "Check Me", true )) != kOkRC ) goto errLabel; @@ -117,9 +117,6 @@ namespace cw if((rc = createLog( uiH, p->logUuId, wsSessId, p->myPanelUuId, "myLogId", kLogId, "logClass", "My Log (click toggles auto-scroll)" )) != kOkRC ) goto errLabel; - //if((rc = createFromFile( uiH, p->uiCfgFn, wsSessId )) != kOkRC ) - // goto errLabel; - errLabel: return rc; } @@ -140,26 +137,36 @@ namespace cw } - rc_t _insert_log_line( ui_test_t* p, unsigned wsSessId, const char* text ) + rc_t _insert_list_ele( ui_test_t* p, unsigned wsSessId ) { - - rc_t rc = kOkRC; - - handle_t uiH = srv::uiHandle(p->wsUiSrvH); + rc_t rc = kOkRC; - //rc = ui::sendValueString( uiH, wsSessId, p->logUuId, text ); - rc = ui::setLogLine( uiH, wsSessId, p->logUuId, text ); + if( p->listEleCfg != nullptr ) + { + handle_t uiH = srv::uiHandle(p->wsUiSrvH); + unsigned listUuId = findElementUuId( uiH, kListId ); + printf("list uuid:%i\n",listUuId); + + rc = createFromObject( uiH, p->listEleCfg, wsSessId, listUuId ); + } + return rc; } + + rc_t _insert_log_line( ui_test_t* p, unsigned wsSessId, const char* text ) + { + return ui::setLogLine( srv::uiHandle(p->wsUiSrvH), wsSessId, p->logUuId, text ); + } + rc_t _handleUiValueMsg( ui_test_t* p, unsigned wsSessId, unsigned parentAppId, unsigned uuId, unsigned appId, const value_t* v ) { rc_t rc = kOkRC; switch( appId ) { - case kBtnId: + case kQuitBtnId: p->quitFl.store(true); break; @@ -205,6 +212,8 @@ namespace cw case kPanelCheck1Id: printf("check 1: %i\n",v->u.b); p->appCheck1Fl = v->u.b; + ui::report( srv::uiHandle(p->wsUiSrvH) ); + break; case kPanelBtn2Id: @@ -215,6 +224,7 @@ namespace cw case kPanelCheck2Id: printf("check 1: %i\n",v->u.b); p->appCheck1Fl = v->u.b; + _insert_list_ele( p, wsSessId ); break; case kPanelFloaterId: @@ -298,7 +308,7 @@ namespace cw break; case kInitOpId: - _uiTestCreateUi(p,wsSessId); + //_uiTestCreateUi(p,wsSessId); break; case kValueOpId: @@ -328,6 +338,7 @@ cw::rc_t cw::ui::test( const object_t* cfg ) // Application Id's for the resource based UI elements. appIdMap_t mapA[] = { + { kRootAppId, kQuitBtnId, "myQuitBtnId" }, { kRootAppId, kPanelDivId, "panelDivId" }, { kPanelDivId, kPanelBtn1Id, "myBtn1Id" }, { kPanelDivId, kPanelCheck1Id, "myCheck1Id" }, @@ -338,6 +349,8 @@ cw::rc_t cw::ui::test( const object_t* cfg ) { kSelId, kOpt1Id, "myOpt1" }, { kSelId, kOpt2Id, "myOpt2" }, { kSelId, kOpt3Id, "myOpt3" }, + { kPanelDivId, kListId, "myListId" } + }; unsigned mapN = sizeof(mapA)/sizeof(mapA[0]); @@ -355,8 +368,6 @@ cw::rc_t cw::ui::test( const object_t* cfg ) goto errLabel; } - - app->quitFl.store(false); // Initial values for the test applications @@ -370,6 +381,9 @@ cw::rc_t cw::ui::test( const object_t* cfg ) app->appCheck2Fl = true; app->appNumb = 1.23; app->appSelId = kOpt3Id; + + if((rc = cfg->getv( "listEle", app->listEleCfg )) != kOkRC ) + rc = cwLogError( rc, "The list element cfg. was not found."); //app->uiCfgFn = "/home/kevin/src/cwtest/src/libcw/html/uiTest/ui.cfg";