cwUi.h/cpp, cwUiDecls.h : Added set/getOrderKey(). Added set/get/clearBlob(). Added destroyElement().

This commit is contained in:
kevin 2021-11-14 11:54:52 -05:00
parent e49a0c6935
commit 40465b335c
5 changed files with 367 additions and 83 deletions

View File

@ -2912,14 +2912,62 @@ cw::rc_t cw::io::uiClearEnable( handle_t h, unsigned uuId )
} }
bool cw::io::uiIsEnabled( handle_t h, unsigned uuId ) bool cw::io::uiIsEnabled( handle_t h, unsigned uuId )
{ rc_t rc; {
rc_t rc;
ui::handle_t uiH; ui::handle_t uiH;
if((rc = _handleToUiHandle(h,uiH)) == kOkRC ) if((rc = _handleToUiHandle(h,uiH)) == kOkRC )
return ui::isEnabled(uiH,uuId); return ui::isEnabled(uiH,uuId);
return false; return false;
} }
cw::rc_t cw::io::uiSetOrderKey( handle_t h, unsigned uuId, int orderKey )
{
rc_t rc;
ui::handle_t uiH;
if((rc = _handleToUiHandle(h,uiH)) == kOkRC )
rc = ui::setOrderKey(uiH,uuId,orderKey);
return rc;
}
int cw::io::uiGetOrderKey( handle_t h, unsigned uuId )
{
rc_t rc;
ui::handle_t uiH;
int orderKey = 0;
if((rc = _handleToUiHandle(h,uiH)) == kOkRC )
orderKey = ui::getOrderKey(uiH,uuId);
return orderKey;
}
cw::rc_t cw::io::uiSetBlob( handle_t h, unsigned uuId, const void* blob, unsigned blobByteN )
{
rc_t rc;
ui::handle_t uiH;
if((rc = _handleToUiHandle(h,uiH)) == kOkRC )
rc = ui::setBlob( uiH, uuId, blob, blobByteN );
return rc;
}
const void* cw::io::uiGetBlob( handle_t h, unsigned uuId, unsigned& blobByteN_Ref )
{
ui::handle_t uiH;
if( _handleToUiHandle(h,uiH) == kOkRC )
return ui::getBlob( uiH, uuId, blobByteN_Ref );
blobByteN_Ref = 0;
return nullptr;
}
cw::rc_t cw::io::uiClearBlob( handle_t h, unsigned uuId )
{
rc_t rc;
ui::handle_t uiH;
if((rc = _handleToUiHandle(h,uiH)) == kOkRC )
rc = ui::clearBlob( uiH, uuId );
return rc;
}
cw::rc_t cw::io::uiRegisterAppIdMap( handle_t h, const ui::appIdMap_t* map, unsigned mapN ) cw::rc_t cw::io::uiRegisterAppIdMap( handle_t h, const ui::appIdMap_t* map, unsigned mapN )
{ {
rc_t rc; rc_t rc;
@ -2938,6 +2986,16 @@ cw::rc_t cw::io::uiSendValue( handle_t h, unsigned uuId, bool value )
return rc; return rc;
} }
cw::rc_t cw::io::uiDestroyElement( handle_t h, unsigned uuId )
{
rc_t rc;
ui::handle_t uiH;
if((rc = _handleToUiHandle(h,uiH)) == kOkRC )
rc = ui::destroyElement(uiH, uuId );
return rc;
}
cw::rc_t cw::io::uiSendValue( handle_t h, unsigned uuId, int value ) cw::rc_t cw::io::uiSendValue( handle_t h, unsigned uuId, int value )
{ {
rc_t rc; rc_t rc;

9
cwIo.h
View File

@ -331,10 +331,19 @@ namespace cw
rc_t uiClearEnable( handle_t h, unsigned uuId ); rc_t uiClearEnable( handle_t h, unsigned uuId );
bool uiIsEnabled( handle_t h, unsigned uuId ); bool uiIsEnabled( handle_t h, unsigned uuId );
rc_t uiSetOrderKey( handle_t h, unsigned uuId, int orderKey );
int uiGetOrderKey( handle_t h, unsigned uuId );
rc_t uiSetBlob( handle_t h, unsigned uuId, const void* blob, unsigned blobByteN );
const void* uiGetBlob( handle_t h, unsigned uuId, unsigned& blobByteN_Ref );
rc_t uiClearBlob( handle_t h, unsigned uuId );
// Register parent/child/name app id's // Register parent/child/name app id's
rc_t uiRegisterAppIdMap( handle_t h, const ui::appIdMap_t* map, unsigned mapN ); rc_t uiRegisterAppIdMap( handle_t h, const ui::appIdMap_t* map, unsigned mapN );
rc_t uiDestroyElement( handle_t h, unsigned uuId );
// Send a value from the application to the UI. // Send a value from the application to the UI.
// Set wsSessId to kInvalidId to send to all sessions. // Set wsSessId to kInvalidId to send to all sessions.
rc_t uiSendValue( handle_t h, unsigned uuId, bool value ); rc_t uiSendValue( handle_t h, unsigned uuId, bool value );

356
cwUi.cpp
View File

@ -16,6 +16,7 @@
#define UI_SELECT_LABEL "select" #define UI_SELECT_LABEL "select"
#define UI_VISIBLE_LABEL "visible" #define UI_VISIBLE_LABEL "visible"
#define UI_ENABLE_LABEL "enable" #define UI_ENABLE_LABEL "enable"
#define UI_ORDER_LABEL "order"
namespace cw namespace cw
{ {
@ -61,11 +62,15 @@ namespace cw
struct ele_str* phys_parent; // pointer to actual parent ele - or nullptr if this ele is the root ui ele struct ele_str* phys_parent; // pointer to actual parent ele - or nullptr if this ele is the root ui ele
struct ele_str* logical_parent; // pointer to the nearest ancestor that has a valid appId - this is useful to skip over unnamed containers like rows and columns struct ele_str* logical_parent; // pointer to the nearest ancestor that has a valid appId - this is useful to skip over unnamed containers like rows and columns
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
unsigned chanId; // unsigned chanId; //
char* eleName; // javascript id char* eleName; // javascript id
object_t* attr; // attribute object object_t* attr; // attribute dictionary object
void* blob; // blob[ blobByteN ] user data
unsigned blobByteN; //
bool destroyFl; // used by the deleteElement() algorithm
} ele_t; } ele_t;
typedef struct ui_str typedef struct ui_str
@ -93,24 +98,47 @@ namespace cw
void _print_eles( ui_t* p ) void _print_eles( ui_t* p )
{ {
for(unsigned i=0; i<p->eleN; ++i) for(unsigned i=0; i<p->eleN; ++i)
{ if( p->eleA[i] != nullptr )
ele_t* e = p->eleA[i]; {
printf("%15s u:%i : u:%i a:%i %s\n",e->phys_parent==nullptr?"<null>" : e->phys_parent->eleName,e->phys_parent==nullptr? -1 :e->phys_parent->uuId,e->uuId,e->appId,e->eleName); ele_t* e = p->eleA[i];
} printf("%15s u:%i : u:%i a:%i %s\n",e->phys_parent==nullptr?"<null>" : e->phys_parent->eleName,e->phys_parent==nullptr? -1 :e->phys_parent->uuId,e->uuId,e->appId,e->eleName);
}
}
// Return true if 'parent' is an ancestor of 'ele' (or 'ele' is a child of 'parent')
bool _is_child_of( const ele_t* parent, const ele_t* ele )
{
if( ele == nullptr )
return false;
if( ele->phys_parent == parent || ele->logical_parent == parent )
return true;
// go up the tree - are 'ele' parents children of 'parent'?
return _is_child_of( parent, ele->phys_parent ) || _is_child_of( parent, ele->logical_parent );
}
void _destroy_element( ele_t* e )
{
if( e == nullptr )
return;
if( e->attr != nullptr )
e->attr->free();
mem::release(e->eleName);
mem::release(e->blob);
mem::release(e);
} }
rc_t _destroy( ui_t* p ) rc_t _destroy( ui_t* p )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
// free each element
for(unsigned i=0; i<p->eleN; ++i) for(unsigned i=0; i<p->eleN; ++i)
{ _destroy_element( p->eleA[i] );
if( p->eleA[i]->attr != nullptr )
p->eleA[i]->attr->free();
mem::release(p->eleA[i]->eleName);
mem::release(p->eleA[i]);
}
appIdMapRecd_t* m = p->appIdMap; appIdMapRecd_t* m = p->appIdMap;
while( m!=nullptr ) while( m!=nullptr )
@ -224,8 +252,9 @@ namespace cw
ele_t* _eleNameToEle( ui_t* p, const char* eleName, bool errorFl=true ) ele_t* _eleNameToEle( ui_t* p, const char* eleName, bool errorFl=true )
{ {
for(unsigned i=0; i<p->eleN; ++i) for(unsigned i=0; i<p->eleN; ++i)
if( textCompare(p->eleA[i]->eleName,eleName) == 0 ) if( p->eleA[i] != nullptr )
return p->eleA[i]; if( textCompare(p->eleA[i]->eleName,eleName) == 0 )
return p->eleA[i];
if( errorFl ) if( errorFl )
cwLogError(kInvalidIdRC,"The element with eleName:%s not found.",cwStringNullGuard(eleName)); cwLogError(kInvalidIdRC,"The element with eleName:%s not found.",cwStringNullGuard(eleName));
@ -236,7 +265,7 @@ namespace cw
unsigned _findElementUuId( ui_t* p, unsigned parentUuId, const char* eleName, unsigned chanId=kInvalidId ) unsigned _findElementUuId( ui_t* p, unsigned parentUuId, const char* eleName, unsigned chanId=kInvalidId )
{ {
for(unsigned i=0; i<p->eleN; ++i) for(unsigned i=0; i<p->eleN; ++i)
if( p->eleA[i]->logical_parent != nullptr ) // skip the root if( p->eleA[i] !=nullptr && p->eleA[i]->logical_parent != nullptr ) // skip the root
{ {
if(( parentUuId == kInvalidId || p->eleA[i]->logical_parent->uuId == parentUuId) && if(( parentUuId == kInvalidId || p->eleA[i]->logical_parent->uuId == parentUuId) &&
( chanId == kInvalidId || p->eleA[i]->chanId == chanId) && ( chanId == kInvalidId || p->eleA[i]->chanId == chanId) &&
@ -255,7 +284,7 @@ namespace cw
return kRootUuId; return kRootUuId;
for(unsigned i=0; i<p->eleN; ++i) for(unsigned i=0; i<p->eleN; ++i)
if( p->eleA[i]->logical_parent != nullptr ) //skip the root if( p->eleA[i]!=nullptr && p->eleA[i]->logical_parent != nullptr ) //skip the root
{ {
if( ( parentUuId == kInvalidId || p->eleA[i]->logical_parent->uuId == parentUuId ) && if( ( parentUuId == kInvalidId || p->eleA[i]->logical_parent->uuId == parentUuId ) &&
( chanId == kInvalidId || p->eleA[i]->chanId == chanId ) && ( chanId == kInvalidId || p->eleA[i]->chanId == chanId ) &&
@ -270,7 +299,7 @@ namespace cw
const char* _findEleEleName( 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] != nullptr && p->eleA[i]->uuId == uuId )
return p->eleA[i]->eleName; return p->eleA[i]->eleName;
return nullptr; return nullptr;
@ -314,19 +343,8 @@ namespace cw
bool _has_attribute( ele_t* e, const char* label ) bool _has_attribute( ele_t* e, const char* label )
{ return e->attr->find_child(label) != nullptr; } { return e->attr->find_child(label) != nullptr; }
bool _get_attribute_bool( ele_t* e, const char* label ) template< typename T >
{ rc_t _set_attribute( ele_t* e, const char* label, const T& value )
bool value = false;
const object_t* pair_value;
if((pair_value = e->attr->find(label)) == nullptr )
return false;
pair_value->value(value);
return value;
}
rc_t _set_attribute_bool( ele_t* e, const char* label, bool value )
{ {
object_t* pair_value; object_t* pair_value;
if((pair_value = e->attr->find(label)) == nullptr ) if((pair_value = e->attr->find(label)) == nullptr )
@ -335,9 +353,25 @@ namespace cw
pair_value->set_value(value); pair_value->set_value(value);
return kOkRC; return kOkRC;
} }
template< typename T >
rc_t _get_attribute( ele_t* e, const char* label, T& valueRef )
{
rc_t rc = kOkRC;
const object_t* pair_value;
if((pair_value = e->attr->find(label)) == nullptr )
{
rc = cwLogError(kInvalidIdRC,"Unable to locate the UI element attribute '%s' on uuid:%i.",cwStringNullGuard(label),e->uuId);
goto errLabel;
}
rc = pair_value->value(valueRef);
errLabel:
return rc;
}
// Convert the ele_t 'attr' object into the attributes for a JSON message. // Convert the ele_t 'attr' object into the attributes for a JSON message.
@ -402,7 +436,7 @@ namespace cw
// Note that this requires going through all the nodes and picking out the ones whose // Note that this requires going through all the nodes and picking out the ones whose
// parent uuid matches the current ele's uuid // parent uuid matches the current ele's uuid
for(unsigned i=0; i<p->eleN; ++i) for(unsigned i=0; i<p->eleN; ++i)
if( p->eleA[i]->uuId != kRootUuId && p->eleA[i]->uuId != ele->uuId && p->eleA[i]->phys_parent->uuId == ele->uuId ) if( p->eleA[i] != nullptr && p->eleA[i]->uuId != kRootUuId && p->eleA[i]->uuId != ele->uuId && p->eleA[i]->phys_parent->uuId == ele->uuId )
if((rc = _transmitTree(p,wsSessId,p->eleA[i]))!=kOkRC ) if((rc = _transmitTree(p,wsSessId,p->eleA[i]))!=kOkRC )
break; break;
@ -411,6 +445,15 @@ namespace cw
return rc; return rc;
} }
unsigned _find_and_available_element_slot( ui_t* p )
{
for(unsigned i=0; i<p->eleN; ++i)
if( p->eleA[i] == nullptr )
return i;
return p->eleN;
}
// Create the base element record. The attributes mut be filled in by the calling function. // 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[]. // Note that if 'appId' is kInvalidId then this function will attempt to lookup the appId in p->appIdMap[].
@ -438,7 +481,6 @@ namespace cw
e->phys_parent = parent; e->phys_parent = parent;
e->logical_parent = logical_parent; e->logical_parent = logical_parent;
e->uuId = p->eleN;
e->appId = appId; e->appId = appId;
e->chanId = chanId; e->chanId = chanId;
e->eleName = eleName==nullptr ? nullptr : mem::duplStr(eleName); e->eleName = eleName==nullptr ? nullptr : mem::duplStr(eleName);
@ -457,14 +499,28 @@ namespace cw
e->attr->insert_pair("visible",true); e->attr->insert_pair("visible",true);
e->attr->insert_pair("enable",true); e->attr->insert_pair("enable",true);
if( p->eleN == p->eleAllocN ) // locate the next available element in p->eleA[]
unsigned avail_ele_idx = _find_and_available_element_slot(p);
// if there are no available slots
if( avail_ele_idx == p->eleAllocN )
{ {
p->eleAllocN += 100; p->eleAllocN += 128;
p->eleA = mem::resizeZ<ele_t*>(p->eleA,p->eleAllocN); p->eleA = mem::resizeZ<ele_t*>(p->eleA,p->eleAllocN);
} }
p->eleA[ p->eleN ] = e; assert( avail_ele_idx <= p->eleN && p->eleAllocN > avail_ele_idx );
p->eleN += 1;
// assign the new element to a slot in p->eleA[]
p->eleA[ avail_ele_idx ] = e;
// the ele uuid is the same as it's index in p->eleA[]
e->uuId = avail_ele_idx;
// track the count of elements in p->eleA[]
if( avail_ele_idx == p->eleN )
p->eleN += 1;
// if the given appId was not valid ... // if the given appId was not valid ...
if( appId == kInvalidId && parent != nullptr ) if( appId == kInvalidId && parent != nullptr )
@ -726,7 +782,10 @@ namespace cw
case 'd': case 'd':
if((rc = string_to_number<double>(s,valueRef.u.d)) == kOkRC ) if((rc = string_to_number<double>(s,valueRef.u.d)) == kOkRC )
{
valueRef.tid = kDoubleTId; valueRef.tid = kDoubleTId;
printf("value:%f\n",valueRef.u.d);
}
break; break;
case 's': case 's':
@ -782,6 +841,38 @@ namespace cw
} }
ele_t* _parse_select_msg( ui_t* p, value_t& valueRef, const char* msg )
{
ele_t* ele = nullptr;
unsigned eleUuId = kInvalidId;
unsigned selectFl = 0;
if( msg == nullptr )
{
cwLogWarning("Empty select message received from UI.");
return nullptr;
}
//
if( sscanf(msg, "select %i %i",&eleUuId,&selectFl) != 2 )
{
cwLogError(kSyntaxErrorRC,"Invalid 'select' message from UI: '%s'.", msg );
goto errLabel;
}
// locate the element record
if((ele = _uuIdToEle( p, eleUuId )) == nullptr )
{
cwLogError(kInvalidIdRC,"UI message elment not found.");
goto errLabel;
}
valueRef.u.b = selectFl ? true : false;
errLabel:
return ele;
}
ele_t* _parse_echo_msg( ui_t* p, const char* msg ) ele_t* _parse_echo_msg( ui_t* p, const char* msg )
{ {
unsigned eleUuId = kInvalidId; unsigned eleUuId = kInvalidId;
@ -821,6 +912,7 @@ namespace cw
{ kInitOpId, "init" }, { kInitOpId, "init" },
{ kValueOpId, "value" }, { kValueOpId, "value" },
{ kClickOpId, "click" }, { kClickOpId, "click" },
{ kSelectOpId, "select" },
{ kEchoOpId, "echo" }, { kEchoOpId, "echo" },
{ kIdleOpId, "idle" }, { kIdleOpId, "idle" },
{ kDisconnectOpId, "disconnect" }, { kDisconnectOpId, "disconnect" },
@ -876,17 +968,18 @@ namespace cw
return rc; return rc;
} }
rc_t _setPropertyFlag( handle_t h, const char* propertyStr, unsigned uuId, bool enableFl ) template< typename T >
rc_t _setPropertyValue( handle_t h, const char* propertyStr, unsigned uuId, const T& value )
{ {
ui_t* p = _handleToPtr(h); ui_t* p = _handleToPtr(h);
rc_t rc = kOkRC; rc_t rc = kOkRC;
ele_t* ele = nullptr; ele_t* ele = nullptr;
const char* mFmt = "{ \"op\":\"set\", \"type\":\"%s\", \"uuId\":%i, \"enableFl\":%i }"; const char* mFmt = "{ \"op\":\"set\", \"type\":\"%s\", \"uuId\":%i, \"value\":%i }";
const int mbufN = 256; const int mbufN = 256;
char mbuf[mbufN]; char mbuf[mbufN];
if( snprintf(mbuf,mbufN,mFmt,propertyStr,uuId,enableFl?1:0) >= mbufN-1 ) if( snprintf(mbuf,mbufN,mFmt,propertyStr,uuId,value) >= mbufN-1 )
{ {
rc = cwLogError(kBufTooSmallRC,"The msg buffer is too small."); rc = cwLogError(kBufTooSmallRC,"The msg buffer is too small.");
goto errLabel; goto errLabel;
@ -898,7 +991,7 @@ namespace cw
goto errLabel; goto errLabel;
} }
if((rc = _set_attribute_bool(ele,propertyStr,enableFl)) != kOkRC ) if((rc = _set_attribute(ele,propertyStr,value)) != kOkRC )
{ {
cwLogError(rc,"Property assignment failed."); cwLogError(rc,"Property assignment failed.");
goto errLabel; goto errLabel;
@ -917,6 +1010,10 @@ namespace cw
return rc; return rc;
} }
rc_t _setPropertyFlag( handle_t h, const char* propertyStr, unsigned uuId, bool enableFl )
{
return _setPropertyValue( h, propertyStr,uuId,enableFl ? 1 : 0 );
}
} }
} }
@ -947,7 +1044,7 @@ cw::rc_t cw::ui::create(
ui_t* p = mem::allocZ<ui_t>(); ui_t* p = mem::allocZ<ui_t>();
p->eleAllocN = 100; p->eleAllocN = 128;
p->eleA = mem::allocZ<ele_t*>( p->eleAllocN ); p->eleA = mem::allocZ<ele_t*>( p->eleAllocN );
p->eleN = 0; p->eleN = 0;
p->uiCbFunc = uiCbFunc; p->uiCbFunc = uiCbFunc;
@ -1076,7 +1173,7 @@ cw::rc_t cw::ui::onReceive( handle_t h, unsigned wsSessId, const void* msg, unsi
case kValueOpId: case kValueOpId:
if((ele = _parse_value_msg(p, value, (const char*)msg )) == nullptr ) if((ele = _parse_value_msg(p, value, (const char*)msg )) == nullptr )
cwLogError(kOpFailRC,"UI Value message parse failed."); cwLogError(kOpFailRC,"UI 'value' message parse failed.");
else else
{ {
p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->logical_parent->appId, ele->uuId, ele->appId, ele->chanId, &value ); p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->logical_parent->appId, ele->uuId, ele->appId, ele->chanId, &value );
@ -1086,7 +1183,16 @@ cw::rc_t cw::ui::onReceive( handle_t h, unsigned wsSessId, const void* msg, unsi
case kClickOpId: case kClickOpId:
if((ele = _parse_click_msg(p, (const char*)msg )) == nullptr ) if((ele = _parse_click_msg(p, (const char*)msg )) == nullptr )
cwLogError(kOpFailRC,"UI Value message parse failed."); cwLogError(kOpFailRC,"UI 'click' message parse failed.");
else
{
p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->logical_parent->appId, ele->uuId, ele->appId, ele->chanId, &value );
}
break;
case kSelectOpId:
if((ele = _parse_select_msg(p, value, (const char*)msg )) == nullptr )
cwLogError(kOpFailRC,"UI 'select' message parse failed.");
else else
{ {
p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->logical_parent->appId, ele->uuId, ele->appId, ele->chanId, &value ); p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->logical_parent->appId, ele->uuId, ele->appId, ele->chanId, &value );
@ -1124,7 +1230,7 @@ unsigned cw::ui::parentAndNameToAppId( handle_t h, unsigned parentAppId, const
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]->logical_parent->appId==parentAppId && strcmp(p->eleA[i]->eleName,eleName) == 0 ) if( p->eleA[i] != nullptr && p->eleA[i]->logical_parent->appId==parentAppId && strcmp(p->eleA[i]->eleName,eleName) == 0 )
return p->eleA[i]->appId; return p->eleA[i]->appId;
return kInvalidId; return kInvalidId;
@ -1135,7 +1241,7 @@ unsigned cw::ui::parentAndNameToUuId( handle_t h, unsigned parentAppId, const ch
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]->logical_parent->appId==parentAppId && strcmp(p->eleA[i]->eleName,eleName) == 0 ) if( p->eleA[i] != nullptr && p->eleA[i]->logical_parent->appId==parentAppId && strcmp(p->eleA[i]->eleName,eleName) == 0 )
return p->eleA[i]->uuId; return p->eleA[i]->uuId;
return kInvalidId; return kInvalidId;
@ -1146,10 +1252,11 @@ unsigned cw::ui::parentAndAppIdToUuId( handle_t h, unsigned parentAppId, unsigne
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]->phys_parent==nullptr && parentAppId==kRootAppId) || if( p->eleA[i] != nullptr )
(p->eleA[i]->logical_parent->appId==parentAppId)) if(((p->eleA[i]->phys_parent==nullptr && parentAppId==kRootAppId) ||
&& p->eleA[i]->appId == appId ) (p->eleA[i]->logical_parent->appId==parentAppId))
return p->eleA[i]->uuId; && p->eleA[i]->appId == appId )
return p->eleA[i]->uuId;
return kInvalidId; return kInvalidId;
} }
@ -1198,17 +1305,17 @@ unsigned cw::ui::findElementUuId( handle_t h, unsigned parentUuId, unsigned appI
cw::rc_t cw::ui::createFromObject( handle_t h, const object_t* o, unsigned parentUuId, unsigned chanId, const char* fieldName ) cw::rc_t cw::ui::createFromObject( handle_t h, const object_t* o, unsigned parentUuId, unsigned chanId, const char* cfgFieldName )
{ {
ui_t* p = _handleToPtr(h); ui_t* p = _handleToPtr(h);
rc_t rc = kOkRC; rc_t rc = kOkRC;
//ele_t* parentEle = nullptr; //ele_t* parentEle = nullptr;
if( fieldName != nullptr ) if( cfgFieldName != nullptr )
if((o = o->find(fieldName)) == nullptr ) if((o = o->find(cfgFieldName)) == nullptr )
{ {
rc = cwLogError(kSyntaxErrorRC,"Unable to locate the '%s' sub-configuration.",cwStringNullGuard(fieldName)); rc = cwLogError(kSyntaxErrorRC,"Unable to locate the '%s' sub-configuration.",cwStringNullGuard(cfgFieldName));
goto errLabel; goto errLabel;
} }
@ -1420,7 +1527,7 @@ bool cw::ui::isClickable( handle_t h, unsigned uuId )
bool clickableFl = false; bool clickableFl = false;
if((ele = _uuIdToEle(p,uuId)) != nullptr ) if((ele = _uuIdToEle(p,uuId)) != nullptr )
clickableFl = _get_attribute_bool(ele,UI_CLICKABLE_LABEL); _get_attribute(ele,UI_CLICKABLE_LABEL,clickableFl);
return clickableFl; return clickableFl;
} }
@ -1439,7 +1546,7 @@ bool cw::ui::isSelected( handle_t h, unsigned uuId )
bool selectFl = false; bool selectFl = false;
if((ele = _uuIdToEle(p,uuId)) != nullptr ) if((ele = _uuIdToEle(p,uuId)) != nullptr )
selectFl = _get_attribute_bool(ele,UI_SELECT_LABEL); _get_attribute(ele,UI_SELECT_LABEL,selectFl);
return selectFl; return selectFl;
} }
@ -1457,7 +1564,7 @@ bool cw::ui::isVisible( handle_t h, unsigned uuId )
bool visibleFl = false; bool visibleFl = false;
if((ele = _uuIdToEle(p,uuId)) != nullptr ) if((ele = _uuIdToEle(p,uuId)) != nullptr )
visibleFl = _get_attribute_bool(ele,UI_VISIBLE_LABEL); _get_attribute(ele,UI_VISIBLE_LABEL,visibleFl);
return visibleFl; return visibleFl;
} }
@ -1475,12 +1582,110 @@ bool cw::ui::isEnabled( handle_t h, unsigned uuId )
bool enableFl = false; bool enableFl = false;
if((ele = _uuIdToEle(p,uuId)) != nullptr ) if((ele = _uuIdToEle(p,uuId)) != nullptr )
enableFl = _get_attribute_bool(ele,UI_ENABLE_LABEL); enableFl = _get_attribute(ele,UI_ENABLE_LABEL,enableFl);
return enableFl; return enableFl;
} }
cw::rc_t cw::ui::setOrderKey( handle_t h, unsigned uuId, int orderKey )
{ return _setPropertyValue( h, UI_ORDER_LABEL,uuId, orderKey ); }
int cw::ui::getOrderKey( handle_t h, unsigned uuId )
{
rc_t rc = kOkRC;
ui_t* p = _handleToPtr(h);
ele_t* ele = nullptr;
int orderKey = 0;
if((ele = _uuIdToEle(p,uuId)) != nullptr)
rc = _get_attribute(ele,UI_ORDER_LABEL,orderKey);
return rc;
}
cw::rc_t cw::ui::setBlob( handle_t h, unsigned uuId, const void* blob, unsigned blobByteN )
{
ui_t* p = _handleToPtr(h);
ele_t* ele;
if((ele = _uuIdToEle(p,uuId)) == nullptr )
return cwLogError(kInvalidIdRC,"Invalid uuId (%i) blob not set.",uuId);
ele->blob = (void*)mem::resize<unsigned char>((unsigned char*)ele->blob,blobByteN);
ele->blobByteN = blobByteN;
memcpy(ele->blob,blob,blobByteN);
return kOkRC;
}
const void* cw::ui::getBlob( handle_t h, unsigned uuId, unsigned& blobByteN )
{
ui_t* p = _handleToPtr(h);
ele_t* ele;
if((ele = _uuIdToEle(p,uuId)) != nullptr )
{
blobByteN = ele->blobByteN;
return ele->blob;
}
blobByteN = 0;
return nullptr;
}
cw::rc_t cw::ui::clearBlob( handle_t h, unsigned uuId )
{
ui_t* p = _handleToPtr(h);
ele_t* ele;
if((ele = _uuIdToEle(p,uuId)) == nullptr )
return cwLogError(kInvalidIdRC,"Invalid uuId (%i) blob not cleared.",uuId);
mem::release(ele->blob);
ele->blobByteN = 0;
return kOkRC;
}
cw::rc_t cw::ui::destroyElement( handle_t h, unsigned uuId )
{
rc_t rc = kOkRC;
ui_t* p = _handleToPtr(h);
ele_t* del_ele = nullptr;
const int mbufN = 256;
char mbuf[mbufN];
// locate the element to delete
if((del_ele = _uuIdToEle( p, uuId)) == nullptr )
{
rc = kInvalidIdRC;
goto errLabel;
}
// mark the element for deletion
del_ele->destroyFl = true;
// mark all child elements of 'del_ele' for deletion
for(unsigned i=0; i<p->eleN; ++i)
if( p->eleA[i] != nullptr )
p->eleA[i]->destroyFl = _is_child_of(del_ele, p->eleA[i] );
// release all elements that are marked for deletion
for(unsigned i=0; i<p->eleN; ++i)
if( p->eleA[i] != nullptr && p->eleA[i]->destroyFl )
{
_destroy_element( p->eleA[i] );
p->eleA[i] = nullptr;
}
snprintf(mbuf,mbufN, "{ \"op\":\"destroy\", \"uuId\":%i }", del_ele->uuId );
_websockSend(p,kInvalidId,mbuf);
errLabel:
if(rc != kOkRC )
rc = cwLogError(rc,"Element delete failed.");
return rc;
}
cw::rc_t cw::ui::registerAppIdMap( handle_t h, const appIdMap_t* map, unsigned mapN ) cw::rc_t cw::ui::registerAppIdMap( handle_t h, const appIdMap_t* map, unsigned mapN )
{ {
@ -1530,22 +1735,23 @@ void cw::ui::report( handle_t h )
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] != nullptr )
const ele_t* e = p->eleA[i];
unsigned parUuId = e->phys_parent==NULL ? kInvalidId : e->phys_parent->uuId;
const char* parEleName = e->phys_parent==NULL || e->phys_parent->eleName == NULL ? "" : e->phys_parent->eleName;
printf("uu:%5i app:%5i %20s : parent uu:%5i app:%5i %20s ", e->uuId, e->appId, e->eleName == NULL ? "" : e->eleName, parUuId, e->logical_parent->appId, parEleName );
for(unsigned i=0; i<e->attr->child_count(); ++i)
{ {
e->attr->child_ele(i)->to_string(p->buf,p->bufN); const ele_t* e = p->eleA[i];
printf("%s, ", p->buf );
}
printf("\n");
} unsigned parUuId = e->phys_parent==NULL ? kInvalidId : e->phys_parent->uuId;
const char* parEleName = e->phys_parent==NULL || e->phys_parent->eleName == NULL ? "" : e->phys_parent->eleName;
printf("uu:%5i app:%5i %20s : parent uu:%5i app:%5i %20s ", e->uuId, e->appId, e->eleName == NULL ? "" : e->eleName, parUuId, e->logical_parent->appId, parEleName );
for(unsigned i=0; i<e->attr->child_count(); ++i)
{
e->attr->child_ele(i)->to_string(p->buf,p->bufN);
printf("%s, ", p->buf );
}
printf("\n");
}
} }

12
cwUi.h
View File

@ -62,7 +62,7 @@ namespace cw
// Create multiple UI elements from an object_t representation. // Create multiple UI elements from an object_t representation.
// The channel id of all elements created from the object will be assigned 'chanId'. // The channel id of all elements created from the object will be assigned 'chanId'.
// The 'fieldName' string identifies // The 'fieldName' string identifies
rc_t createFromObject( handle_t h, const object_t* o, unsigned parentUuId=kInvalidId, unsigned chanId=kInvalidId, const char* fieldName=nullptr); rc_t createFromObject( handle_t h, const object_t* o, unsigned parentUuId=kInvalidId, unsigned chanId=kInvalidId, const char* cfgFieldName=nullptr);
rc_t createFromFile( handle_t h, const char* fn, unsigned parentUuId=kInvalidId, unsigned chanId=kInvalidId); rc_t createFromFile( handle_t h, const char* fn, unsigned parentUuId=kInvalidId, unsigned chanId=kInvalidId);
rc_t createFromText( handle_t h, const char* text, unsigned parentUuId=kInvalidId, unsigned chanId=kInvalidId); rc_t createFromText( handle_t h, const char* text, unsigned parentUuId=kInvalidId, unsigned chanId=kInvalidId);
@ -135,9 +135,19 @@ namespace cw
rc_t clearEnable( handle_t h, unsigned uuId ); rc_t clearEnable( handle_t h, unsigned uuId );
bool isEnabled( handle_t h, unsigned uuId ); bool isEnabled( handle_t h, unsigned uuId );
rc_t setOrderKey( handle_t h, unsigned uuId, int orderKey );
int getOrderKey( handle_t h, unsigned uuId );
rc_t setBlob( handle_t h, unsigned uuId, const void* blob, unsigned blobByteN );
const void* getBlob( handle_t h, unsigned uuId, unsigned& blobByteN_Ref );
rc_t clearBlob( handle_t h, unsigned uuId );
// Register parent/child/name app id's // Register parent/child/name app id's
rc_t registerAppIdMap( handle_t h, const appIdMap_t* map, unsigned mapN ); rc_t registerAppIdMap( handle_t h, const appIdMap_t* map, unsigned mapN );
// Release an element an all of it's children.
rc_t destroyElement( handle_t h, unsigned uuId );
// Send a value from the application to the UI via a JSON messages. // Send a value from the application to the UI via a JSON messages.
// Set wsSessId to kInvalidId to send to all sessions. // Set wsSessId to kInvalidId to send to all sessions.
rc_t sendValueBool( handle_t h, unsigned uuId, bool value ); rc_t sendValueBool( handle_t h, unsigned uuId, bool value );

View File

@ -18,6 +18,7 @@ namespace cw
kInitOpId, // A remote user interface instance was created and is available. It needs to be updated with the current state of the UI from the server. kInitOpId, // A remote user interface instance was created and is available. It needs to be updated with the current state of the UI from the server.
kValueOpId, // The value of a remote user interface control changed. Send this value to the application engine. kValueOpId, // The value of a remote user interface control changed. Send this value to the application engine.
kClickOpId, // A element on a remote user interface was clicked. kClickOpId, // A element on a remote user interface was clicked.
kSelectOpId, // An element on a remote user interface was is 'selected' or 'deselected'.
kEchoOpId, // A remote user interface is requesting an application engine value. The the current value of a ui element must be sent to the remote UI. kEchoOpId, // A remote user interface is requesting an application engine value. The the current value of a ui element must be sent to the remote UI.
kIdleOpId, // The application (UI server) is idle and waiting for the next event from a remote UI. kIdleOpId, // The application (UI server) is idle and waiting for the next event from a remote UI.
kDisconnectOpId // A reemot user interface was disconnected. kDisconnectOpId // A reemot user interface was disconnected.