diff --git a/cwUi.cpp b/cwUi.cpp index b31a9d4..f3a9c40 100644 --- a/cwUi.cpp +++ b/cwUi.cpp @@ -14,6 +14,8 @@ #define UI_CLICKABLE_LABEL "clickable" #define UI_SELECT_LABEL "select" +#define UI_VISIBLE_LABEL "visible" +#define UI_ENABLE_LABEL "enable" namespace cw { @@ -31,7 +33,8 @@ namespace cw typedef struct ele_str { - 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 the root ui ele + unsigned parentAppId; 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; // @@ -351,13 +354,31 @@ namespace cw 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(); + unsigned parentAppId = kInvalidId; + + // Go up the tree looking for the first parent with a valid appId + // This is useful to cover the situation where the parent is an unamed div (e.g. row, col, panel) + // and the appIdMap gives the panel name as the parent. - e->parent = parent; - e->uuId = p->eleN; - e->appId = appId; - e->chanId = chanId; - e->eleName = eleName==nullptr ? nullptr : mem::duplStr(eleName); - e->attr = newDictObject(); + if( parent != nullptr ) + { + parentAppId = parent->appId; + for(const ele_t* par=parent; par!=nullptr; par=par->parent) + if( par->appId != kInvalidId ) + { + parentAppId = par->appId; + break; + } + } + + + e->parent = parent; + e->parentAppId = parentAppId; + e->uuId = p->eleN; + e->appId = appId; + e->chanId = chanId; + e->eleName = eleName==nullptr ? nullptr : mem::duplStr(eleName); + e->attr = newDictObject(); if( eleTypeStr != nullptr ) e->attr->insert_pair("type",eleTypeStr); @@ -368,6 +389,9 @@ namespace cw if( eleTitle != nullptr ) e->attr->insert_pair("title",eleTitle); + // elements default to visible and enabled + e->attr->insert_pair("visible",true); + e->attr->insert_pair("enable",true); if( p->eleN == p->eleAllocN ) { @@ -382,20 +406,9 @@ namespace cw if( appId == kInvalidId && parent != nullptr ) { appIdMapRecd_t* m; - - // Go up the tree looking for the first parent with a valid appId - // This is useful to cover the situation where the parent is an unamed div (e.g. row, col, panel) - // and the appIdMap gives the panel name as the parent. - unsigned parentAppId = parent->appId; - for(const ele_t* par=parent; par!=nullptr; par=par->parent) - if( par->appId != kInvalidId ) - { - parentAppId = par->appId; - break; - } - + // ... then try to look it up from the appIdMap. - if((m = _findAppIdMap(p, parentAppId, eleName)) != nullptr ) + if((m = _findAppIdMap(p, e->parentAppId, eleName)) != nullptr ) e->appId = m->appId; } @@ -1022,9 +1035,7 @@ cw::rc_t cw::ui::onReceive( handle_t h, unsigned wsSessId, const void* msg, unsi 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 ); + p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->parentAppId, ele->uuId, ele->appId, ele->chanId, &value ); } break; @@ -1034,9 +1045,7 @@ cw::rc_t cw::ui::onReceive( handle_t h, unsigned wsSessId, const void* msg, unsi 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 ); + p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->parentAppId, ele->uuId, ele->appId, ele->chanId, &value ); } break; @@ -1045,9 +1054,7 @@ cw::rc_t cw::ui::onReceive( handle_t h, unsigned wsSessId, const void* msg, unsi cwLogError(kOpFailRC,"UI Echo 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,nullptr ); + p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->parentAppId, ele->uuId, ele->appId, ele->chanId,nullptr ); } break; @@ -1068,35 +1075,35 @@ cw::rc_t cw::ui::onReceive( handle_t h, unsigned wsSessId, const void* msg, unsi return rc; } -unsigned cw::ui::findElementAppId( handle_t h, unsigned parentUuId, const char* eleName ) +unsigned cw::ui::findElementAppId( handle_t h, unsigned parentAppId, const char* eleName ) { ui_t* p = _handleToPtr(h); for(unsigned i=0; ieleN; ++i) - if( p->eleA[i]->parent->uuId==parentUuId && strcmp(p->eleA[i]->eleName,eleName) == 0 ) + if( p->eleA[i]->parentAppId==parentAppId && strcmp(p->eleA[i]->eleName,eleName) == 0 ) return p->eleA[i]->appId; return kInvalidId; } -unsigned cw::ui::findElementUuId( handle_t h, unsigned parentUuId, const char* eleName ) +unsigned cw::ui::parentAndNameToUuId( handle_t h, unsigned parentAppId, const char* eleName ) { ui_t* p = _handleToPtr(h); for(unsigned i=0; ieleN; ++i) - if( p->eleA[i]->parent->uuId==parentUuId && strcmp(p->eleA[i]->eleName,eleName) == 0 ) + if( p->eleA[i]->parentAppId==parentAppId && strcmp(p->eleA[i]->eleName,eleName) == 0 ) return p->eleA[i]->uuId; return kInvalidId; } -unsigned cw::ui::findElementUuId( handle_t h, unsigned parentUuId, unsigned appId ) +unsigned cw::ui::parentAndAppIdToUuId( handle_t h, unsigned parentAppId, unsigned appId ) { ui_t* p = _handleToPtr(h); for(unsigned i=0; ieleN; ++i) - if(((p->eleA[i]->parent==nullptr && parentUuId==kRootUuId) || - (p->eleA[i]->parent!=nullptr && p->eleA[i]->parent->uuId==parentUuId)) + if(((p->eleA[i]->parent==nullptr && parentAppId==kRootAppId) || + (p->eleA[i]->parentAppId==parentAppId)) && p->eleA[i]->appId == appId ) return p->eleA[i]->uuId; return kInvalidId; @@ -1379,6 +1386,42 @@ bool cw::ui::isSelected( handle_t h, unsigned uuId ) return selectFl; } +cw::rc_t cw::ui::setVisible( handle_t h, unsigned uuId, bool enableFl ) +{ return _setPropertyFlag( h, UI_VISIBLE_LABEL, uuId, enableFl ); } + +cw::rc_t cw::ui::clearVisible( handle_t h, unsigned uuId ) +{ return setVisible(h,uuId,false); } + +bool cw::ui::isVisible( handle_t h, unsigned uuId ) +{ + ui_t* p = _handleToPtr(h); + ele_t* ele = nullptr; + bool visibleFl = false; + + if((ele = _uuIdToEle(p,uuId)) != nullptr ) + visibleFl = _get_attribute_bool(ele,UI_VISIBLE_LABEL); + + return visibleFl; +} + +cw::rc_t cw::ui::setEnable( handle_t h, unsigned uuId, bool enableFl ) +{ return _setPropertyFlag( h, UI_ENABLE_LABEL, uuId, enableFl ); } + +cw::rc_t cw::ui::clearEnable( handle_t h, unsigned uuId ) +{ return setEnable(h,uuId,false); } + +bool cw::ui::isEnabled( handle_t h, unsigned uuId ) +{ + ui_t* p = _handleToPtr(h); + ele_t* ele = nullptr; + bool enableFl = false; + + if((ele = _uuIdToEle(p,uuId)) != nullptr ) + enableFl = _get_attribute_bool(ele,UI_ENABLE_LABEL); + + return enableFl; +} + cw::rc_t cw::ui::registerAppIdMap( handle_t h, const appIdMap_t* map, unsigned mapN ) @@ -1433,10 +1476,9 @@ void cw::ui::report( handle_t h ) const ele_t* e = p->eleA[i]; unsigned parUuId = e->parent==NULL ? kInvalidId : e->parent->uuId; - unsigned parAppId = e->parent==NULL ? kInvalidId : e->parent->appId; const char* parEleName = e->parent==NULL || e->parent->eleName == NULL ? "" : e->parent->eleName; - printf("uu:%5i app:%5i %20s : parent uu:%5i app:%5i %20s ", e->uuId, e->appId, e->eleName == NULL ? "" : e->eleName, parUuId, parAppId, parEleName ); + printf("uu:%5i app:%5i %20s : parent uu:%5i app:%5i %20s ", e->uuId, e->appId, e->eleName == NULL ? "" : e->eleName, parUuId, e->parentAppId, parEleName ); for(unsigned i=0; iattr->child_count(); ++i) { diff --git a/cwUi.h b/cwUi.h index 00af319..043374d 100644 --- a/cwUi.h +++ b/cwUi.h @@ -45,9 +45,9 @@ namespace cw rc_t onReceive( handle_t h, unsigned wsSessId, const void* msg, unsigned byteN ); // Locate an element whose parent uuid is 'parentUuId' with a child named 'eleName'. - unsigned findElementAppId( handle_t h, unsigned parentUuId, const char* eleName ); - unsigned findElementUuId( handle_t h, unsigned parentUuId, const char* eleName ); - unsigned findElementUuId( handle_t h, unsigned parentUuId, unsigned appId ); + unsigned findElementAppId( handle_t h, unsigned parentAppId, const char* eleName ); + unsigned parentAndNameToUuId( handle_t h, unsigned parentAppId, const char* eleName ); + unsigned parentAndAppIdToUuId( handle_t h, unsigned parentAppId, unsigned appId ); const char* findElementName( handle_t h, unsigned uuId ); unsigned findElementAppId( handle_t h, unsigned uuId ); @@ -124,6 +124,14 @@ namespace cw 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 ); + + rc_t setVisible( handle_t h, unsigned uuId, bool enableFl=true ); + rc_t clearVisible( handle_t h, unsigned uuId ); + bool isVisible( handle_t h, unsigned uuId ); + + rc_t setEnable( handle_t h, unsigned uuId, bool enableFl=true ); + rc_t clearEnable( handle_t h, unsigned uuId ); + bool isEnabled( handle_t h, unsigned uuId ); // Register parent/child/name app id's rc_t registerAppIdMap( handle_t h, const appIdMap_t* map, unsigned mapN ); diff --git a/cwUiTest.cpp b/cwUiTest.cpp index 997bc49..ecbd8fa 100644 --- a/cwUiTest.cpp +++ b/cwUiTest.cpp @@ -50,7 +50,7 @@ namespace cw kOption0Id, kOption1Id, kOption2Id, - kOption3Id, + kOption3Id, kStringId, kIntegerId, kFloatId, @@ -59,6 +59,7 @@ namespace cw // Resource Based elements kQuitBtnId, + kUiRptBtnId, kPanelDivId, kPanelBtn1Id, kPanelCheck1Id, @@ -169,6 +170,10 @@ namespace cw p->quitFl.store(true); break; + case kUiRptBtnId: + ui::report(srv::uiHandle(p->wsUiSrvH)); + break; + case kCheckId: printf("Check:%i\n", v->u.b); p->appCheckFl = v->u.b; @@ -193,7 +198,7 @@ namespace cw p->appInteger = v->u.i; handle_t uiH = srv::uiHandle(p->wsUiSrvH); - unsigned progUuId = findElementUuId( uiH, p->myPanelUuId, kProgressId ); + unsigned progUuId = parentAndAppIdToUuId( uiH, kDivId, kProgressId ); sendValueInt( uiH, progUuId, v->u.i ); } break; @@ -204,15 +209,29 @@ namespace cw case kPanelBtn1Id: - printf("Button 1\n"); - _print_state(p); + { + handle_t uiH = srv::uiHandle(p->wsUiSrvH); + unsigned btnUuId = parentAndAppIdToUuId( uiH, kPanelDivId, kPanelBtn2Id ); + + printf("Button 1 %i\n",btnUuId); + _print_state(p); + + + bool enableFl = isEnabled( uiH, btnUuId ); + setEnable( uiH, btnUuId, !enableFl ); + } break; case kPanelCheck1Id: - printf("check 1: %i\n",v->u.b); - p->appCheck1Fl = v->u.b; - ui::report( srv::uiHandle(p->wsUiSrvH) ); - + { + printf("check 2: %i\n",v->u.b); + p->appCheck1Fl = v->u.b; + + handle_t uiH = srv::uiHandle(p->wsUiSrvH); + unsigned progUuId = parentAndAppIdToUuId( uiH, kDivId, kProgressId ); + bool visibleFl = isVisible( uiH, progUuId ); + setVisible( uiH, progUuId, !visibleFl ); + } break; case kPanelBtn2Id: @@ -235,6 +254,9 @@ namespace cw printf("sel: %i\n",v->u.i); p->appSelId = v->u.i; break; + + default: + cwLogWarning("Unhandled value message: uuid:%i appId:%i\n",uuId,appId); } return rc; @@ -360,6 +382,7 @@ cw::rc_t cw::ui::test( const object_t* cfg ) { kSelId, kOpt1Id, "myOpt1" }, { kSelId, kOpt2Id, "myOpt2" }, { kSelId, kOpt3Id, "myOpt3" }, + { kPanelDivId, kUiRptBtnId, "uiRptBtnId" }, { kPanelDivId, kListId, "myListId" } }; diff --git a/html/preset_sel/ui.cfg b/html/preset_sel/ui.cfg index 94bf32f..cd7c2f7 100644 --- a/html/preset_sel/ui.cfg +++ b/html/preset_sel/ui.cfg @@ -41,6 +41,13 @@ button:{ name: saveBtnId, title:"Save" }, }, + row: { + number:{ name: insertLocId, title:"End Loc", min:0, max:100000, step:1, decpl:0 }, + button:{ name: insertBtnId, title:"Insert" }, + button:{ name: deleteBtnId, title:"Delete" }, + + }, + row: { list:{ name: presetLocListId, title:"Preset Locations" }, }, diff --git a/html/uiTest/js/ui.js b/html/uiTest/js/ui.js index e0f26f8..2ee5208 100644 --- a/html/uiTest/js/ui.js +++ b/html/uiTest/js/ui.js @@ -870,20 +870,27 @@ function ui_set_value( d ) } } -function ui_set_select( ele, enableFl ) +function _ui_modify_class( ele, classLabelArg, enableFl ) { - let selectClassLabel = " uiSelected" - let isSelectSetFl = ele.className.includes(selectClassLabel) + let classLabel = " " + classLabelArg; // prefix the class label with a space + + let isEnabledFl = ele.className.includes(classLabel) - if( enableFl != isSelectSetFl ) + // if the class is not already enabled/disabled + if( enableFl != isEnabledFl ) { if( enableFl ) - ele.className += selectClassLabel; + ele.className += classLabel; else - ele.className = ele.className.replace(selectClassLabel, ""); + ele.className = ele.className.replace(classLabel, ""); } } +function ui_set_select( ele, enableFl ) +{ + _ui_modify_class("uiSelected") +} + function ui_set_clickable( ele, enableFl ) { @@ -895,10 +902,35 @@ function ui_set_clickable( ele, enableFl ) ele.onclick = null } +function ui_set_visible( ele, enableFl ) +{ + if(enableFl) + { + if(ele.hasOwnProperty("style_display") ) + { + ele.style.display = ele.style_display; + } + else + { + ele.style.display = "block"; + } + } + else + { + ele.style_display = ele.style.display; + ele.style.display = "none"; + } +} + +function ui_set_enable( ele, enableFl ) +{ + ele.disabled = !enableFl +} + function ui_set( d ) { - //console.log(d) + console.log(d) var ele = dom_id_to_ele(d.uuId.toString()) if( ele == null ) @@ -923,6 +955,15 @@ function ui_set( d ) case "clickable": ui_set_clickable(ele,d.enableFl) break + + case "visible": + ui_set_visible(ele,d.enableFl) + break + + case "enable": + ui_set_enable(ele,d.enableFl) + break + } } } diff --git a/html/uiTest/ui.cfg b/html/uiTest/ui.cfg index 79f4192..4cfbe82 100644 --- a/html/uiTest/ui.cfg +++ b/html/uiTest/ui.cfg @@ -4,7 +4,7 @@ parent: "uiDivId" button:{ name: myQuitBtnId, title:"Quit" }, - + panel: { @@ -23,6 +23,7 @@ option:{ name: myOpt3, title:"Sel 3" } }, }, + button:{ name: uiRptBtnId, title:"UI Report" }, }, row: {