cwUi.h/cpp, cwUiTest.cpp, html/uiTest : Initial working version of cwUI.

This commit is contained in:
kevin.larke 2020-04-06 19:17:04 -04:00
parent d3d4c7c6f9
commit b6d716e8ff
6 changed files with 635 additions and 570 deletions

392
cwUi.cpp
View File

@ -19,7 +19,7 @@ namespace cw
struct appIdMapRecd_str* link; struct appIdMapRecd_str* link;
unsigned parentAppId; unsigned parentAppId;
unsigned appId; unsigned appId;
char* jsId; char* eleName;
} appIdMapRecd_t; } appIdMapRecd_t;
@ -28,7 +28,7 @@ namespace cw
struct ele_str* parent; // pointer to parent ele - or nullptr if this ele is attached to the root ui ele struct ele_str* parent; // pointer to parent ele - or nullptr if this ele is attached to the root ui ele
unsigned uuId; // UI unique id - automatically generated and unique among all elements that are part of this ui_t object. 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 unsigned appId; // application assigned id - application assigned id
char* jsId; // javascript id char* eleName; // javascript id
} ele_t; } ele_t;
typedef struct ui_str typedef struct ui_str
@ -52,7 +52,7 @@ namespace cw
for(unsigned i=0; i<p->eleN; ++i) for(unsigned i=0; i<p->eleN; ++i)
{ {
ele_t* e = p->eleA[i]; ele_t* e = p->eleA[i];
printf("%15s u:%i : u:%i a:%i %s\n",e->parent==nullptr?"<null>" : e->parent->jsId,e->parent==nullptr? -1 :e->parent->uuId,e->uuId,e->appId,e->jsId); printf("%15s u:%i : u:%i a:%i %s\n",e->parent==nullptr?"<null>" : e->parent->eleName,e->parent==nullptr? -1 :e->parent->uuId,e->uuId,e->appId,e->eleName);
} }
} }
@ -66,7 +66,7 @@ namespace cw
for(unsigned i=0; i<p->eleN; ++i) for(unsigned i=0; i<p->eleN; ++i)
{ {
mem::release(p->eleA[i]->jsId); mem::release(p->eleA[i]->eleName);
mem::release(p->eleA[i]); mem::release(p->eleA[i]);
} }
@ -74,22 +74,23 @@ namespace cw
while( m!=nullptr ) while( m!=nullptr )
{ {
appIdMapRecd_t* m0 = m->link; appIdMapRecd_t* m0 = m->link;
mem::release(m->jsId); mem::release(m->eleName);
mem::release(m); mem::release(m);
m = m0; m = m0;
} }
mem::release(p->eleA); mem::release(p->eleA);
mem::release(p->buf);
mem::release(p); mem::release(p);
return rc; return rc;
} }
appIdMapRecd_t* _findAppIdMap( ui_t* p, unsigned parentAppId, const char* jsId ) appIdMapRecd_t* _findAppIdMap( ui_t* p, unsigned parentAppId, const char* eleName )
{ {
appIdMapRecd_t* m = p->appIdMap; appIdMapRecd_t* m = p->appIdMap;
for(; m != nullptr; m=m->link) for(; m != nullptr; m=m->link)
if( m->parentAppId==parentAppId && textCompare(jsId,m->jsId)==0 ) if( m->parentAppId==parentAppId && textCompare(eleName,m->eleName)==0 )
return m; return m;
return nullptr; return nullptr;
} }
@ -103,42 +104,42 @@ namespace cw
return nullptr; return nullptr;
} }
rc_t _allocAppIdMap( ui_t* p, unsigned parentAppId, unsigned appId, const char* jsId ) rc_t _allocAppIdMap( ui_t* p, unsigned parentAppId, unsigned appId, const char* eleName )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
// The 'jsId' must be valid (or there is no reason to create the map. // The 'eleName' must be valid (or there is no reason to create the map.
// (since it will ultimately be used to locate the appId give the parentAppId and jsId) // (since it will ultimately be used to locate the appId give the parentAppId and eleName)
if( jsId == nullptr || strlen(jsId) == 0 ) if( eleName == nullptr || strlen(eleName) == 0 )
return cwLogError(kInvalidIdRC,"Registered parent/child app id's must have a valid 'jsId'."); return cwLogError(kInvalidIdRC,"Registered parent/child app id's must have a valid 'eleName'.");
// verify that the parent/child pair is unique // verify that the parent/child pair is unique
if( _findAppIdMap(p,parentAppId,appId) != nullptr ) if( _findAppIdMap(p,parentAppId,appId) != nullptr )
return cwLogError(kDuplicateRC,"An attempt was made to register a duplicate parent/child appid pair. parentId:%i appId:%i jsId:'%s'.",parentAppId,appId,cwStringNullGuard(jsId)); return cwLogError(kDuplicateRC,"An attempt was made to register a duplicate parent/child appid pair. parentId:%i appId:%i eleName:'%s'.",parentAppId,appId,cwStringNullGuard(eleName));
// verify that the parent/js pair is unique // verify that the parent/js pair is unique
if( _findAppIdMap(p,parentAppId,jsId) != nullptr ) if( _findAppIdMap(p,parentAppId,eleName) != nullptr )
return cwLogError(kDuplicateRC,"An attempt was made to register a duplicate parent app id/js id pair. parentId:%i appId:%i jsId:'%s'.",parentAppId,appId,cwStringNullGuard(jsId)); return cwLogError(kDuplicateRC,"An attempt was made to register a duplicate parent app id/js id pair. parentId:%i appId:%i eleName:'%s'.",parentAppId,appId,cwStringNullGuard(eleName));
// allocate and link in a new appId map record // allocate and link in a new appId map record
appIdMapRecd_t* m = mem::allocZ<appIdMapRecd_t>(); appIdMapRecd_t* m = mem::allocZ<appIdMapRecd_t>();
m->parentAppId = parentAppId; m->parentAppId = parentAppId;
m->appId = appId; m->appId = appId;
m->jsId = mem::duplStr(jsId); m->eleName = mem::duplStr(eleName);
m->link = p->appIdMap; m->link = p->appIdMap;
p->appIdMap = m; p->appIdMap = m;
return rc; return rc;
} }
ele_t* _createEle( ui_t* p, ele_t* parent, unsigned appId, const char* jsId ) ele_t* _createEle( ui_t* p, ele_t* parent, unsigned appId, const char* eleName )
{ {
ele_t* e = mem::allocZ<ele_t>(); ele_t* e = mem::allocZ<ele_t>();
e->parent = parent; e->parent = parent;
e->uuId = p->eleN; e->uuId = p->eleN;
e->appId = appId; e->appId = appId;
e->jsId = mem::duplStr(jsId); e->eleName = mem::duplStr(eleName);
if( p->eleN == p->eleAllocN ) if( p->eleN == p->eleAllocN )
{ {
p->eleAllocN += 100; p->eleAllocN += 100;
@ -147,6 +148,15 @@ namespace cw
p->eleA[ p->eleN ] = e; p->eleA[ p->eleN ] = e;
p->eleN += 1; p->eleN += 1;
// if the given appId was not valid ...
if( appId == kInvalidId && parent != nullptr )
{
appIdMapRecd_t* m;
// ... then try to look it up from the appIdMap.
if((m = _findAppIdMap( p, parent->appId, eleName)) != nullptr )
e->appId = m->appId;
}
return e; return e;
} }
@ -163,33 +173,57 @@ namespace cw
return p->eleA[ uuId ]; return p->eleA[ uuId ];
} }
// Given a parent UuId and a javascript id find the associated ele ele_t* _eleNameToEle( ui_t* p, const char* eleName, bool errorFl=true )
ele_t* _parentUuId_JsId_ToEle( ui_t* p, unsigned parentUuId, const char* jsId, bool errorFl=true )
{ {
for(unsigned i=0; i<p->eleN; ++i) for(unsigned i=0; i<p->eleN; ++i)
if( ((p->eleA[i]->parent==nullptr && parentUuId == kRootUuId) || (p->eleA[i]->parent != nullptr && parentUuId == p->eleA[i]->parent->uuId)) && (strcmp(p->eleA[i]->jsId,jsId) == 0)) if( textCompare(p->eleA[i]->eleName,eleName) == 0 )
return p->eleA[i]; return p->eleA[i];
if( errorFl )
cwLogError(kInvalidIdRC,"The element with eleName:%s not found.",cwStringNullGuard(eleName));
return nullptr;
}
// Given a parent UuId and a eleName find the associated ele
ele_t* _parentUuId_EleName_ToEle( ui_t* p, unsigned parentUuId, const char* eleName, bool errorFl=true )
{
// if we are looking for the root
if( (parentUuId==kRootUuId || parentUuId == kInvalidId) && textCompare(eleName,"uiDivId")==0 )
{
for(unsigned i=0; i<p->eleN; ++i)
if( p->eleA[i]->parent==nullptr && p->eleA[i]->uuId==kRootUuId)
return p->eleA[i];
}
else // we are looking for an elment which is not the root
{
for(unsigned i=0; i<p->eleN; ++i)
if( ((p->eleA[i]->parent==nullptr && parentUuId == kRootUuId) || (p->eleA[i]->parent != nullptr && parentUuId == p->eleA[i]->parent->uuId)) && (textCompare(p->eleA[i]->eleName,eleName) == 0))
return p->eleA[i];
}
if( errorFl ) if( errorFl )
cwLogError(kInvalidIdRC,"The element with parent uuid:%i and jsId:%s is not found.",parentUuId,jsId); cwLogError(kInvalidIdRC,"The element with parent uuid:%i and eleName:%s is not found.",parentUuId,eleName);
return nullptr; return nullptr;
} }
unsigned _findElementUuId( ui_t* p, const char* jsId ) unsigned _findElementUuId( ui_t* p, const char* eleName )
{ {
for(unsigned i=0; i<p->eleN; ++i) for(unsigned i=0; i<p->eleN; ++i)
if( strcmp(p->eleA[i]->jsId,jsId) == 0 ) if( strcmp(p->eleA[i]->eleName,eleName) == 0 )
return p->eleA[i]->uuId; return p->eleA[i]->uuId;
return kInvalidId; return kInvalidId;
} }
const char* _findEleJsId( ui_t* p, unsigned uuId ) const char* _findEleEleName( ui_t* p, unsigned uuId )
{ {
for(unsigned i=0; i<p->eleN; ++i) for(unsigned i=0; i<p->eleN; ++i)
if( p->eleA[i]->uuId == uuId ) if( p->eleA[i]->uuId == uuId )
return p->eleA[i]->jsId; return p->eleA[i]->eleName;
return nullptr; return nullptr;
} }
@ -234,11 +268,10 @@ namespace cw
} }
template< typename... ARGS> template< typename... ARGS>
rc_t _createOneEle( ui_t* p, unsigned& uuIdRef, const char* eleTypeStr, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title, ARGS&&... 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 )
{ {
// { op:create, parent:my_parent_id, value:{ button:{ jsId:my_jsId, appId:appId, uuId:uuId, class:clas, title:'my title' } } // { op:create, parent:my_parent_id, value:{ button:{ eleName:my_eleName, appId:appId, uuId:uuId, class:clas, title:'my title' } }
rc_t rc = kOkRC; rc_t rc = kOkRC;
const char* parentJsId = "";
ele_t* newEle = nullptr; ele_t* newEle = nullptr;
ele_t* parentEle = nullptr; ele_t* parentEle = nullptr;
//const unsigned bufN = 1024; // TODO: use preallocated buffer //const unsigned bufN = 1024; // TODO: use preallocated buffer
@ -253,20 +286,19 @@ namespace cw
if(( parentEle = _uuIdToEle(p, parentUuId )) == nullptr ) if(( parentEle = _uuIdToEle(p, parentUuId )) == nullptr )
return cwLogError( kInvalidArgRC, "Unable to locate the parent element (id:%i).", parentUuId ); return cwLogError( kInvalidArgRC, "Unable to locate the parent element (id:%i).", parentUuId );
// get the parent jsId
parentJsId = parentEle->jsId;
// create the local representation of the new element // create the local representation of the new element
newEle = _createEle( p, parentEle, appId, jsId ); newEle = _createEle( p, parentEle, appId, eleName );
// form the create json message string // form the create json message string
unsigned i = snprintf( p->buf, p->bufN, "{ \"op\":\"create\", \"parent\":\"%s\", \"children\":{ \"%s\":{ \"jsId\":\"%s\", \"appId\":%i, \"uuId\":%i, \"class\":\"%s\", \"title\":\"%s\" ", parentJsId, eleTypeStr, jsId, appId, newEle->uuId, clas, title ); //unsigned i = snprintf( p->buf, p->bufN, "{ \"op\":\"create\", \"parent\":\"%s\", \"children\":{ \"%s\":{ \"eleName\":\"%s\", \"appId\":%i, \"uuId\":%i, \"class\":\"%s\", \"title\":\"%s\" ", parentEleName, eleTypeStr, eleName, appId, newEle->uuId, clas, title );
unsigned i = snprintf( p->buf, p->bufN, "{ \"op\":\"create\", \"parentUuId\":\"%i\", \"type\":\"%s\", \"eleName\":\"%s\", \"appId\":\"%i\", \"uuId\":%i, \"class\":\"%s\", \"title\":\"%s\" ", parentEle->uuId, eleTypeStr, eleName, appId, newEle->uuId, clas, title );
// add the UI specific attributes // add the UI specific attributes
i += format_attributes(p->buf+i, p->bufN-i, 0, std::forward<ARGS>(args)...); i += format_attributes(p->buf+i, p->bufN-i, 0, std::forward<ARGS>(args)...);
// terminate the message // terminate the message
i += toText(p->buf+i, p->bufN-i, "}}}"); i += toText(p->buf+i, p->bufN-i, "}");
if( i >= p->bufN ) if( i >= p->bufN )
return cwLogError(kBufTooSmallRC,"The UI message formatting buffer is too small. (size:%i bytes)", p->bufN); return cwLogError(kBufTooSmallRC,"The UI message formatting buffer is too small. (size:%i bytes)", p->bufN);
@ -281,92 +313,168 @@ namespace cw
return rc; return rc;
} }
rc_t _decorateObj( ui_t* p, object_t* o ) ele_t* _findOrCreateEle( ui_t* p, ele_t* parentEle, const char* eleName )
{ {
rc_t rc = kOkRC; ele_t* ele;
const object_t* oo; if((ele = _parentUuId_EleName_ToEle( p, parentEle->uuId, eleName, false )) == nullptr )
//ele_t* parent_ele; ele = _createEle(p, parentEle, kInvalidId, eleName );
const char* jsId;
// find the parent pair return ele;
if((oo = o->find( "parent", kNoRecurseFl | kOptionalFl)) != nullptr )
{
}
// find the parent JsId
if((rc = oo->value(jsId)) != kOkRC )
{
}
// find the parent element
//if((parent_ele = _jsIdToEle( p, jsId )) == nullptr )
//{
//}
return rc;
} }
rc_t _createElementsFromChildList( ui_t* p, object_t* po, unsigned wsSessId, ele_t* parentEle );
rc_t _createFromObj( ui_t* p, object_t* o, unsigned wsSessId, unsigned parentUuId ) //
rc_t _createEleFromRsrsc( ui_t* p, ele_t* parentEle, const char* eleType, object_t* o, unsigned wsSessId )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
const char* parentJsId = ""; object_t* co = nullptr;
const int kBufN = 512; // TODO: preallocate this buffer as part of ui_t. ele_t* ele = nullptr;
char buf0[ kBufN ]; char* eleName = nullptr;
char buf1[ kBufN ];
// if a parentUuid was given ... if( !o->is_dict() )
if( parentUuId != kInvalidId ) return cwLogError(kSyntaxErrorRC,"All ui element resource records must be dictionaries.");
// if this object has a 'children' list then unlink it an save it for later
if((co = o->find("children", kNoRecurseFl | kOptionalFl)) != nullptr )
{ {
// ... then find the associated JS id co = co->parent;
if((parentJsId = _findEleJsId( p, parentUuId )) == nullptr ) co->unlink();
return cwLogError(kInvalidIdRC, "The JS id associated with the uuid '%i' could not be found for an resource object.", parentUuId );
} }
else // if no parentUuid was given then look for one in the resource
// get the ui ele name
if((rc = o->get("name",eleName)) != kOkRC )
{ {
// get the parent JS id from the cfg object rc = cwLogError(rc,"The UI element name could not be read.");
rc = o->get("parent",parentJsId,kNoRecurseFl | kOptionalFl); goto errLabel;
}
switch(rc)
// get or create the ele record to associate with this ele
if((ele = _findOrCreateEle( p, parentEle, eleName )) == nullptr )
{
rc = cwLogError(kOpFailRC,"The local element '%s' could not be created.",cwStringNullGuard(eleName));
goto errLabel;
}
if( o->insertPair("uuId",ele->uuId) == nullptr )
{
rc = cwLogError(kOpFailRC,"The 'uuid' node insertion failed on UI element '%s'.",cwStringNullGuard(eleName));
goto errLabel;
}
if( ele->appId != kInvalidId )
{
if( o->insertPair("appId",ele->appId) == nullptr )
{ {
case kOkRC: rc = cwLogError(kOpFailRC,"The 'appId' node insertion failed on UI element '%s'.",cwStringNullGuard(eleName));
// get a pointer to the jsId from the local list (the copy in the object is about to be deleted) goto errLabel;
parentJsId = _findEleJsId( p, _findElementUuId(p,parentJsId));
//remove the parent link
o->find("parent")->parent->free();
break;
case kLabelNotFoundRC:
parentJsId = _findEleJsId( p, kRootUuId );
break;
default:
rc = cwLogError(rc,"The resource object parent id '%s' could not be found.", parentJsId );
goto errLabel;
} }
}
if( o->insertPair("parentUuId",parentEle->uuId) == nullptr )
{
rc = cwLogError(kOpFailRC,"The 'parentUuId' node insertion failed on UI element '%s'.",cwStringNullGuard(eleName));
goto errLabel;
}
if( o->insertPair("op","create") == nullptr )
{
rc = cwLogError(kOpFailRC,"The 'op' node insertion failed on UI element '%s'.",cwStringNullGuard(eleName));
goto errLabel;
} }
// form the msg string from the resource if( o->insertPair("type",eleType) == nullptr )
if( o->to_string( buf0, kBufN ) >= kBufN ) {
return cwLogError(kBufTooSmallRC,"The resource object string buffer is too small (buf bytes:%i).",kBufN); rc = cwLogError(kOpFailRC,"The 'eleType' node insertion failed on UI element '%s'.",cwStringNullGuard(eleName));
goto errLabel;
}
printf("buf0: %s\n",buf0); if( o->to_string(p->buf,p->bufN) >= p->bufN )
if( snprintf( buf1, kBufN, "{ \"op\":\"create\", \"parent\":\"%s\", \"children\":%s }", parentJsId, buf0 ) >= kBufN ) {
return cwLogError(kBufTooSmallRC,"The resource object string buffer is too small (buf bytes:%i).",kBufN); rc = cwLogError(kOpFailRC,"Conversion to JSON string failed on UI element '%s'.",cwStringNullGuard(eleName));
goto errLabel;
}
// send the msg string
printf("buf1: %s\n",buf1);
rc = _websockSend( p, wsSessId, buf1 );
printf("%s\n",p->buf);
if((rc = _websockSend( p, wsSessId, p->buf )) != kOkRC )
{
rc = cwLogError(rc,"The creation request send failed on UI element '%s'.", cwStringNullGuard(eleName));
goto errLabel;
}
// if this element has a list of children then create them here
if( co != nullptr )
rc = _createElementsFromChildList(p, co->pair_value(), wsSessId, ele );
errLabel: errLabel:
if( co != nullptr )
co->free();
return rc; return rc;
} }
// 'od' is an object dictionary where each pair in the dictionary has
// the form: 'eleType':{ <object> }
rc_t _createElementsFromChildList( ui_t* p, object_t* po, unsigned wsSessId, ele_t* parentEle )
{
rc_t rc = kOkRC;
if( !po->is_dict() )
return cwLogError(kSyntaxErrorRC,"All UI resource elements must be containers.");
unsigned childN = po->child_count();
for(unsigned i=0; i<childN; ++i)
{
object_t* o = po->child_ele(i);
if( !o->is_pair() )
return cwLogError(kSyntaxErrorRC,"All object dictionary children must be pairs.");
if((rc = _createEleFromRsrsc(p, parentEle, o->pair_label(), o->pair_value(), wsSessId )) != kOkRC )
return rc;
}
return rc;
}
rc_t _createFromObj( ui_t* p, object_t* o, unsigned wsSessId, unsigned parentUuId )
{
rc_t rc = kOkRC;
object_t* po = nullptr;
ele_t* parentEle = nullptr;
char* eleName = nullptr;
// locate the the 'parent' ele name value object
if((po = o->find("parent",kNoRecurseFl | kOptionalFl)) == nullptr )
return cwLogError(kSyntaxErrorRC,"UI resources must have a root 'parent' value.");
// get the parent element name
if((rc = po->value(eleName)) != kOkRC )
return cwLogError(kOpFailRC,"The root 'parent' value could not be accessed.");
// find the parent element
if((parentEle = _parentUuId_EleName_ToEle( p, parentUuId, eleName )) == nullptr )
return cwLogError(kSyntaxErrorRC,"A parent UI element named '%s' could not be found.",cwStringNullGuard(eleName));
// unlink the 'parent' pair
po = po->parent;
po->unlink();
rc = _createElementsFromChildList( p, o, wsSessId, parentEle );
po->free();
return rc;
}
ele_t* _parse_value_msg( ui_t* p, value_t& valueRef, const char* msg ) ele_t* _parse_value_msg( ui_t* p, value_t& valueRef, const char* msg )
{ {
@ -449,7 +557,7 @@ namespace cw
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
unsigned i = snprintf(p->buf,p->bufN,"{ \"op\":\"set_app_id\", \"parentUuId\":%i, \"jsId\":\"%s\", \"appId\":%i, \"uuId\":%i }", ele->parent->uuId, ele->jsId, ele->parent->appId, ele->appId ); unsigned i = snprintf(p->buf,p->bufN,"{ \"op\":\"set_app_id\", \"parentUuId\":%i, \"eleName\":\"%s\", \"appId\":%i, \"uuId\":%i }", ele->parent->uuId, ele->eleName, ele->parent->appId, ele->appId );
if( i >= p->bufN ) if( i >= p->bufN )
return cwLogError(kBufTooSmallRC,"The 'app_id' msg formatting buffer is too small (%i bytes).", p->bufN); return cwLogError(kBufTooSmallRC,"The 'app_id' msg formatting buffer is too small (%i bytes).", p->bufN);
@ -475,10 +583,10 @@ namespace cw
const char* s0 = nextNonWhiteChar(msg + strlen("register")); const char* s0 = nextNonWhiteChar(msg + strlen("register"));
const char* jsId = nextNonWhiteChar(nextWhiteChar(s0)); const char* eleName = nextNonWhiteChar(nextWhiteChar(s0));
// verifity the message tokens // verifity the message tokens
if( s0 == nullptr || jsId == nullptr ) if( s0 == nullptr || eleName == nullptr )
{ {
cwLogError(kSyntaxErrorRC, "'register' msg format error: '%s' is not a valid message.", cwStringNullGuard(msg) ); cwLogError(kSyntaxErrorRC, "'register' msg format error: '%s' is not a valid message.", cwStringNullGuard(msg) );
goto errLabel; goto errLabel;
@ -499,15 +607,15 @@ namespace cw
} }
// if the child element does not already exist // if the child element does not already exist
if(( ele = _parentUuId_JsId_ToEle( p, parentUuId, jsId, false )) == nullptr ) if(( ele = _parentUuId_EleName_ToEle( p, parentUuId, eleName, false )) == nullptr )
{ {
// look up the parent/jsId pair map // look up the parent/eleName pair map
appIdMapRecd_t* m = _findAppIdMap( p, parentEle->appId, jsId ); appIdMapRecd_t* m = _findAppIdMap( p, parentEle->appId, eleName );
// create the ele // create the ele
ele = _createEle( p, parentEle, m==nullptr ? kInvalidId : m->appId, jsId ); ele = _createEle( p, parentEle, m==nullptr ? kInvalidId : m->appId, eleName );
printf("creating: parent uuid:%i js:%s \n", parentUuId,jsId); printf("creating: parent uuid:%i js:%s \n", parentUuId,eleName);
// notify the app of the new ele's uuid and appId // notify the app of the new ele's uuid and appId
if( m != nullptr ) if( m != nullptr )
@ -516,7 +624,7 @@ namespace cw
} }
else else
{ {
printf("parent uuid:%i js:%s already exists.\n", parentUuId,jsId); printf("parent uuid:%i js:%s already exists.\n", parentUuId,eleName);
} }
if( ele != nullptr ) if( ele != nullptr )
@ -585,10 +693,6 @@ namespace cw
// Pass on the 'init' msg to the app. // Pass on the 'init' msg to the app.
p->cbFunc( p->cbArg, wsSessId, opId, kInvalidId, kInvalidId, kInvalidId, nullptr ); p->cbFunc( p->cbArg, wsSessId, opId, kInvalidId, kInvalidId, kInvalidId, nullptr );
// The UI is initialized - begin the id update process
if( _websockSend( p, wsSessId, "{ \"op\":\"begin_app_id_update\" }" ) != kOkRC )
cwLogError(kOpFailRC,"'begin_app_id_update' transmit failed.");
break; break;
case kValueOpId: case kValueOpId:
@ -684,7 +788,7 @@ cw::rc_t cw::ui::createUi(
p->bufN = fmtBufByteN; p->bufN = fmtBufByteN;
// create the root element // create the root element
if((ele = _createEle(p, nullptr, kRootEleAppId, "uiDivId" )) == nullptr || ele->uuId != kRootUuId ) if((ele = _createEle(p, nullptr, kRootAppId, "uiDivId" )) == nullptr || ele->uuId != kRootUuId )
{ {
cwLogError(kOpFailRC,"The UI root element creation failed."); cwLogError(kOpFailRC,"The UI root element creation failed.");
goto errLabel; goto errLabel;
@ -739,22 +843,22 @@ cw::rc_t cw::ui::destroyUi( handle_t& h )
return rc; return rc;
} }
unsigned cw::ui::findElementAppId( handle_t h, unsigned parentUuId, const char* jsId ) unsigned cw::ui::findElementAppId( handle_t h, unsigned parentUuId, const char* eleName )
{ {
ui_t* p = _handleToPtr(h); ui_t* p = _handleToPtr(h);
for(unsigned i=0; i<p->eleN; ++i) for(unsigned i=0; i<p->eleN; ++i)
if( p->eleA[i]->parent->uuId==parentUuId && strcmp(p->eleA[i]->jsId,jsId) == 0 ) if( p->eleA[i]->parent->uuId==parentUuId && strcmp(p->eleA[i]->eleName,eleName) == 0 )
return p->eleA[i]->appId; return p->eleA[i]->appId;
return kInvalidId; return kInvalidId;
} }
unsigned cw::ui::findElementUuId( handle_t h, unsigned parentUuId, const char* jsId ) unsigned cw::ui::findElementUuId( handle_t h, unsigned parentUuId, const char* eleName )
{ {
ui_t* p = _handleToPtr(h); ui_t* p = _handleToPtr(h);
ele_t* ele; ele_t* ele;
if((ele = _parentUuId_JsId_ToEle(p, parentUuId, jsId )) != nullptr ) if((ele = _parentUuId_EleName_ToEle(p, parentUuId, eleName )) != nullptr )
return ele->uuId; return ele->uuId;
return kInvalidId; return kInvalidId;
@ -770,17 +874,17 @@ unsigned cw::ui::findElementUuId( handle_t h, unsigned parentUuId, unsigned appI
return kInvalidId; return kInvalidId;
} }
const char* cw::ui::findElementJsId( handle_t h, unsigned uuId ) const char* cw::ui::findElementName( handle_t h, unsigned uuId )
{ {
ui_t* p = _handleToPtr(h); ui_t* p = _handleToPtr(h);
return _findEleJsId(p,uuId); return _findEleEleName(p,uuId);
} }
unsigned cw::ui::findElementUuId( handle_t h, const char* jsId ) unsigned cw::ui::findElementUuId( handle_t h, const char* eleName )
{ {
ui_t* p = _handleToPtr(h); ui_t* p = _handleToPtr(h);
return _findElementUuId(p,jsId); return _findElementUuId(p,eleName);
} }
@ -830,34 +934,34 @@ cw::rc_t cw::ui::createFromText( handle_t h, const char* text, unsigned wsSessId
return rc; return rc;
} }
cw::rc_t cw::ui::createDiv( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title ) cw::rc_t cw::ui::createDiv( 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, "div", wsSessId, parentUuId, jsId, appId, clas, title ); } { return _createOneEle( _handleToPtr(h), uuIdRef, "div", wsSessId, parentUuId, eleName, appId, clas, title ); }
cw::rc_t cw::ui::createTitle( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title ) cw::rc_t cw::ui::createTitle( 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, "option", wsSessId, parentUuId, jsId, appId, clas, title ); } { return _createOneEle( _handleToPtr(h), uuIdRef, "option", wsSessId, parentUuId, eleName, appId, clas, title ); }
cw::rc_t cw::ui::createButton( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title ) cw::rc_t cw::ui::createButton( 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, "button", wsSessId, parentUuId, jsId, appId, clas, title ); } { return _createOneEle( _handleToPtr(h), uuIdRef, "button", wsSessId, parentUuId, eleName, appId, clas, title ); }
cw::rc_t cw::ui::createCheck( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title, bool value ) cw::rc_t cw::ui::createCheck( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, bool value )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "check", wsSessId, parentUuId, jsId, appId, clas, title, "value", value ); } { return _createOneEle( _handleToPtr(h), uuIdRef, "check", wsSessId, parentUuId, eleName, appId, clas, title, "value", value ); }
cw::rc_t cw::ui::createSelect( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title ) cw::rc_t cw::ui::createSelect( 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, "select", wsSessId, parentUuId, jsId, appId, clas, title ); } { return _createOneEle( _handleToPtr(h), uuIdRef, "select", wsSessId, parentUuId, eleName, appId, clas, title ); }
cw::rc_t cw::ui::createOption( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title ) cw::rc_t cw::ui::createOption( 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, "option", wsSessId, parentUuId, jsId, appId, clas, title ); } { return _createOneEle( _handleToPtr(h), uuIdRef, "option", wsSessId, parentUuId, eleName, appId, clas, title ); }
cw::rc_t cw::ui::createString( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title, const char* value ) cw::rc_t cw::ui::createString( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, const char* value )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "string", wsSessId, parentUuId, jsId, appId, clas, title, "value", value ); } { return _createOneEle( _handleToPtr(h), uuIdRef, "string", wsSessId, parentUuId, eleName, appId, clas, title, "value", value ); }
cw::rc_t cw::ui::createNumber( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title, double value, double minValue, double maxValue, double stepValue, unsigned decpl ) cw::rc_t cw::ui::createNumber( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, double value, double minValue, double maxValue, double stepValue, unsigned decpl )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "number", wsSessId, parentUuId, jsId, appId, clas, title, "value", value, "min", minValue, "max", maxValue, "step", stepValue, "decpl", decpl ); } { return _createOneEle( _handleToPtr(h), uuIdRef, "number", wsSessId, parentUuId, eleName, appId, clas, title, "value", value, "min", minValue, "max", maxValue, "step", stepValue, "decpl", decpl ); }
cw::rc_t cw::ui::createProgress( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title, double value, double minValue, double maxValue ) cw::rc_t cw::ui::createProgress( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, double value, double minValue, double maxValue )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "progress", wsSessId, parentUuId, jsId, appId, clas, title, "value", value, "min", minValue, "max", maxValue ); } { return _createOneEle( _handleToPtr(h), uuIdRef, "progress", wsSessId, parentUuId, eleName, appId, clas, title, "value", value, "min", minValue, "max", maxValue ); }
cw::rc_t cw::ui::createText( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title ) cw::rc_t cw::ui::createText( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title )
{ {
rc_t rc= kOkRC; rc_t rc= kOkRC;
return rc; return rc;
@ -871,7 +975,7 @@ cw::rc_t cw::ui::registerAppIds( handle_t h, const appIdMap_t* map, unsigned ma
rc_t rc = kOkRC; rc_t rc = kOkRC;
for(unsigned i=0; i<mapN; ++i) for(unsigned i=0; i<mapN; ++i)
if((rc = _allocAppIdMap( p, map[i].parentAppId, map[i].appId, map[i].jsId )) != kOkRC ) if((rc = _allocAppIdMap( p, map[i].parentAppId, map[i].appId, map[i].eleName )) != kOkRC )
return rc; return rc;
return rc; return rc;

36
cwUi.h
View File

@ -41,7 +41,7 @@ namespace cw
enum enum
{ {
kRootUuId = 0, kRootUuId = 0,
kRootEleAppId, kRootAppId,
}; };
typedef struct typedef struct
@ -76,35 +76,35 @@ namespace cw
rc_t start( handle_t h ); rc_t start( handle_t h );
rc_t stop( handle_t h ); rc_t stop( handle_t h );
unsigned findElementAppId( handle_t h, unsigned parentUuId, const char* jsId ); unsigned findElementAppId( handle_t h, unsigned parentUuId, const char* eleName );
unsigned findElementUuId( handle_t h, unsigned parentUuId, const char* jsId ); unsigned findElementUuId( handle_t h, unsigned parentUuId, const char* eleName );
unsigned findElementUuId( handle_t h, unsigned parentUuId, unsigned appId ); unsigned findElementUuId( handle_t h, unsigned parentUuId, unsigned appId );
const char* findElementJsId( handle_t h, unsigned uuId ); const char* findElementName( handle_t h, unsigned uuId );
// Return the uuid of the first matching 'jsId'. // Return the uuid of the first matching 'eleName'.
unsigned findElementUuId( handle_t h, const char* jsId ); unsigned findElementUuId( handle_t h, const char* eleName );
rc_t createFromFile( handle_t h, const char* fn, unsigned wsSessId, unsigned parentUuId=kInvalidId); rc_t createFromFile( handle_t h, const char* fn, unsigned wsSessId, unsigned parentUuId=kInvalidId);
rc_t createFromText( handle_t h, const char* text, unsigned wsSessId, unsigned parentUuId=kInvalidId); rc_t createFromText( handle_t h, const char* text, unsigned wsSessId, unsigned parentUuId=kInvalidId);
rc_t createDiv( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title ); rc_t createDiv( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title );
rc_t createTitle( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title ); rc_t createTitle( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title );
rc_t createButton( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title ); rc_t createButton( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title );
rc_t createCheck( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title, bool value ); rc_t createCheck( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, bool value );
rc_t createSelect( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title ); rc_t createSelect( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title );
rc_t createOption( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title ); rc_t createOption( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title );
rc_t createString( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title, const char* value ); rc_t createString( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, const char* value );
rc_t createNumber( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title, double value, double minValue, double maxValue, double stepValue, unsigned decPl ); rc_t createNumber( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, double value, double minValue, double maxValue, double stepValue, unsigned decPl );
rc_t createProgress( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title, double value, double minValue, double maxValue ); rc_t createProgress( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, double value, double minValue, double maxValue );
rc_t createText( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* jsId, unsigned appId, const char* clas, const char* title ); rc_t createText( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title );
typedef struct appIdMap_str typedef struct appIdMap_str
{ {
unsigned parentAppId; unsigned parentAppId;
unsigned appId; unsigned appId;
const char* jsId; const char* eleName;
} appIdMap_t; } appIdMap_t;
// Register parent/child/js app id's // Register parent/child/name app id's
rc_t registerAppIds( handle_t h, const appIdMap_t* map, unsigned mapN ); rc_t registerAppIds( handle_t h, const appIdMap_t* map, unsigned mapN );
} }

View File

@ -28,7 +28,11 @@ namespace cw
kOption3Id, kOption3Id,
kStringId, kStringId,
kNumberId, kNumberId,
kProgressId kProgressId,
kPanelDivId,
kPanelBtnId,
kPanelCheckId
}; };
rc_t _uiTestCreateUi( ui_test_t* p, unsigned wsSessId ) rc_t _uiTestCreateUi( ui_test_t* p, unsigned wsSessId )
@ -38,6 +42,15 @@ namespace cw
unsigned selUuId = kInvalidId; unsigned selUuId = kInvalidId;
unsigned divUuId = kInvalidId; unsigned divUuId = kInvalidId;
appIdMap_t mapA[] =
{
{ ui::kRootAppId, kPanelDivId, "panelDivId" },
{ ui::kPanelDivId, kPanelBtnId, "myBtn1Id" },
{ ui::kPanelDivId, kPanelCheckId, "myCheck1Id" },
};
registerAppIds(p->uiH, mapA, sizeof(mapA)/sizeof(mapA[0]));
if((rc = createDiv( p->uiH, divUuId, wsSessId, kInvalidId, "myDivId", kDivId, "divClass", "My Panel" )) != kOkRC ) if((rc = createDiv( p->uiH, divUuId, wsSessId, kInvalidId, "myDivId", kDivId, "divClass", "My Panel" )) != kOkRC )
goto errLabel; goto errLabel;

View File

@ -15,7 +15,7 @@
<p id="appTitleId">Disconnected</p> <p id="appTitleId">Disconnected</p>
<div id="uiDivId" class="uiAppDiv"> <div id="0" class="uiAppDiv">
</div> </div>
</body> </body>

View File

@ -1,54 +1,54 @@
var _ws = null; var _ws = null;
var _rootJsId = "uiDivId"; var _rootId = "0";
var _nextEleId = 0; var _nextEleId = 0;
function set_app_title( suffix, className ) function set_app_title( suffix, className )
{ {
var ele = document.getElementById('appTitleId'); var ele = document.getElementById('appTitleId');
ele.innerHTML = "UI Test:" + suffix ele.innerHTML = "UI Test:" + suffix
ele.className = className ele.className = className
} }
function uiOnError( msg, r) function uiOnError( msg, r)
{ {
console.log("Error:" + msg); console.log("Error:" + msg);
} }
function uiGetParent( r ) function uiGetParent( r )
{ {
parent_ele = document.getElementById(r.parent_id); parent_ele = document.getElementById(r.parent_id);
if( parent_ele == null ) if( parent_ele == null )
{ {
uiOnError("Parent not found. parent_id:" + r.parent_id,r); uiOnError("Parent not found. parent_id:" + r.parent_id,r);
} }
return parent_ele; return parent_ele;
} }
function uiCreateEle( r ) function uiCreateEle( r )
{ {
var parent_ele; var parent_ele;
if((parent_ele = uiGetParent(r)) != null )
{
ele = document.createElement(r.ele_type)
ele.id = r.ele_id;
ele.className = r.value;
parent_ele.appendChild(ele) if((parent_ele = uiGetParent(r)) != null )
} {
ele = document.createElement(r.ele_type)
ele.id = r.ele_id;
ele.className = r.value;
parent_ele.appendChild(ele)
}
} }
function uiRemoveChildren( r ) function uiRemoveChildren( r )
{ {
ele = document.getElementById(r.ele_id) ele = document.getElementById(r.ele_id)
while (ele.firstChild) while (ele.firstChild)
{ {
ele.removeChild(ele.firstChild); ele.removeChild(ele.firstChild);
} }
} }
function uiDivCreate( r ) function uiDivCreate( r )
@ -56,148 +56,148 @@ function uiDivCreate( r )
function uiLabelCreate( r ) function uiLabelCreate( r )
{ {
var parent_ele; var parent_ele;
if((parent_ele = uiGetParent(r)) != null ) if((parent_ele = uiGetParent(r)) != null )
{ {
ele = document.createElement("label") ele = document.createElement("label")
ele.htmlFor = r.ele_id ele.htmlFor = r.ele_id
ele.innerHTML = r.value; ele.innerHTML = r.value;
parent_ele.appendChild(ele) parent_ele.appendChild(ele)
} }
} }
function uiSelectCreate( r ) function uiSelectCreate( r )
{ {
uiCreateEle(r) uiCreateEle(r)
} }
function uiSelectClear( r ) function uiSelectClear( r )
{ uiRemoveChildren(r) } { uiRemoveChildren(r) }
function uiSelectInsert( r ) function uiSelectInsert( r )
{ {
var select_ele; var select_ele;
if((select_ele = uiGetParent(r)) != null ) if((select_ele = uiGetParent(r)) != null )
{ {
var option = document.createElement('option'); var option = document.createElement('option');
option.id = r.ele_id; option.id = r.ele_id;
option.innerHTML = r.value; option.innerHTML = r.value;
option.value = r.ele_id; option.value = r.ele_id;
option.onclick = function() { uiOnSelectClick(this) } option.onclick = function() { uiOnSelectClick(this) }
select_ele.appendChild(option) select_ele.appendChild(option)
} }
} }
function uiSelectChoose( r ) function uiSelectChoose( r )
{ {
var select_ele; var select_ele;
if((select_ele = uiGetParent(r)) != null ) if((select_ele = uiGetParent(r)) != null )
{
if( select_ele.hasChildNodes())
{ {
var children = select_ele.childNodes if( select_ele.hasChildNodes())
for(var i=0; i<children.length; i++)
{
if( children[i].id == r.ele_id )
{ {
select_ele.selectedIndex = i var children = select_ele.childNodes
break; for(var i=0; i<children.length; i++)
} {
} if( children[i].id == r.ele_id )
{
select_ele.selectedIndex = i
break;
}
}
}
} }
}
} }
function uiOnSelectClick( ele ) function uiOnSelectClick( ele )
{ {
cmdstr = "mode ui ele_type select op choose parent_id "+ele.parentElement.id+" option_id " + ele.id cmdstr = "mode ui ele_type select op choose parent_id "+ele.parentElement.id+" option_id " + ele.id
websocket.send(cmdstr); websocket.send(cmdstr);
} }
function uiNumberOnKeyUp( e ) function uiNumberOnKeyUp( e )
{ {
if( e.keyCode == 13 ) if( e.keyCode == 13 )
{ {
//console.log(e) //console.log(e)
cmdstr = "mode ui ele_type number op change parent_id "+e.srcElement.parentElement.id+" ele_id " + e.srcElement.id + " value " + e.srcElement.value cmdstr = "mode ui ele_type number op change parent_id "+e.srcElement.parentElement.id+" ele_id " + e.srcElement.id + " value " + e.srcElement.value
websocket.send(cmdstr); websocket.send(cmdstr);
} }
} }
function uiNumberCreate( r ) function uiNumberCreate( r )
{ {
var parent_ele; var parent_ele;
if((parent_ele = uiGetParent(r)) != null ) if((parent_ele = uiGetParent(r)) != null )
{ {
ele = document.createElement("input") ele = document.createElement("input")
ele.id = r.ele_id ele.id = r.ele_id
ele.setAttribute('type','number') ele.setAttribute('type','number')
ele.addEventListener('keyup',uiNumberOnKeyUp) ele.addEventListener('keyup',uiNumberOnKeyUp)
parent_ele.appendChild(ele) parent_ele.appendChild(ele)
} }
} }
function uiNumberSet( r ) function uiNumberSet( r )
{ {
var ele; var ele;
console.log("ele_id:" + r.ele_id + " parent_id:" + r.parent_id + " value:" + r.value) console.log("ele_id:" + r.ele_id + " parent_id:" + r.parent_id + " value:" + r.value)
if((ele = document.getElementById(r.parent_id)) != null) if((ele = document.getElementById(r.parent_id)) != null)
{
switch( r.ele_id )
{ {
case "0": ele.min = r.value; break; switch( r.ele_id )
case "1": ele.max = r.value; break; {
case "2": ele.step = r.value; break; case "0": ele.min = r.value; break;
case "3": ele.value = r.value; break; case "1": ele.max = r.value; break;
case "2": ele.step = r.value; break;
case "3": ele.value = r.value; break;
}
} }
}
} }
function dom_child_by_id( parentEle, child_id ) function dom_child_by_id( parentEle, child_id )
{ {
var childrenL = parentEle.children var childrenL = parentEle.children
for(var i=0; i<childrenL.length; i++) for(var i=0; i<childrenL.length; i++)
{
if( childrenL[i].id == child_id )
{ {
return childrenL[i]; if( childrenL[i].id == child_id )
{
return childrenL[i];
}
} }
} return null;
return null;
} }
function dom_set_option_by_text( ele_id, text ) function dom_set_option_by_text( ele_id, text )
{ {
var ele = dom_id_to_ele(ele_id); var ele = dom_id_to_ele(ele_id);
for (var i = 0; i < ele.options.length; i++) for (var i = 0; i < ele.options.length; i++)
{ {
if (ele.options[i].text === text) if (ele.options[i].text === text)
{ {
ele.selectedIndex = i; ele.selectedIndex = i;
break; break;
}
} }
}
} }
function dom_set_number( ele_id, val ) function dom_set_number( ele_id, val )
{ {
dom_id_to_ele(ele_id).value = val dom_id_to_ele(ele_id).value = val
} }
@ -214,437 +214,385 @@ function dom_get_checkbox( ele_id )
function dom_create_ele( ele_type ) function dom_create_ele( ele_type )
{ {
ele = document.createElement(ele_type); ele = document.createElement(ele_type);
ele.id = _nextEleId; return ele
_nextEleId += 1;
} }
//============================================================================== //==============================================================================
function ui_error( msg ) function ui_error( msg )
{ {
console.log("Error: " + msg ) console.log("Error: " + msg )
} }
function ui_send_value( ele, typeId, value ) function ui_send_value( ele, typeId, value )
{ {
if( ele.hasOwnProperty('uuId') ) ws_send("value " + ele.id + " " + typeId + " : " + value)
ws_send("value " + ele.uuId + " " + typeId + " : " + value)
else
ui_error("A value msg send failed because the value had no UuId.");
} }
function ui_send_bool_value( ele, value ) { ui_send_value(ele,'b',value); } function ui_send_bool_value( ele, value ) { ui_send_value(ele,'b',value); }
function ui_send_int_value( ele, value ) { ui_send_value(ele,'i',value); } function ui_send_int_value( ele, value ) { ui_send_value(ele,'i',value); }
function ui_send_string_value( ele, value ) { ui_send_value(ele,'s',value); } function ui_send_string_value( ele, value ) { ui_send_value(ele,'s',value); }
function ui_send_register( ele )
{
ws_send("register " + ele.parentJsId + " " + ele.jsId + " " + ele.id + " " + ele.uuId + " " + ele.appId )
}
function ui_print_children( eleId ) function ui_print_children( eleId )
{ {
var childrenL = dom_id_to_ele(eleId).children var childrenL = dom_id_to_ele(eleId).children
for(var i=0; i<childrenL.length; i++) for(var i=0; i<childrenL.length; i++)
{ {
console.log( childrenL[i] ) console.log( childrenL[i] )
} }
} }
function ui_get_parent( parentId ) function ui_get_parent( parentId )
{ {
if( parentId==null || parentId.trim().length == 0 ) if( parentId==null || parentId.trim().length == 0 )
parentId = _rootJsId parentId = _rootId
parent_ele = dom_id_to_ele(parentId); parent_ele = dom_id_to_ele(parentId);
if( parent_ele == null ) if( parent_ele == null )
{ {
ui_error("Parent element id: " + parentId + " not found.") ui_error("Parent element id: " + parentId + " not found.")
} }
return parent_ele; return parent_ele;
} }
function ui_create_ele( parent_ele, ele_type, d ) function ui_create_ele( parent_ele, ele_type, d )
{ {
// create the ctl object // create the ctl object
var ele = dom_create_ele(ele_type); var ele = dom_create_ele(ele_type);
if( ele == null ) if( ele == null )
ui_error("'%s' element create failed.", ele_type); ui_error(ele_type +" element create failed.");
else else
{ {
ele.jsId = d.jsId; ele.id = d.uuId;
ele.parentJsId = d.parentJsId;
ele.uuId = d.hasOwnProperty("uuId") ? d.uuId : null
ele.appId = d.hasOwnProperty("appId") ? d.appId : null
console.log("Created: " + ele_type + " parent:" + d.parentJsId + " id:" + ele.id + " appId:" + ele.appId + " uuId:" + ele.uuId) if(d.hasOwnProperty('appId'))
ele.appId = d.appId;
parent_ele.appendChild(ele); else
ele.appId = null;
console.log("Created: " + ele_type + " parent:" + d.parentUuId + " id:" + ele.id + " appId:" + ele.appId)
parent_ele.appendChild(ele);
ui_send_register( ele );
}
} return ele
return ele
} }
function ui_create_ctl( parent_ele, ele_type, label, d ) function ui_create_ctl( parent_ele, ele_type, label, d )
{ {
// create an enclosing div // create an enclosing div
var div_ele = dom_create_ele("div"); var div_ele = dom_create_ele("div");
div_ele.className = d.clas; div_ele.className = d.clas;
parent_ele.appendChild( div_ele ); parent_ele.appendChild( div_ele );
var label_ele = div_ele var label_ele = div_ele
// if label is not null then create an enclosing 'label' element // if label is not null then create an enclosing 'label' element
if( label != null ) if( label != null )
{ {
label_ele = dom_create_ele("label"); label_ele = dom_create_ele("label");
label_ele.innerHTML = label; label_ele.innerHTML = label;
div_ele.appendChild(label_ele) div_ele.appendChild(label_ele)
} }
return ui_create_ele( label_ele, ele_type, d ); return ui_create_ele( label_ele, ele_type, d );
} }
function ui_create_div( parent_ele, d ) function ui_create_div( parent_ele, d )
{ {
var div_ele = ui_create_ele( parent_ele, "div", d ); var div_ele = ui_create_ele( parent_ele, "div", d );
if( div_ele != null ) if( div_ele != null )
{ {
div_ele.className = d.clas div_ele.className = d.clas
var p_ele = dom_create_ele("p")
if( d.title != null && d.title.length > 0 )
p_ele.innerHTML = d.title
div_ele.appendChild( p_ele )
}
var p_ele = dom_create_ele("p") return div_ele;
if( d.title != null && d.title.length > 0 )
p_ele.innerHTML = d.title
div_ele.appendChild( p_ele )
}
return div_ele;
} }
function ui_create_title( parent_ele, d ) function ui_create_title( parent_ele, d )
{ {
return ui_create_ele( parent_ele, "label", d ); return ui_create_ele( parent_ele, "label", d );
} }
function ui_create_button( parent_ele, d ) function ui_create_button( parent_ele, d )
{ {
var ele = ui_create_ctl( parent_ele, "button", null, d ); var ele = ui_create_ctl( parent_ele, "button", null, d );
if( ele != null ) if( ele != null )
{ {
ele.innerHTML = d.title; ele.innerHTML = d.title;
ele.onclick = function() { ui_send_int_value(this,1); } ele.onclick = function() { ui_send_int_value(this,1); }
} }
return ele; return ele;
} }
function ui_create_check( parent_ele, d ) function ui_create_check( parent_ele, d )
{ {
var ele = ui_create_ctl( parent_ele, "input", d.title, d ) var ele = ui_create_ctl( parent_ele, "input", d.title, d )
if( ele != null )
{
ele.type = "checkbox";
dom_set_checkbox(ele.id, d.value );
ele.onclick = function() { ui_send_bool_value(this,dom_get_checkbox(this.id)); } if( ele != null )
} {
return ele; ele.type = "checkbox";
dom_set_checkbox(ele.id, d.value );
ele.onclick = function() { ui_send_bool_value(this,dom_get_checkbox(this.id)); }
}
return ele;
} }
function ui_on_select( ele ) function ui_on_select( ele )
{ {
ui_send_int_value(ele,ele.options[ ele.selectedIndex ].appId); ui_send_int_value(ele,ele.options[ ele.selectedIndex ].appId);
} }
function ui_create_select( parent_ele, d ) function ui_create_select( parent_ele, d )
{ {
var sel_ele = ui_create_ctl( parent_ele, "select", d.title, d ); var sel_ele = ui_create_ctl( parent_ele, "select", d.title, d );
sel_ele.onchange = function() { ui_on_select(this) } sel_ele.onchange = function() { ui_on_select(this) }
return sel_ele; return sel_ele;
} }
function ui_create_option( parent_ele, d ) function ui_create_option( parent_ele, d )
{ {
var opt_ele = ui_create_ele( parent_ele, "option", d ); var opt_ele = ui_create_ele( parent_ele, "option", d );
if( opt_ele != null ) if( opt_ele != null )
{ {
opt_ele.className = d.clas; opt_ele.className = d.clas;
opt_ele.innerHTML = d.title; opt_ele.innerHTML = d.title;
} }
return opt_ele; return opt_ele;
} }
function ui_create_string( parent_ele, d ) function ui_create_string( parent_ele, d )
{ {
var ele = ui_create_ctl( parent_ele, "input", d.title, d ); var ele = ui_create_ctl( parent_ele, "input", d.title, d );
if( ele != null ) if( ele != null )
{ {
ele.value = d.value; ele.value = d.value;
ele.addEventListener('keyup', function(e) { if(e.keyCode===13){ ui_send_string_value(this, this.value); }} ); ele.addEventListener('keyup', function(e) { if(e.keyCode===13){ ui_send_string_value(this, this.value); }} );
} }
} }
function ui_number_keyup( e ) function ui_number_keyup( e )
{ {
console.log(e) if( e.keyCode===13 )
if( e.keyCode===13 )
{
var ele = dom_id_to_ele(e.target.id)
console.log(ele.value)
if( ele != null )
{ {
ui_send_int_value(ele,ele.value); var ele = dom_id_to_ele(e.target.id)
if( ele != null )
{
console.log("min:"+ele.minValue+" max:"+ele.maxValue)
var val = 0;
if( ele.decpl == 0 )
val = Number.parseInt(ele.value)
else
val = Number.parseFloat(ele.value)
if( !(ele.minValue<=val && val<=ele.maxValue))
ele.style.borderColor = "red"
else
{
ele.style.borderColor = ""
ui_send_int_value(ele,ele.value);
}
}
} }
}
} }
function ui_create_number( parent_ele, d ) function ui_create_number( parent_ele, d )
{ {
var ele = ui_create_ctl( parent_ele, "input", d.title, d ); var ele = ui_create_ctl( parent_ele, "input", d.title, d );
if( ele != null ) if( ele != null )
{ {
ele.value = d.value; ele.value = d.value;
ele.maxValue = d.max; ele.maxValue = d.max;
ele.minValue = d.min; ele.minValue = d.min;
ele.stepValue = d.step; ele.stepValue = d.step;
ele.decpl = d.decpl; ele.decpl = d.decpl;
ele.addEventListener('keyup', ui_number_keyup ); ele.addEventListener('keyup', ui_number_keyup );
} }
return ele; return ele;
} }
function ui_set_progress( ele_id, value ) function ui_set_progress( ele_id, value )
{ {
var ele = dom_id_to_ele(ele_id); var ele = dom_id_to_ele(ele_id);
ele.value = Math.round( ele.max * (value - ele.minValue) / (ele.maxValue - ele.minValue)); ele.value = Math.round( ele.max * (value - ele.minValue) / (ele.maxValue - ele.minValue));
} }
function ui_create_progress( parent_ele, d ) function ui_create_progress( parent_ele, d )
{ {
var ele = ui_create_ctl( parent_ele, "progress", d.title, d ); var ele = ui_create_ctl( parent_ele, "progress", d.title, d );
if( ele != null )
{
ele.max = 100;
ele.maxValue = d.max;
ele.minValue = d.min;
ui_set_progress( ele.id, d.value );
}
return ele
}
function ui_create( parentId, ele_type, d )
{
var parent_ele = ui_get_parent(parentId);
var ele = null;
if( parent_ele != null )
{
d.parentJsId = parentId
switch( ele_type )
{
case "div":
ele = ui_create_div( parent_ele, d )
break;
case "title":
ele = ui_create_title( parent_ele, d )
break;
case "button":
ele = ui_create_button( parent_ele, d )
break;
case "check":
ele = ui_create_check( parent_ele, d )
break;
case "select":
ele = ui_create_select( parent_ele, d );
break;
case "option":
ele = ui_create_option( parent_ele, d );
break;
case "string":
ele = ui_create_string( parent_ele, d );
break;
case "number":
ele = ui_create_number( parent_ele, d );
break;
case "progress":
ele = ui_create_progress( parent_ele, d );
break;
default:
ui_error("Unknown UI element type: " + ele_type )
}
if( d.hasOwnProperty("children") )
{
for (const ele_type in d.children)
ui_create( d.jsId, ele_type, d.children[ele_type] )
}
}
}
function ui_uuid_to_ele( uuId, ele=null )
{
if( ele == null )
ele = dom_id_to_ele( _rootJsId )
if( ele.hasOwnProperty('uuId') )
{
if( ele.uuId == uuId )
return ele
for(var i=0; i<ele.childElementCount; ++i)
ui_uuid_to_ele( uuId, ele.children[i] )
}
ui_error("The element with uuid: " + uuId + " was not found.")
return null
}
// Do breadth first search for ele's without uuId's
function ui_next_ele_to_register( parentEle )
{
for(var i=0; i<parentEle.childElementCount; ++i)
{
var ele = parentEle.children[i]
if( ele.hasOwnProperty('uuId') && ele.uuId==null)
return ele
}
for(var i=0; i<parentEle.childElementCount; ++i)
{
var ele = ui_next_ele_to_register( parentEle.children[i])
if( ele != null ) if( ele != null )
return ele {
} ele.max = 100;
ele.maxValue = d.max;
return null ele.minValue = d.min;
ui_set_progress( ele.id, d.value );
}
return ele
} }
//
function ui_set_app_uuId( d ) function ui_create( d )
{ {
console.log(d) if( typeof(d.parentUuId) == "number")
d.parentUuId = d.parentUuId.toString()
if( typeof(d.uuId) == "number" )
d.uuId = d.uuId.toString()
var parent_ele = ui_get_parent(d.parentUuId);
var ele = null;
if( parent_ele != null )
{
switch( d.type )
{
case "div":
ele = ui_create_div( parent_ele, d )
break;
case "title":
ele = ui_create_title( parent_ele, d )
break;
case "button":
ele = ui_create_button( parent_ele, d )
break;
case "check":
ele = ui_create_check( parent_ele, d )
break;
case "select":
ele = ui_create_select( parent_ele, d );
break;
case "option":
ele = ui_create_option( parent_ele, d );
break;
case "string":
ele = ui_create_string( parent_ele, d );
break;
case "number":
ele = ui_create_number( parent_ele, d );
break;
case "progress":
ele = ui_create_progress( parent_ele, d );
break;
default:
ui_error("Unknown UI element type: " + d.type )
}
}
} }
function ws_send( s ) function ws_send( s )
{ {
//console.log(s) //console.log(s)
_ws.send(s+"\0") _ws.send(s+"\0")
} }
function ws_on_msg( jsonMsg ) function ws_on_msg( jsonMsg )
{ {
console.log(jsonMsg) //console.log(jsonMsg)
d = JSON.parse(jsonMsg.data); d = JSON.parse(jsonMsg.data);
switch( d.op ) switch( d.op )
{
case 'create':
for (const ele_type in d.children)
{ {
ui_create( d.parent, ele_type, d.children[ele_type] ) case 'create':
//console.log(`${ele_type}: ${d.value[ele_type]}`); ui_create( d )
break;
}
break;
case 'set_app_id':
ui_set_app_uuId(d)
break;
default: default:
ui_error("Unknown UI operation. " + d.op ) ui_error("Unknown UI operation. " + d.op )
} }
} }
function ws_on_open() function ws_on_open()
{ {
set_app_title( "Connected", "title_connected" ); set_app_title( "Connected", "title_connected" );
_ws.send("init") _ws.send("init")
} }
function ws_on_close() function ws_on_close()
{ {
set_app_title( "Disconnected", "title_disconnected" ); set_app_title( "Disconnected", "title_disconnected" );
} }
function ws_form_url(urlSuffix) function ws_form_url(urlSuffix)
{ {
var pcol; var pcol;
var u = document.URL; var u = document.URL;
pcol = "ws://"; pcol = "ws://";
if (u.substring(0, 4) === "http") if (u.substring(0, 4) === "http")
u = u.substr(7); u = u.substr(7);
u = u.split("/"); u = u.split("/");
return pcol + u[0] + "/" + urlSuffix; return pcol + u[0] + "/" + urlSuffix;
} }
function main() function main()
{ {
rootEle = dom_id_to_ele(_rootJsId); rootEle = dom_id_to_ele(_rootId);
rootEle.uuId = 0; rootEle.uuId = 0;
rootEle.id = _nextEleId; rootEle.id = _nextEleId;
_nextEleId += 1; _nextEleId += 1;
console.log(ws_form_url("")) //console.log(ws_form_url(""))
_ws = new WebSocket(ws_form_url(""),"ui_protocol") _ws = new WebSocket(ws_form_url(""),"ui_protocol")
_ws.onmessage = ws_on_msg _ws.onmessage = ws_on_msg
_ws.onopen = ws_on_open _ws.onopen = ws_on_open
_ws.onclose = ws_on_close; _ws.onclose = ws_on_close;
} }

View File

@ -5,14 +5,14 @@
div: { div: {
jsId: "panelDivId", name: "panelDivId",
class: "myPanelClass", class: "myPanelClass",
title: "My resource based panel", title: "My resource based panel",
children: { children: {
button:{ jsId: myBtn1Id, title:"Push Me" }, button:{ name: myBtn1Id, title:"Push Me" },
check:{ jsId: myCheck1Id, title:"Check Me" }, check:{ name: myCheck1Id, title:"Check Me" },
} }
} }