cwUi.h/cpp : Removed use of 'wsSessId' from 'createXXX()' calls, and added 'chanId' to 'createXXX()' calls.

Added 'click' event, 'clickable' and 'select' properties and associated setters/getters.
This commit is contained in:
kevin 2021-11-03 11:03:30 -04:00
parent 5ab42df103
commit dce46bd419
7 changed files with 422 additions and 215 deletions

420
cwUi.cpp
View File

@ -12,12 +12,13 @@
#include "cwUi.h"
#define UI_CLICKABLE_LABEL "clickable"
#define UI_SELECT_LABEL "select"
namespace cw
{
namespace ui
{
typedef struct appIdMapRecd_str
{
@ -33,9 +34,9 @@ namespace cw
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 appId; // application assigned id - application assigned id
unsigned chanId; //
char* eleName; // javascript id
object_t* attr; // attribute object
} ele_t;
typedef struct ui_str
@ -47,11 +48,11 @@ namespace cw
void* uiCbArg; // app. cb func arg.
sendCallback_t sendCbFunc;
void* sendCbArg;
appIdMapRecd_t* appIdMap; // map of application parent/child/js id's
char* buf; // buf[bufN] output message formatting buffer
unsigned bufN; //
appIdMapRecd_t* appIdMap; // map of application parent/child/js id's
char* buf; // buf[bufN] output message formatting buffer
unsigned bufN; //
unsigned* sessA; // sessA[ sessN ] array of wsSessId's
unsigned* sessA; // sessA[ sessN ] array of wsSessId's
unsigned sessN;
unsigned sessAllocN;
@ -182,33 +183,6 @@ namespace cw
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 )
cwLogError(kInvalidIdRC,"The element with parent uuid:%i and eleName:%s is not found.",parentUuId,eleName);
return nullptr;
}
*/
unsigned _findElementUuId( ui_t* p, const char* eleName )
{
for(unsigned i=0; i<p->eleN; ++i)
@ -259,6 +233,47 @@ namespace cw
}
// terminating condition for format_attributes()
void _create_attributes( ele_t* e )
{ }
template<typename T, typename... ARGS>
void _create_attributes(ele_t* e, const char* label, T value, ARGS&&... args)
{
e->attr->insert_pair(label,value);
_create_attributes(e,std::forward<ARGS>(args)...);
}
bool _has_attribute( ele_t* e, const char* label )
{ return e->attr->find_child(label) != nullptr; }
bool _get_attribute_bool( ele_t* e, const char* label )
{
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;
if((pair_value = e->attr->find(label)) == nullptr )
_create_attributes(e,label,value);
else
pair_value->set_value(value);
return kOkRC;
}
// Convert the ele_t 'attr' object into the attributes for a JSON message.
unsigned _format_attributes( char* buf, unsigned n, unsigned i, ele_t* ele )
{
@ -333,13 +348,14 @@ namespace cw
// 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* _createBaseEle( ui_t* p, ele_t* parent, unsigned appId, unsigned chanId, const char* eleName, const char* eleTypeStr=nullptr, const char* eleClass=nullptr, const char* eleTitle=nullptr )
{
ele_t* e = mem::allocZ<ele_t>();
e->parent = parent;
e->uuId = p->eleN;
e->appId = appId;
e->chanId = chanId;
e->eleName = eleName==nullptr ? nullptr : mem::duplStr(eleName);
e->attr = newDictObject();
@ -389,21 +405,9 @@ namespace cw
}
// terminating condition for format_attributes()
void create_attributes( ele_t* e )
{ }
template<typename T, typename... ARGS>
void create_attributes(ele_t* e, const char* label, T value, ARGS&&... args)
{
e->attr->insert_pair(label,value);
create_attributes(e,std::forward<ARGS>(args)...);
}
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 )
rc_t _createOneEle( ui_t* p, unsigned& uuIdRef, const char* eleTypeStr, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, ARGS&&... args )
{
rc_t rc = kOkRC;
ele_t* newEle = nullptr;
@ -419,10 +423,10 @@ namespace cw
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 );
newEle = _createBaseEle(p, parentEle, appId, chanId, eleName, eleTypeStr, clas, title );
// create the attributes
create_attributes(newEle, std::forward<ARGS>(args)...);
_create_attributes(newEle, std::forward<ARGS>(args)...);
uuIdRef = newEle->uuId;
@ -448,9 +452,9 @@ namespace cw
return divAliasFl;
}
rc_t _createElementsFromChildList( ui_t* p, const object_t* po, unsigned wsSessId, ele_t* parentEle );
rc_t _createElementsFromChildList( ui_t* p, const object_t* po, unsigned wsSessId, ele_t* parentEle, unsigned chanId );
rc_t _createEleFromRsrsc( ui_t* p, ele_t* parentEle, const char* eleType, const object_t* srcObj, unsigned wsSessId )
rc_t _createEleFromRsrsc( ui_t* p, ele_t* parentEle, const char* eleType, unsigned chanId, const object_t* srcObj, unsigned wsSessId )
{
rc_t rc = kOkRC;
object_t* co = nullptr;
@ -463,7 +467,7 @@ namespace cw
return cwLogError(kSyntaxErrorRC,"All ui element resource records must be dictionaries.");
// if this object has a 'children' list then unlink it and save it for later
if((co = o->find("children", kNoRecurseFl | kOptionalFl)) != nullptr )
if((co = o->find("children", kOptionalFl)) != nullptr )
{
co = co->parent;
co->unlink();
@ -472,7 +476,7 @@ namespace cw
divAliasFl = _is_div_type(eleType);
// get the ui ele name
if((rc = o->get("name",eleName, cw::kNoRecurseFl | cw::kOptionalFl)) != kOkRC )
if((rc = o->get("name",eleName, cw::kOptionalFl)) != kOkRC )
{
// div's and titles don't need a 'name'
if( rc == kLabelNotFoundRC && (divAliasFl || textCompare(eleType,"label")==0) )
@ -486,7 +490,7 @@ namespace cw
}
// get or create the ele record to associate with this ele
if((ele = _createBaseEle(p, parentEle, kInvalidId, eleName, eleType, nullptr, nullptr)) == nullptr )
if((ele = _createBaseEle(p, parentEle, kInvalidId, chanId, eleName, eleType, nullptr, nullptr)) == nullptr )
{
rc = cwLogError(kOpFailRC,"The local element '%s' could not be created.",cwStringNullGuard(eleName));
goto errLabel;
@ -495,17 +499,27 @@ namespace cw
if( !divAliasFl )
{
unsigned childN = o->child_count();
unsigned child_idx = 0;
// transfer the attributes of this resource object to ele->attr
for(unsigned i=0; i<o->child_count(); ++i)
for(unsigned i=0; i<childN; ++i)
{
object_t* child = o->child_ele(i);
object_t* child = o->child_ele(child_idx);
const char* pair_label = child->pair_label();
//if( textCompare(eleType,"list")==0 )
// printf("%i list: %s %i\n",i,pair_label,o->child_count());
if( textCompare(pair_label,"name") != 0 && _is_div_type(pair_label)==false )
{
child->unlink();
ele->attr->append_child(child);
}
}
else
{
child_idx += 1;
}
}
}
@ -517,7 +531,7 @@ namespace cw
// Note that 'div's need not have an explicit 'children' node.
// Any child node of a 'div' with a dictionary as a value is a child control.
const object_t* childL = co!=nullptr ? co->pair_value() : srcObj;
rc = _createElementsFromChildList(p, childL, wsSessId, ele );
rc = _createElementsFromChildList(p, childL, wsSessId, ele, chanId );
}
errLabel:
@ -534,7 +548,7 @@ namespace cw
// 'od' is an object dictionary where each pair in the dictionary has
// the form: 'eleType':{ <object> }
rc_t _createElementsFromChildList( ui_t* p, const object_t* po, unsigned wsSessId, ele_t* parentEle )
rc_t _createElementsFromChildList( ui_t* p, const object_t* po, unsigned wsSessId, ele_t* parentEle, unsigned chanId )
{
rc_t rc = kOkRC;
@ -553,7 +567,7 @@ namespace cw
// skip pairs whose value is not a dict
if( o->pair_value()->is_dict() )
{
if((rc = _createEleFromRsrsc(p, parentEle, o->pair_label(), o->pair_value(), wsSessId )) != kOkRC )
if((rc = _createEleFromRsrsc(p, parentEle, o->pair_label(), chanId, o->pair_value(), wsSessId )) != kOkRC )
return rc;
}
}
@ -563,7 +577,7 @@ namespace cw
// This functions assumes that the cfg object 'o' contains a field named: 'parent'
// which contains the element name of the parent node.
rc_t _createFromObj( ui_t* p, const object_t* o, unsigned wsSessId, unsigned parentUuId )
rc_t _createFromObj( ui_t* p, const object_t* o, unsigned wsSessId, unsigned parentUuId, unsigned chanId )
{
rc_t rc = kOkRC;
const object_t* po = nullptr;
@ -573,7 +587,7 @@ namespace cw
if( parentUuId == kInvalidId )
{
// locate the the 'parent' ele name value object
if((po = o->find("parent",kNoRecurseFl | kOptionalFl)) == nullptr )
if((po = o->find("parent",kOptionalFl)) == nullptr )
return cwLogError(kSyntaxErrorRC,"UI resources must have a root 'parent' value.");
// get the parent element name
@ -595,7 +609,7 @@ namespace cw
return cwLogError(kSyntaxErrorRC,"A parent UI element named '%s' could not be found.",cwStringNullGuard(eleName));
rc = _createElementsFromChildList( p, o, wsSessId, parentEle );
rc = _createElementsFromChildList( p, o, wsSessId, parentEle, chanId );
return rc;
}
@ -614,7 +628,7 @@ namespace cw
if( msg == nullptr )
{
cwLogWarning("Empty message received from UI.");
cwLogWarning("Empty 'value' message received from UI.");
return nullptr;
}
@ -623,7 +637,7 @@ namespace cw
if( s == nullptr || sscanf(msg, "value %i %c ",&eleUuId,&argType) != 2 )
{
cwLogError(kSyntaxErrorRC,"Invalid message from UI: '%s'.", msg );
cwLogError(kSyntaxErrorRC,"Invalid 'value' message from UI: '%s'.", msg );
goto errLabel;
}
@ -680,6 +694,37 @@ namespace cw
return ele;
}
ele_t* _parse_click_msg( ui_t* p, const char* msg )
{
ele_t* ele = nullptr;
unsigned eleUuId = kInvalidId;
if( msg == nullptr )
{
cwLogWarning("Empty click message received from UI.");
return nullptr;
}
//
if( sscanf(msg, "click %i ",&eleUuId) != 1 )
{
cwLogError(kSyntaxErrorRC,"Invalid 'click' 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;
}
errLabel:
return ele;
}
ele_t* _parse_echo_msg( ui_t* p, const char* msg )
{
unsigned eleUuId = kInvalidId;
@ -718,6 +763,7 @@ namespace cw
{ kConnectOpId, "connect" },
{ kInitOpId, "init" },
{ kValueOpId, "value" },
{ kClickOpId, "click" },
{ kEchoOpId, "echo" },
{ kIdleOpId, "idle" },
{ kDisconnectOpId, "disconnect" },
@ -732,13 +778,13 @@ namespace cw
}
template< typename T >
rc_t _sendValue( ui_t* p, unsigned wsSessId, unsigned uuId, const char* vFmt, const T& value, int vbufN=32 )
rc_t _sendValue( ui_t* p, unsigned wsSessId, unsigned uuId, const char* vFmt, const T& value, const char* opStr="value", int vbufN=32 )
{
rc_t rc = kOkRC;
if( p->sendCbFunc != nullptr )
{
const char* mFmt = "{ \"op\":\"value\", \"uuId\":%i, \"value\":%s }";
const char* mFmt = "{ \"op\":\"%s\", \"uuId\":%i, \"value\":%s }";
const int mbufN = 128;
char vbuf[vbufN];
char mbuf[mbufN];
@ -746,7 +792,7 @@ namespace cw
if( snprintf(vbuf,vbufN,vFmt,value) >= vbufN-1 )
return cwLogError(kBufTooSmallRC,"The value msg buffer is too small.");
if( snprintf(mbuf,mbufN,mFmt,uuId,vbuf) >= mbufN-1 )
if( snprintf(mbuf,mbufN,mFmt,opStr,uuId,vbuf) >= mbufN-1 )
return cwLogError(kBufTooSmallRC,"The msg buffer is too small.");
//p->sendCbFunc(p->sendCbArg,wsSessId,mbuf,strlen(mbuf));
@ -772,6 +818,48 @@ namespace cw
errLabel:
return rc;
}
rc_t _setPropertyFlag( handle_t h, const char* propertyStr, unsigned uuId, bool enableFl )
{
ui_t* p = _handleToPtr(h);
rc_t rc = kOkRC;
ele_t* ele = nullptr;
const char* mFmt = "{ \"op\":\"set\", \"type\":\"%s\", \"uuId\":%i, \"enableFl\":%i }";
const int mbufN = 256;
char mbuf[mbufN];
if( snprintf(mbuf,mbufN,mFmt,propertyStr,uuId,enableFl?1:0) >= mbufN-1 )
{
rc = cwLogError(kBufTooSmallRC,"The msg buffer is too small.");
goto errLabel;
}
if((ele = _uuIdToEle(p,uuId)) == nullptr )
{
rc = kInvalidIdRC;
goto errLabel;
}
if((rc = _set_attribute_bool(ele,propertyStr,enableFl)) != kOkRC )
{
cwLogError(rc,"Property assignment failed.");
goto errLabel;
}
if((rc = _websockSend(p,kInvalidId,mbuf)) != kOkRC )
{
cwLogError(rc,"'%s' msg transmit failed.",propertyStr);
goto errLabel;
}
errLabel:
if( rc != kOkRC )
rc = cwLogError(rc,"Set '%s' failed.",propertyStr);
return rc;
}
}
}
@ -813,7 +901,7 @@ cw::rc_t cw::ui::create(
p->bufN = fmtBufByteN;
// create the root element
if((ele = _createBaseEle(p, nullptr, kRootAppId, "uiDivId" )) == nullptr || ele->uuId != kRootUuId )
if((ele = _createBaseEle(p, nullptr, kRootAppId, kInvalidId, "uiDivId" )) == nullptr || ele->uuId != kRootUuId )
{
cwLogError(kOpFailRC,"The UI root element creation failed.");
goto errLabel;
@ -824,7 +912,7 @@ cw::rc_t cw::ui::create(
goto errLabel;
if( uiRsrc != nullptr )
if((rc = _createFromObj( p, uiRsrc, kInvalidId, kRootUuId )) != kOkRC )
if((rc = _createFromObj( p, uiRsrc, kInvalidId, kRootUuId, kInvalidId )) != kOkRC )
rc = cwLogError(rc,"Create from UI resource failed.");
@ -886,7 +974,7 @@ cw::rc_t cw::ui::onConnect( handle_t h, unsigned wsSessId )
// append the new session id
p->sessA[p->sessN++] = wsSessId;
p->uiCbFunc( p->uiCbArg, wsSessId, kConnectOpId, kInvalidId, kInvalidId, kInvalidId, nullptr );
p->uiCbFunc( p->uiCbArg, wsSessId, kConnectOpId, kInvalidId, kInvalidId, kInvalidId, kInvalidId, nullptr );
return kOkRC;
}
@ -894,7 +982,7 @@ cw::rc_t cw::ui::onDisconnect( handle_t h, unsigned wsSessId )
{
ui_t* p = _handleToPtr(h);
p->uiCbFunc( p->uiCbArg, wsSessId, kDisconnectOpId, kInvalidId, kInvalidId, kInvalidId, nullptr );
p->uiCbFunc( p->uiCbArg, wsSessId, kDisconnectOpId, kInvalidId, kInvalidId, kInvalidId, kInvalidId, nullptr );
// erase the disconnected session id by shrinking the array
for(unsigned i=0; i<p->sessN; ++i)
@ -926,7 +1014,7 @@ cw::rc_t cw::ui::onReceive( handle_t h, unsigned wsSessId, const void* msg, unsi
_onNewRemoteUi( p, wsSessId );
// Pass on the 'init' msg to the app.
p->uiCbFunc( p->uiCbArg, wsSessId, opId, kInvalidId, kInvalidId, kInvalidId, nullptr );
p->uiCbFunc( p->uiCbArg, wsSessId, opId, kInvalidId, kInvalidId, kInvalidId, kInvalidId, nullptr );
break;
case kValueOpId:
@ -936,11 +1024,22 @@ cw::rc_t cw::ui::onReceive( handle_t h, unsigned wsSessId, const void* msg, unsi
{
unsigned parentEleAppId = ele->parent == nullptr ? kInvalidId : ele->parent->appId;
p->uiCbFunc( p->uiCbArg, wsSessId, opId, parentEleAppId, ele->uuId, ele->appId, &value );
p->uiCbFunc( p->uiCbArg, wsSessId, opId, parentEleAppId, ele->uuId, ele->appId, ele->chanId, &value );
}
break;
case kClickOpId:
if((ele = _parse_click_msg(p, (const char*)msg )) == nullptr )
cwLogError(kOpFailRC,"UI Value message parse failed.");
else
{
unsigned parentEleAppId = ele->parent == nullptr ? kInvalidId : ele->parent->appId;
p->uiCbFunc( p->uiCbArg, wsSessId, opId, parentEleAppId, ele->uuId, ele->appId, ele->chanId, &value );
}
break;
case kEchoOpId:
if((ele = _parse_echo_msg(p,(const char*)msg)) == nullptr )
cwLogError(kOpFailRC,"UI Echo message parse failed.");
@ -948,12 +1047,12 @@ cw::rc_t cw::ui::onReceive( handle_t h, unsigned wsSessId, const void* msg, unsi
{
unsigned parentEleAppId = ele->parent == nullptr ? kInvalidId : ele->parent->appId;
p->uiCbFunc( p->uiCbArg, wsSessId, opId, parentEleAppId, ele->uuId, ele->appId, nullptr );
p->uiCbFunc( p->uiCbArg, wsSessId, opId, parentEleAppId, ele->uuId, ele->appId, ele->chanId,nullptr );
}
break;
case kIdleOpId:
p->uiCbFunc( p->uiCbArg, kInvalidId, opId, kInvalidId, kInvalidId, kInvalidId, nullptr );
p->uiCbFunc( p->uiCbArg, kInvalidId, opId, kInvalidId, kInvalidId, kInvalidId, kInvalidId, nullptr );
break;
case kInvalidOpId:
@ -1034,21 +1133,21 @@ 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 )
cw::rc_t cw::ui::createFromObject( handle_t h, const object_t* o, unsigned parentUuId, unsigned chanId, const char* fieldName )
{
ui_t* p = _handleToPtr(h);
rc_t rc = kOkRC;
//ele_t* parentEle = nullptr;
if( eleName != nullptr )
if((o = o->find(eleName)) == nullptr )
if( fieldName != nullptr )
if((o = o->find(fieldName)) == nullptr )
{
rc = cwLogError(kSyntaxErrorRC,"Unable to locate the '%s' sub-configuration.",cwStringNullGuard(eleName));
rc = cwLogError(kSyntaxErrorRC,"Unable to locate the '%s' sub-configuration.",cwStringNullGuard(fieldName));
goto errLabel;
}
if((rc = _createFromObj( p, o, wsSessId, parentUuId )) != kOkRC )
if((rc = _createFromObj( p, o, kInvalidId, parentUuId, chanId )) != kOkRC )
goto errLabel;
errLabel:
@ -1059,7 +1158,7 @@ cw::rc_t cw::ui::createFromObject( handle_t h, const object_t* o, unsigned wsS
}
cw::rc_t cw::ui::createFromFile( handle_t h, const char* fn, unsigned wsSessId, unsigned parentUuId)
cw::rc_t cw::ui::createFromFile( handle_t h, const char* fn, unsigned parentUuId, unsigned chanId)
{
ui_t* p = _handleToPtr(h);
rc_t rc = kOkRC;
@ -1068,7 +1167,7 @@ cw::rc_t cw::ui::createFromFile( handle_t h, const char* fn, unsigned wsSessId
if((rc = objectFromFile( fn, o )) != kOkRC )
goto errLabel;
if((rc = _createFromObj( p, o, wsSessId, parentUuId )) != kOkRC )
if((rc = _createFromObj( p, o, kInvalidId, parentUuId, chanId )) != kOkRC )
goto errLabel;
errLabel:
@ -1081,7 +1180,7 @@ cw::rc_t cw::ui::createFromFile( handle_t h, const char* fn, unsigned wsSessId
return rc;
}
cw::rc_t cw::ui::createFromText( handle_t h, const char* text, unsigned wsSessId, unsigned parentUuId)
cw::rc_t cw::ui::createFromText( handle_t h, const char* text, unsigned parentUuId, unsigned chanId )
{
ui_t* p = _handleToPtr(h);
rc_t rc = kOkRC;
@ -1090,7 +1189,7 @@ cw::rc_t cw::ui::createFromText( handle_t h, const char* text, unsigned wsSessId
if((rc = objectFromString( text, o )) != kOkRC )
goto errLabel;
if((rc = _createFromObj( p, o, wsSessId, parentUuId )) != kOkRC )
if((rc = _createFromObj( p, o, kInvalidId, parentUuId, chanId )) != kOkRC )
goto errLabel;
errLabel:
@ -1103,93 +1202,93 @@ cw::rc_t cw::ui::createFromText( handle_t h, const char* text, unsigned wsSessId
return rc;
}
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, eleName, appId, clas, title ); }
cw::rc_t cw::ui::createDiv( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "div", kInvalidId, parentUuId, eleName, appId, chanId, clas, title ); }
cw::rc_t cw::ui::createLabel( 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, "label", wsSessId, parentUuId, eleName, appId, clas, title ); }
cw::rc_t cw::ui::createLabel( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "label", kInvalidId, parentUuId, eleName, appId, chanId, clas, 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, eleName, appId, clas, title ); }
cw::rc_t cw::ui::createButton( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "button", kInvalidId, parentUuId, eleName, appId, chanId, clas, title ); }
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 )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "check", wsSessId, parentUuId, eleName, appId, clas, title ); }
cw::rc_t cw::ui::createCheck( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "check", kInvalidId, parentUuId, eleName, appId, chanId, clas, title ); }
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, eleName, appId, clas, title, "value", value ); }
cw::rc_t cw::ui::createCheck( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, bool value )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "check", kInvalidId, parentUuId, eleName, appId, chanId, clas, title, "value", value ); }
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, eleName, appId, clas, title ); }
cw::rc_t cw::ui::createSelect( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "select", kInvalidId, parentUuId, eleName, appId, chanId, clas, 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, eleName, appId, clas, title ); }
cw::rc_t cw::ui::createOption( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "option", kInvalidId, parentUuId, eleName, appId, chanId, clas, title ); }
cw::rc_t cw::ui::createStr( 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, "string", wsSessId, parentUuId, eleName, appId, clas, title ); }
cw::rc_t cw::ui::createStr( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "string", kInvalidId, parentUuId, eleName, appId, chanId, clas, title ); }
cw::rc_t cw::ui::createStr( 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, eleName, appId, clas, title, "value", value ); }
cw::rc_t cw::ui::createStr( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, const char* value )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "string", kInvalidId, parentUuId, eleName, appId, chanId, clas, title, "value", value ); }
cw::rc_t cw::ui::createNumbDisplay( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, unsigned decpl )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "numb_disp", wsSessId, parentUuId, eleName, appId, clas, title, "decpl", decpl ); }
cw::rc_t cw::ui::createNumbDisplay( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, unsigned decpl )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "numb_disp", kInvalidId, parentUuId, eleName, appId, chanId, clas, title, "decpl", decpl ); }
cw::rc_t cw::ui::createNumbDisplay( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, unsigned decpl, double value )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "numb_disp", wsSessId, parentUuId, eleName, appId, clas, title, "decpl", decpl, "value", value ); }
cw::rc_t cw::ui::createNumbDisplay( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, unsigned decpl, double value )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "numb_disp", kInvalidId, parentUuId, eleName, appId, chanId, clas, title, "decpl", decpl, "value", value ); }
cw::rc_t cw::ui::createNumb( 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 stepValue, unsigned decpl )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "number", wsSessId, parentUuId, eleName, appId, clas, title, "min", minValue, "max", maxValue, "step", stepValue, "decpl", decpl ); }
cw::rc_t cw::ui::createNumb( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, double minValue, double maxValue, double stepValue, unsigned decpl )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "number", kInvalidId, parentUuId, eleName, appId, chanId, clas, title, "min", minValue, "max", maxValue, "step", stepValue, "decpl", decpl ); }
cw::rc_t cw::ui::createNumb( 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 stepValue, unsigned decpl, double value )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "number", wsSessId, parentUuId, eleName, appId, clas, title, "min", minValue, "max", maxValue, "step", stepValue, "decpl", decpl, "value", value ); }
cw::rc_t cw::ui::createNumb( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, double minValue, double maxValue, double stepValue, unsigned decpl, double value )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "number", kInvalidId, parentUuId, eleName, appId, chanId, clas, title, "min", minValue, "max", maxValue, "step", stepValue, "decpl", decpl, "value", value ); }
cw::rc_t cw::ui::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 )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "progress", wsSessId, parentUuId, eleName, appId, clas, title, "min", minValue, "max", maxValue ); }
cw::rc_t cw::ui::createProg( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, double minValue, double maxValue )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "progress", kInvalidId, parentUuId, eleName, appId, chanId, clas, title, "min", minValue, "max", maxValue ); }
cw::rc_t cw::ui::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 )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "progress", wsSessId, parentUuId, eleName, appId, clas, title, "value", value, "min", minValue, "max", maxValue ); }
cw::rc_t cw::ui::createProg( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, double minValue, double maxValue, double value )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "progress", kInvalidId, parentUuId, eleName, appId, chanId, clas, title, "value", value, "min", minValue, "max", maxValue ); }
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::createLog( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "log", kInvalidId, parentUuId, eleName, appId, chanId, 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::createList( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title )
{ return _createOneEle( _handleToPtr(h), uuIdRef, "list", kInvalidId, parentUuId, eleName, appId, chanId, 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 )
cw::rc_t cw::ui::setNumbRange( handle_t h, unsigned uuId, double minValue, double maxValue, double stepValue, unsigned decPl, double value )
{
rc_t rc = kOkRC;
ui_t* p = _handleToPtr(h);
const char* mFmt = "{ \"op\":\"set\", \"uuId\":%i, \"min\":%f, \"max\":%f, \"step\":%f, \"decpl\":%i, \"value\":%f }";
const char* mFmt = "{ \"op\":\"set\", \"type\":\"number_range\", \"uuId\":%i, \"min\":%f, \"max\":%f, \"step\":%f, \"decpl\":%i, \"value\":%f }";
const int mbufN = 256;
char mbuf[mbufN];
if( snprintf(mbuf,mbufN,mFmt,uuId,minValue,maxValue,stepValue,decPl,value) >= mbufN-1 )
return cwLogError(kBufTooSmallRC,"The msg buffer is too small.");
rc = _websockSend(p,wsSessId,mbuf);
rc = _websockSend(p,kInvalidId,mbuf);
return rc;
}
cw::rc_t cw::ui::setProgRange( handle_t h, unsigned wsSessId, unsigned uuId, double minValue, double maxValue, double value )
cw::rc_t cw::ui::setProgRange( handle_t h, unsigned uuId, double minValue, double maxValue, double value )
{
rc_t rc = kOkRC;
ui_t* p = _handleToPtr(h);
const char* mFmt = "{ \"op\":\"set\", \"uuId\":%i, \"min\":%f, \"max\":%f, \"value\":%f }";
const char* mFmt = "{ \"op\":\"set\", \"type\":\"progress_range\", \"uuId\":%i, \"min\":%f, \"max\":%f, \"value\":%f }";
const int mbufN = 256;
char mbuf[mbufN];
if( snprintf(mbuf,mbufN,mFmt,uuId,minValue,maxValue,value) >= mbufN-1 )
return cwLogError(kBufTooSmallRC,"The msg buffer is too small.");
rc = _websockSend(p,wsSessId,mbuf);
rc = _websockSend(p,kInvalidId,mbuf);
return rc;
}
cw::rc_t cw::ui::setLogLine( handle_t h, unsigned wsSessId, unsigned uuId, const char* text )
cw::rc_t cw::ui::setLogLine( handle_t h, unsigned uuId, const char* text )
{
rc_t rc = kOkRC;
@ -1200,7 +1299,7 @@ cw::rc_t cw::ui::setLogLine( handle_t h, unsigned wsSessId, unsigned uuId, con
++n;
if( n == 0 )
rc = sendValueString(h,wsSessId,uuId,text);
rc = sendValueString(h,uuId,text);
else
{
int sn = textLength(text);
@ -1236,13 +1335,50 @@ cw::rc_t cw::ui::setLogLine( handle_t h, unsigned wsSessId, unsigned uuId, con
printf("%s %s\n",text,s);
rc = sendValueString(h,wsSessId,uuId,s);
rc = sendValueString(h,uuId,s);
}
return rc;
}
cw::rc_t cw::ui::setClickable( handle_t h, unsigned uuId, bool clickableFl )
{ return _setPropertyFlag( h, UI_CLICKABLE_LABEL, uuId, clickableFl ); }
cw::rc_t cw::ui::clearClickable( handle_t h, unsigned uuId )
{ return setClickable(h,uuId,false); }
bool cw::ui::isClickable( handle_t h, unsigned uuId )
{
ui_t* p = _handleToPtr(h);
ele_t* ele = nullptr;
bool clickableFl = false;
if((ele = _uuIdToEle(p,uuId)) != nullptr )
clickableFl = _get_attribute_bool(ele,UI_CLICKABLE_LABEL);
return clickableFl;
}
cw::rc_t cw::ui::setSelect( handle_t h, unsigned uuId, bool enableFl )
{ return _setPropertyFlag( h, UI_SELECT_LABEL, uuId, enableFl ); }
cw::rc_t cw::ui::clearSelect( handle_t h, unsigned uuId )
{ return setSelect(h,uuId,false); }
bool cw::ui::isSelected( handle_t h, unsigned uuId )
{
ui_t* p = _handleToPtr(h);
ele_t* ele = nullptr;
bool selectFl = false;
if((ele = _uuIdToEle(p,uuId)) != nullptr )
selectFl = _get_attribute_bool(ele,UI_SELECT_LABEL);
return selectFl;
}
cw::rc_t cw::ui::registerAppIdMap( handle_t h, const appIdMap_t* map, unsigned mapN )
@ -1250,42 +1386,42 @@ cw::rc_t cw::ui::registerAppIdMap( handle_t h, const appIdMap_t* map, unsigned
return _registerAppIdMap( _handleToPtr(h), map, mapN);
}
cw::rc_t cw::ui::sendValueBool( handle_t h, unsigned wsSessId, unsigned uuId, bool value )
cw::rc_t cw::ui::sendValueBool( handle_t h, unsigned uuId, bool value )
{
ui_t* p = _handleToPtr(h);
return _sendValue<int>(p,wsSessId,uuId,"%i",value?1:0);
return _sendValue<int>(p,kInvalidId,uuId,"%i",value?1:0);
}
cw::rc_t cw::ui::sendValueInt( handle_t h, unsigned wsSessId, unsigned uuId, int value )
cw::rc_t cw::ui::sendValueInt( handle_t h, unsigned uuId, int value )
{
ui_t* p = _handleToPtr(h);
return _sendValue<int>(p,wsSessId,uuId,"%i",value);
return _sendValue<int>(p,kInvalidId,uuId,"%i",value);
}
cw::rc_t cw::ui::sendValueUInt( handle_t h, unsigned wsSessId, unsigned uuId, unsigned value )
cw::rc_t cw::ui::sendValueUInt( handle_t h, unsigned uuId, unsigned value )
{
ui_t* p = _handleToPtr(h);
return _sendValue<unsigned>(p,wsSessId,uuId,"%i",value);
return _sendValue<unsigned>(p,kInvalidId,uuId,"%i",value);
}
cw::rc_t cw::ui::sendValueFloat( handle_t h, unsigned wsSessId, unsigned uuId, float value )
cw::rc_t cw::ui::sendValueFloat( handle_t h, unsigned uuId, float value )
{
ui_t* p = _handleToPtr(h);
return _sendValue<float>(p,wsSessId,uuId,"%f",value);
return _sendValue<float>(p,kInvalidId,uuId,"%f",value);
}
cw::rc_t cw::ui::sendValueDouble( handle_t h, unsigned wsSessId, unsigned uuId, double value )
cw::rc_t cw::ui::sendValueDouble( handle_t h, unsigned uuId, double value )
{
ui_t* p = _handleToPtr(h);
return _sendValue<double>(p,wsSessId,uuId,"%f",value);
return _sendValue<double>(p,kInvalidId,uuId,"%f",value);
}
cw::rc_t cw::ui::sendValueString( handle_t h, unsigned wsSessId, unsigned uuId, const char* value )
cw::rc_t cw::ui::sendValueString( handle_t h, unsigned uuId, const char* value )
{
ui_t* p = _handleToPtr(h);
// +10 allows for extra value buffer space for double quotes and slashed
return _sendValue<const char*>(p,wsSessId,uuId,"\"%s\"",value,strlen(value)+10);
return _sendValue<const char*>(p,kInvalidId,uuId,"\"%s\"",value,"value",strlen(value)+10);
}
void cw::ui::report( handle_t h )
@ -1375,7 +1511,7 @@ namespace cw
rc_t _webSockSend( void* cbArg, unsigned wsSessId, const void* msg, unsigned msgByteN )
{
ui_ws_t* p = static_cast<ui_ws_t*>(cbArg);
return websock::send( p->wsH, kUiProtocolId, wsSessId, msg, msgByteN );
return websock::send( p->wsH, kUiProtocolId, kInvalidId, msg, msgByteN );
}
}

73
cwUi.h
View File

@ -12,7 +12,7 @@ namespace cw
// Callback for application notification.
// (e.g. the GUI changed the value of a UI element)
typedef rc_t (*uiCallback_t)( void* cbArg, unsigned wsSessId, opId_t opId, unsigned parentAppId, unsigned uuId, unsigned appId, const value_t* value );
typedef rc_t (*uiCallback_t)( void* cbArg, unsigned wsSessId, opId_t opId, unsigned parentAppId, unsigned uuId, unsigned appId, unsigned chanId, const value_t* value );
// Callback with messages for the GUI as JSON strings
// { "op":"create", "type":<>, "appId":<>, "parentUuId":<>, "name":<> (type specific fields) }
@ -58,9 +58,11 @@ namespace cw
// Create multiple UI elements from an object_t representation.
rc_t createFromObject( handle_t h, const object_t* o, unsigned wsSessId, unsigned parentUuId=kInvalidId, const char* eleName=nullptr);
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);
// The channel id of all elements created from the object will be assigned 'chanId'.
// 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 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);
//
// Create Sincgle UI elements on the UI instance identified by wsSessId.
@ -88,45 +90,54 @@ namespace cw
// title: (optional) Visible Text label associated with this element.
//
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 createLabel( 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* eleName, unsigned appId, const char* clas, const char* title );
rc_t createDiv( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title );
rc_t createLabel( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title );
rc_t createButton( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title );
// Create check: w/o value. The value will be read from the engine via the UI 'echo' event.
rc_t createCheck( 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 parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title );
// Create check: w/ value. The value will be sent to the engine as the new value of the associated varaible.
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 createCheck( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, bool value );
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* eleName, unsigned appId, const char* clas, const char* title );
rc_t createStr( handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title );
rc_t createStr( 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 createNumbDisplay(handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, unsigned decPl );
rc_t createNumbDisplay(handle_t h, unsigned& uuIdRef, unsigned wsSessId, unsigned parentUuId, const char* eleName, unsigned appId, const char* clas, const char* title, unsigned decPl, double value );
rc_t createNumb( 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 stepValue, unsigned decPl );
rc_t createNumb( 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 stepValue, unsigned decPl, double value );
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 createSelect( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title );
rc_t createOption( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title );
rc_t createStr( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title );
rc_t createStr( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, const char* value );
rc_t createNumbDisplay(handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, unsigned decPl );
rc_t createNumbDisplay(handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, unsigned decPl, double value );
rc_t createNumb( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, double minValue, double maxValue, double stepValue, unsigned decPl );
rc_t createNumb( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, double minValue, double maxValue, double stepValue, unsigned decPl, double value );
rc_t createProg( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, double minValue, double maxValue );
rc_t createProg( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title, double minValue, double maxValue, double value );
rc_t createLog( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, const char* clas, const char* title );
rc_t createList( handle_t h, unsigned& uuIdRef, unsigned parentUuId, const char* eleName, unsigned appId, unsigned chanId, 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 );
rc_t setLogLine( handle_t h, unsigned wsSessId, unsigned uuId, const char* text );
rc_t setNumbRange( handle_t h, unsigned uuId, double minValue, double maxValue, double stepValue, unsigned decPl, double value );
rc_t setProgRange( handle_t h, unsigned uuId, double minValue, double maxValue, double value );
rc_t setLogLine( handle_t h, unsigned uuId, const char* text );
rc_t setClickable( handle_t h, unsigned uuId, bool clickableFl=true );
rc_t clearClickable( handle_t h, unsigned uuId );
bool isClickable( handle_t h, unsigned uuId );
rc_t setSelect( handle_t h, unsigned uuId, bool enableFl=true );
rc_t clearSelect( handle_t h, unsigned uuId );
bool isSelected( handle_t h, unsigned uuId );
// Register parent/child/name app id's
rc_t registerAppIdMap( handle_t h, const appIdMap_t* map, unsigned mapN );
// Send a value from the application to the UI via a JSON messages.
// Set wsSessId to kInvalidId to send to all sessions.
rc_t sendValueBool( handle_t h, unsigned wsSessId, unsigned uuId, bool value );
rc_t sendValueInt( handle_t h, unsigned wsSessId, unsigned uuId, int value );
rc_t sendValueUInt( handle_t h, unsigned wsSessId, unsigned uuId, unsigned value );
rc_t sendValueFloat( handle_t h, unsigned wsSessId, unsigned uuId, float value );
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 );
rc_t sendValueBool( handle_t h, unsigned uuId, bool value );
rc_t sendValueInt( handle_t h, unsigned uuId, int value );
rc_t sendValueUInt( handle_t h, unsigned uuId, unsigned value );
rc_t sendValueFloat( handle_t h, unsigned uuId, float value );
rc_t sendValueDouble( handle_t h, unsigned uuId, double value );
rc_t sendValueString( handle_t h, unsigned uuId, const char* value );
void report( handle_t h );
@ -147,7 +158,7 @@ namespace cw
unsigned wsTimeOutMs;
} args_t;
rc_t parseArgs( const object_t& o, args_t& args, const char* object_label=nullptr );
rc_t parseArgs( const object_t& o, args_t& args, const char* object_label="ui" );
rc_t releaseArgs( args_t& args );
rc_t create( handle_t& h,

View File

@ -17,6 +17,7 @@ namespace cw
kConnectOpId, // A new remote user interface was connected
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.
kClickOpId, // A element on a remote user interface was clicked.
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.
kDisconnectOpId // A reemot user interface was disconnected.

View File

@ -77,44 +77,43 @@ namespace cw
rc_t rc = kOkRC;
unsigned uuid = kInvalidId;
unsigned selUuId = kInvalidId;
unsigned chanId = 0;
handle_t uiH = srv::uiHandle(p->wsUiSrvH);
// Create a UI elements programatically.
if((rc = createDiv( uiH, p->myPanelUuId, wsSessId, kInvalidId, "myDivId", kDivId, "divClass", "My Panel" )) != kOkRC )
if((rc = createDiv( uiH, p->myPanelUuId, kInvalidId, "myDivId", kDivId, chanId, "divClass", "My Panel" )) != kOkRC )
goto errLabel;
if((rc = createCheck( uiH, uuid, wsSessId, p->myPanelUuId, "myCheckId", kCheckId, "checkClass", "Check Me", true )) != kOkRC )
if((rc = createCheck( uiH, uuid, p->myPanelUuId, "myCheckId", kCheckId, chanId, "checkClass", "Check Me", true )) != kOkRC )
goto errLabel;
if((rc = createSelect( uiH, selUuId, wsSessId, p->myPanelUuId, "mySelId", kSelectId, "selClass", "Select" )) != kOkRC )
if((rc = createSelect( uiH, selUuId, p->myPanelUuId, "mySelId", kSelectId, chanId, "selClass", "Select" )) != kOkRC )
goto errLabel;
if((rc = createOption( uiH, uuid, wsSessId, selUuId, "myOpt0Id", kOption0Id, "optClass", "Option 0" )) != kOkRC )
if((rc = createOption( uiH, uuid, selUuId, "myOpt0Id", kOption0Id, chanId, "optClass", "Option 0" )) != kOkRC )
goto errLabel;
if((rc = createOption( uiH, uuid, wsSessId, selUuId, "myOpt1Id", kOption1Id, "optClass", "Option 1" )) != kOkRC )
if((rc = createOption( uiH, uuid, selUuId, "myOpt1Id", kOption1Id, chanId, "optClass", "Option 1" )) != kOkRC )
goto errLabel;
if((rc = createOption( uiH, uuid, wsSessId, selUuId, "myOpt2Id", kOption2Id, "optClass", "Option 2" )) != kOkRC )
if((rc = createOption( uiH, uuid, selUuId, "myOpt2Id", kOption2Id, chanId, "optClass", "Option 2" )) != kOkRC )
goto errLabel;
if((rc = createStr( uiH, uuid, wsSessId, p->myPanelUuId, "myStringId", kStringId, "stringClass", "String", "a string value" )) != kOkRC )
if((rc = createStr( uiH, uuid, p->myPanelUuId, "myStringId", kStringId, chanId, "stringClass", "String", "a string value" )) != kOkRC )
goto errLabel;
if((rc = createNumb( uiH, uuid, wsSessId, p->myPanelUuId, "myIntegerId", kIntegerId, "integerClass", "Integer", 0, 100, 1, 0, 10 )) != kOkRC )
if((rc = createNumb( uiH, uuid, p->myPanelUuId, "myIntegerId", kIntegerId, chanId, "integerClass", "Integer", 0, 100, 1, 0, 10 )) != kOkRC )
goto errLabel;
if((rc = createNumb( uiH, uuid, wsSessId, p->myPanelUuId, "myFloatId", kFloatId, "floatClass", "Float", 0.53, 100.97, 1.0, 5, 10.0 )) != kOkRC )
if((rc = createNumb( uiH, uuid, p->myPanelUuId, "myFloatId", kFloatId, chanId, "floatClass", "Float", 0.53, 100.97, 1.0, 5, 10.0 )) != kOkRC )
goto errLabel;
if((rc = createProg( uiH, uuid, wsSessId, p->myPanelUuId, "myProgressId", kProgressId, "progressClass", "Progress", 0, 10, 5 )) != kOkRC )
if((rc = createProg( uiH, uuid, p->myPanelUuId, "myProgressId", kProgressId, chanId, "progressClass", "Progress", 0, 10, 5 )) != kOkRC )
goto errLabel;
if((rc = createLog( uiH, p->logUuId, wsSessId, p->myPanelUuId, "myLogId", kLogId, "logClass", "My Log (click toggles auto-scroll)" )) != kOkRC )
if((rc = createLog( uiH, p->logUuId, p->myPanelUuId, "myLogId", kLogId, chanId, "logClass", "My Log (click toggles auto-scroll)" )) != kOkRC )
goto errLabel;
errLabel:
@ -137,7 +136,7 @@ namespace cw
}
rc_t _insert_list_ele( ui_test_t* p, unsigned wsSessId )
rc_t _insert_list_ele( ui_test_t* p )
{
rc_t rc = kOkRC;
@ -148,16 +147,16 @@ namespace cw
printf("list uuid:%i\n",listUuId);
rc = createFromObject( uiH, p->listEleCfg, wsSessId, listUuId );
rc = createFromObject( uiH, p->listEleCfg, listUuId, kInvalidId );
}
return rc;
}
rc_t _insert_log_line( ui_test_t* p, unsigned wsSessId, const char* text )
rc_t _insert_log_line( ui_test_t* p, const char* text )
{
return ui::setLogLine( srv::uiHandle(p->wsUiSrvH), wsSessId, p->logUuId, text );
return ui::setLogLine( srv::uiHandle(p->wsUiSrvH), p->logUuId, text );
}
rc_t _handleUiValueMsg( ui_test_t* p, unsigned wsSessId, unsigned parentAppId, unsigned uuId, unsigned appId, const value_t* v )
@ -173,7 +172,7 @@ namespace cw
case kCheckId:
printf("Check:%i\n", v->u.b);
p->appCheckFl = v->u.b;
_insert_log_line( p, wsSessId, "check!\n" );
_insert_log_line( p, "check!\n" );
break;
case kSelectId:
@ -195,7 +194,7 @@ namespace cw
handle_t uiH = srv::uiHandle(p->wsUiSrvH);
unsigned progUuId = findElementUuId( uiH, p->myPanelUuId, kProgressId );
sendValueInt( uiH, wsSessId, progUuId, v->u.i );
sendValueInt( uiH, progUuId, v->u.i );
}
break;
@ -224,7 +223,7 @@ namespace cw
case kPanelCheck2Id:
printf("check 1: %i\n",v->u.b);
p->appCheck1Fl = v->u.b;
_insert_list_ele( p, wsSessId );
_insert_list_ele( p );
break;
case kPanelFloaterId:
@ -249,43 +248,43 @@ namespace cw
switch( appId )
{
case kCheckId:
sendValueBool( uiHandle( p->wsUiSrvH ), wsSessId, uuId, p->appCheckFl );
sendValueBool( uiHandle( p->wsUiSrvH ), uuId, p->appCheckFl );
break;
case kSelectId:
sendValueInt( uiHandle( p->wsUiSrvH ), wsSessId, uuId, p->appSelOptAppId );
sendValueInt( uiHandle( p->wsUiSrvH ), uuId, p->appSelOptAppId );
break;
case kStringId:
sendValueString( uiHandle( p->wsUiSrvH ), wsSessId, uuId, p->appString );
sendValueString( uiHandle( p->wsUiSrvH ), uuId, p->appString );
break;
case kIntegerId:
sendValueInt( uiHandle( p->wsUiSrvH ), wsSessId, uuId, p->appInteger );
sendValueInt( uiHandle( p->wsUiSrvH ), uuId, p->appInteger );
break;
case kFloatId:
sendValueFloat( uiHandle( p->wsUiSrvH ), wsSessId, uuId, p->appFloat );
sendValueFloat( uiHandle( p->wsUiSrvH ), uuId, p->appFloat );
break;
case kProgressId:
sendValueInt( uiHandle( p->wsUiSrvH ), wsSessId, uuId, p->appProgress );
sendValueInt( uiHandle( p->wsUiSrvH ), uuId, p->appProgress );
break;
case kPanelCheck1Id:
sendValueBool( uiHandle( p->wsUiSrvH ), wsSessId, uuId, p->appCheck1Fl);
sendValueBool( uiHandle( p->wsUiSrvH ), uuId, p->appCheck1Fl);
break;
case kPanelCheck2Id:
sendValueBool( uiHandle( p->wsUiSrvH ), wsSessId, uuId, p->appCheck2Fl);
sendValueBool( uiHandle( p->wsUiSrvH ), uuId, p->appCheck2Fl);
break;
case kPanelFloaterId:
sendValueFloat( uiHandle( p->wsUiSrvH ), wsSessId, uuId, p->appNumb );
sendValueFloat( uiHandle( p->wsUiSrvH ), uuId, p->appNumb );
break;
case kSelId:
sendValueInt( uiHandle( p->wsUiSrvH ), wsSessId, uuId, p->appSelId );
sendValueInt( uiHandle( p->wsUiSrvH ), uuId, p->appSelId );
break;
}
return rc;
@ -294,7 +293,7 @@ namespace cw
// This function is called by the websocket with messages coming from a remote UI.
rc_t _uiTestCallback( void* cbArg, unsigned wsSessId, opId_t opId, unsigned parentAppId, unsigned uuId, unsigned appId, const value_t* v )
rc_t _uiTestCallback( void* cbArg, unsigned wsSessId, opId_t opId, unsigned parentAppId, unsigned uuId, unsigned appId, unsigned chanId, const value_t* v )
{
ui_test_t* p = (ui_test_t*)cbArg;
@ -316,6 +315,17 @@ namespace cw
_handleUiValueMsg( p, wsSessId, parentAppId, uuId, appId, v );
break;
case kClickOpId:
{
printf("APP clicked. uu:%i app:%i ch:%i\n",uuId,appId,chanId);
handle_t uiH = srv::uiHandle(p->wsUiSrvH);
bool selectedFl = isSelected(uiH,uuId);
setSelect( uiH, uuId, !selectedFl );
}
break;
case kEchoOpId:
_handleUiEchoMsg( p, wsSessId, parentAppId, uuId, appId );
break;

View File

@ -138,3 +138,7 @@ label {
background-color: PowderBlue;
}
.uiSelected {
border: 1px solid red;
}

View File

@ -237,6 +237,14 @@ function ui_send_int_value( ele, value ) { ui_send_value(ele,'i',value); }
function ui_send_float_value( ele, value ) { ui_send_value(ele,'f',value); }
function ui_send_string_value( ele, value ) { ui_send_value(ele,'s',value); }
function ui_send_click( ele )
{
console.log("click " + ele.id )
ws_send("click " + ele.id )
}
function ui_send_echo( ele )
{
ws_send("echo " + ele.id )
@ -267,6 +275,11 @@ function ui_get_parent( parentId )
return parent_ele;
}
function ui_on_click( ele, evt )
{
ui_send_click(ele);
evt.stopPropagation();
}
function ui_create_ele( parent_ele, ele_type, d, dfltClassName )
{
@ -289,6 +302,9 @@ function ui_create_ele( parent_ele, ele_type, d, dfltClassName )
else
ele.appId = null;
if( d.hasOwnProperty('clickable') )
ui_set_clickable( ele, d.clickable );
//console.log("Created: " + ele_type + " parent:" + d.parentUuId + " id:" + ele.id + " appId:" + ele.appId)
parent_ele.appendChild(ele);
@ -777,6 +793,7 @@ function ui_create_log( parent_ele, d )
function ui_create_list( parent_ele, d )
{
d.className = "uiList"
console.log(d)
var list_ele = ui_create_ctl( parent_ele, "div", d.title, d, "uiList" )
return list_ele
@ -848,11 +865,37 @@ function ui_set_value( d )
break
default:
ui_error("Unknown UI element type: " + d.type )
ui_error("Unknown UI element type on set value: " + d.type )
}
}
}
function ui_set_select( ele, enableFl )
{
let selectClassLabel = " uiSelected"
let isSelectSetFl = ele.className.includes(selectClassLabel)
if( enableFl != isSelectSetFl )
{
if( enableFl )
ele.className += selectClassLabel;
else
ele.className = ele.className.replace(selectClassLabel, "");
}
}
function ui_set_clickable( ele, enableFl )
{
ele.clickableFl = enableFl
if(enableFl)
ele.onclick = function( evt ){ ui_on_click( this, evt ); }
else
ele.onclick = null
}
function ui_set( d )
{
//console.log(d)
@ -860,24 +903,26 @@ function ui_set( d )
if( ele == null )
console.log("ele not found");
else
if( !ele.hasOwnProperty("uiEleType") )
console.log("No type");
if( ele != null && ele.hasOwnProperty("uiEleType"))
if( ele != null)
{
//console.log("found: "+ele.uiEleType)
switch( ele.uiEleType )
switch( d.type )
{
case "number":
case "number_range":
ui_set_number_range(ele, d)
break;
case "progress":
case "progress_range":
ui_set_prog_range(ele, d)
break;
case "select":
ui_set_select(ele,d.enableFl)
break
case "clickable":
ui_set_clickable(ele,d.enableFl)
break
}
}
}

View File

@ -34,7 +34,7 @@
row: {
list:{ name: myListId, title:"My List" },
list:{ name: myListId, title:"My List", clickable: 1 },
},