// %flair:license{ // This file is part of the Flair framework distributed under the // CECILL-C License, Version 1.0. // %flair:license} // created: 2012/05/02 // filename: Widget.cpp // // author: Guillaume Sanahuja // Copyright Heudiasyc UMR UTC/CNRS 7253 // // version: $Id: $ // // purpose: classe pour widget // // /*********************************************************************/ #include "Widget.h" #include "Widget_impl.h" #include "Object_impl.h" #include "FrameworkManager.h" #include "FrameworkManager_impl.h" #include "config.h" #ifdef __XENO__ #include #else #include #include #endif using std::string; using std::vector; using namespace flair::core; using namespace flair::gui; namespace{ #ifdef __XENO__ RT_HEAP xml_heap; void xml2_free(void *mem) { //Printf("free %x\n",mem); if(mem==NULL) return; int status=rt_heap_free(&xml_heap,mem); if(status!=0) { printf("libxml2: rt_heap_free error (%s)\n",strerror(-status)); } } void *xml2_alloc(size_t sz) { void *ptr; //printf("alloc %i\n",sz); int status=rt_heap_alloc(&xml_heap,sz,TM_NONBLOCK ,&ptr); if(status!=0) { printf("libxml2: rt_heap_alloc error (%s)\n",strerror(-status)); } //Printf("alloc %x %i\n",ptr,sz); return ptr; } void *xml2_realloc(void *emem,size_t sz) { //Printf("realloc %x %i -> %i\n",emem,sz,sz); void *mem_re; if (emem == NULL) { return xml2_alloc(sz); } else if (sz == 0) { xml2_free(emem); } mem_re = xml2_alloc(sz); memcpy(mem_re, emem, sz); xml2_free(emem); return mem_re; } char *xml2_strdup(const char * str) { // printf("strdup %s\n",str); char *s = (char*)xml2_alloc(strlen(str) + 1); if (s == NULL) return NULL; strcpy(s, str); return s; } #endif //__XENO__ } Widget_impl::Widget_impl(Widget* self,const Widget* parent,string name,string type) { //Printf("Widget %s\n",name.c_str()); isenabled=true; file_node=NULL; this->self=self; //n'est execute qu'une fois lorsqu'on construit le FrameworkManager if(parent==NULL) { #ifdef __XENO__ string tmp_name; tmp_name=name + "-xml"; int status=rt_heap_create(&xml_heap,tmp_name.c_str(),XML_HEAP,H_FIFO); if(status!=0) { self->Err("rt_heap_create error (%s)\n",strerror(-status)); } xmlMemSetup(xml2_free,xml2_alloc, xml2_realloc,xml2_strdup); #endif //__XENO__ } //xml init if(parent==NULL) { //create local doc send_doc = xmlNewDoc((xmlChar*)"1.0"); send_node = xmlNewNode(NULL, (xmlChar*)type.c_str()); xmlDocSetRootElement(send_doc, send_node); xmlSetProp(send_node,(xmlChar*)"name",(xmlChar*)self->ObjectName().c_str()); } else { parent->pimpl_->AddChild(self); //get node corresponding to this widget in the xml file if(parent->pimpl_->file_node!=NULL) { xmlChar* search=xmlCharStrdup(type.c_str()); file_node=GetNodeByProp(parent->pimpl_->file_node->xmlChildrenNode,search,(xmlChar*)"name",(xmlChar*)name.c_str()); xmlFree(search); } else { self->Err("parent->file_node is NULL\n"); } if(file_node==NULL) { self->Warn("%s, no match found in xml file\n",type.c_str()); xmlNode *node; node=xmlNewNode(NULL, (xmlChar*)type.c_str()); xmlSetProp(node,(xmlChar*)"name",(xmlChar*)name.c_str()); file_node=xmlAddChild(parent->pimpl_->file_node,node); //((Widget*)getFrameworkManager())->pimpl_->PrintXml(); } send_doc=parent->pimpl_->CopyDoc(); //on recupere le dernier node xmlNodePtr node=xmlDocGetRootElement(send_doc); while(node->children!=NULL) node=node->children; //on ajoute le node du widget send_node = xmlNewNode(NULL, (xmlChar*)type.c_str()); xmlSetProp(send_node,(xmlChar*)"name",(xmlChar*)name.c_str()); xmlAddChild(node,send_node); } //Printf("Widget ok %s\n",name.c_str()); } Widget_impl::~Widget_impl() { //Printf("destruction widget %s\n",self->ObjectName().c_str()); if(self->Parent()!=NULL) ((Widget*)(self->Parent()))->pimpl_->RemoveChild(self); //on efface les widgets enfants avant d'envoyer son propre delete au sol //dans le delete child on modifie le child du parent, donc on se refere toujours au premier while(childs.size()!=0) { //Printf("child %i %s\n",childs.size(),childs.front()->ObjectName().c_str()); if(childs.front()!=NULL) delete childs.front(); } childs.clear(); self->SetVolatileXmlProp("Delete",true); if(self->Parent()!=NULL) SendXml(); xmlFreeDoc(send_doc); if(self->Parent()==NULL) { xmlCleanupParser(); #ifdef __XENO__ int status; RT_HEAP_INFO info; status=rt_heap_inquire(&xml_heap,&info); if(status!=0) { self->Err("rt_heap_inquire error (%s)\n",strerror(-status)); } if(info.usedmem!=0) self->Err("fuite memoire xml heap (%ld)\n",info.usedmem); //Printf("fin heap xml\n"); status=rt_heap_delete(&xml_heap); if(status!=0) { self->Err("rt_heap_delete error (%s)\n",strerror(-status)); } #endif } //Printf("destruction widget %s ok\n",self->ObjectName().c_str()); } void Widget_impl::AddChild(const Widget* child) { childs.push_back((Widget*)child); } void Widget_impl::RemoveChild(const Widget* child) { for(vector::iterator it=childs.begin() ; it < childs.end(); it++ ) { if(*it==child) { childs.erase(it); break; } } } xmlDocPtr Widget_impl::CopyDoc(void) { return xmlCopyDoc(send_doc,1); } void Widget_impl::ClearXmlProps(void) { xmlUnlinkNode(send_node); xmlFreeNode(send_node); xmlNodePtr node; node=xmlDocGetRootElement(send_doc); if(node==NULL) {//il ne reste plus rien, on refait le rootelement send_node = xmlNewNode(NULL, (xmlChar*)XML_ROOT_TYPE); xmlSetProp(send_node,(xmlChar*)"name",(xmlChar*)self->ObjectName().c_str()); xmlDocSetRootElement(send_doc, send_node); } else { while(node->children!=NULL) node=node->children; send_node = xmlNewNode(NULL, (xmlChar*)self->ObjectType().c_str()); xmlSetProp(send_node,(xmlChar*)"name",(xmlChar*)self->ObjectName().c_str()); xmlAddChild(node,send_node); } } void Widget_impl::printSendNode() { xmlChar *xmlbuff; int buffersize; xmlDocDumpFormatMemory(send_doc, &xmlbuff, &buffersize, 1); Printf("xml:\n%s\n",xmlbuff); xmlFree(xmlbuff); } void Widget_impl::SendXml(void) { if(getUiCom()!=NULL) { xmlChar *xmlbuff; int buffersize; xmlDocDumpFormatMemory(send_doc, &xmlbuff, &buffersize, 0); getUiCom()->Send((char*)xmlbuff,buffersize); xmlFree(xmlbuff); ClearXmlProps(); } } void Widget_impl::setEnabled(bool status) { self->SetVolatileXmlProp("IsEnabled",status); SendXml(); } void Widget_impl::ProcessXML(xmlNode *node) { //Printf("ProcessXML %s %s\n",xmlGetProp(send_node, (xmlChar*)"name"),send_node->name); xmlNode *cur_node = NULL; for(size_t i=0;inext) { if (cur_node->type == XML_ELEMENT_NODE) { //Printf("recherche %s\n", xmlGetProp(cur_node, (xmlChar*)"name")); xmlChar* name=NULL; name=xmlGetProp(cur_node, (xmlChar*)"name"); if (!xmlStrcmp((xmlChar *)childs[i]->ObjectName().c_str(), name)) { //Printf("correspond %s\n",childs[i]->ObjectName().c_str()); xmlChar* new_name=NULL; new_name=xmlGetProp(cur_node, (xmlChar*)"new_name"); if(new_name!=NULL) { unsigned char* ren_name=new_name;//xmlGetProp(cur_node, (xmlChar*)"new_name"); self->Warn("%s existe deja, renommage en %s; possiblite de problemes!!\n",childs[i]->ObjectName().c_str(),new_name); childs[i]->Object::pimpl_->name=((const char*)ren_name); xmlSetProp(childs[i]->pimpl_->send_node,(xmlChar*)"name",xmlGetProp(cur_node, (xmlChar*)"new_name")); xmlFree(new_name); if(name!=NULL) xmlFree(name); break; } if(name!=NULL) xmlFree(name); //update file node xmlAttr *cur_prop = NULL; //xmlAttr *file_prop = NULL; for (cur_prop = cur_node->properties; cur_prop; cur_prop = cur_prop->next) { //Printf("rcv prop %s %s\n",cur_prop->name,cur_prop->children->content); xmlSetProp(childs[i]->pimpl_->file_node,cur_prop->name,cur_prop->children->content); } childs[i]->XmlEvent(); childs[i]->pimpl_->ProcessXML(cur_node->children); break; } if(name!=NULL) xmlFree(name); } } } //printf("fin ProcessXML %s %s\n",xmlGetProp(send_node, (xmlChar*)"name"),send_node->name); } xmlNodePtr Widget_impl::GetNodeByProp(xmlNodePtr doc,xmlChar *type,xmlChar *prop,xmlChar *value) { //printf("cherche keyword: %s %s %s\n", type,prop,value); xmlNode *cur_node = NULL; for (cur_node = doc; cur_node; cur_node = cur_node->next) { if (cur_node->type == XML_ELEMENT_NODE) { //printf("node %s %s\n",xmlGetProp(cur_node, (xmlChar*)"name"),cur_node->name); xmlChar *test = NULL; test=xmlGetProp(cur_node, prop); if(!xmlStrcmp(test,value) && !xmlStrcmp(cur_node->name,type )) { //printf("ok\n"); if(test!=NULL) xmlFree(test); return cur_node; } if(test!=NULL) xmlFree(test); } } return NULL; }