ewol/sources/ewol/object/Object.cpp

452 lines
13 KiB
C++

/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license BSD v3 (see license file)
*/
#include <ewol/object/Object.h>
#include <ewol/object/Manager.h>
#include <ewol/debug.h>
#include <ewol/context/Context.h>
#include <ewol/object/MultiCast.h>
#undef __class__
#define __class__ "ewol::object::Shared<ewol::Object>"
const char* const ewol::Object::configName = "name";
size_t ewol::Object::m_valUID = 0;
void ewol::Object::objRefCountIncrement() {
std::unique_lock<std::mutex> lock(m_lockRefCount);
m_objRefCount++;
}
void ewol::Object::objRefCountDecrement() {
std::unique_lock<std::mutex> lock(m_lockRefCount);
m_objRefCount--;
}
bool ewol::Object::setRefOwner(bool _haveOwner) {
std::unique_lock<std::mutex> lock(m_lockRefCount);
if (_haveOwner == true) {
if (m_hasReferenceOwner == true) {
EWOL_CRITICAL("Object have already an owner");
return false;;
}
m_hasReferenceOwner = true;
return true;
}
if (m_hasReferenceOwner == false) {
EWOL_CRITICAL("Object have already NO owner");
return false;
}
m_hasReferenceOwner = false;
return true;
}
void ewol::Object::operator delete(void* _ptr, std::size_t _sz) {
EWOL_DEBUG("custom delete for size " << _sz);
ewol::object::Shared<ewol::Object> obj = (ewol::Object*)_ptr;
obj->objRefCountDecrement();
if (obj->m_objRefCount <= 0) {
EWOL_DEBUG(" ==> real remove");
if (obj->m_hasReferenceOwner == true) {
EWOL_ERROR(" ==> Remove ofject that have not a reference owner removed");
}
::operator delete(_ptr);
} else {
EWOL_DEBUG(" ==> Some user is link on it ...");
}
}
void ewol::Object::operator delete[](void* _ptr, std::size_t _sz) {
EWOL_CRITICAL("custom delete for size ==> not implemented ..." << _sz);
::operator delete(_ptr);
}
ewol::Object::Object() :
m_objRefCount(1),
m_hasReferenceOwner(false),
m_static(false),
m_isResource(false) {
// note this is nearly atomic ... (but it is enough)
m_uniqueId = m_valUID++;
EWOL_DEBUG("new Object : [" << m_uniqueId << "]");
getObjectManager().add(this);
registerConfig(configName, "string", NULL, "Object name, might be a unique reference in all the program");
}
ewol::Object::Object(const std::string& _name) :
m_objRefCount(1),
m_static(false),
m_name(_name),
m_isResource(false) {
// note this is nearly atomic ... (but it is enough)
m_uniqueId = m_valUID++;
EWOL_DEBUG("new Object : [" << m_uniqueId << "]");
getObjectManager().add(this);
registerConfig(configName, "string", NULL, "Object name, might be a unique reference in all the program");
}
ewol::Object::~Object() {
EWOL_DEBUG("delete Object : [" << m_uniqueId << "] : " << getTypeDescription());
getObjectManager().rm(this);
getMultiCast().rm(this);
for (size_t iii=0; iii<m_externEvent.size(); iii++) {
if (NULL!=m_externEvent[iii]) {
delete(m_externEvent[iii]);
m_externEvent[iii] = NULL;
}
}
m_externEvent.clear();
m_availlableEventId.clear();
m_uniqueId = -1;
}
const char * const ewol::Object::getObjectType() {
if (m_listType.size() == 0) {
return "ewol::object::Shared<ewol::Object>";
}
return m_listType.back();
}
void ewol::Object::addObjectType(const char* _type) {
if (_type == NULL) {
EWOL_ERROR(" try to add a type with no value...");
return;
}
m_listType.push_back(_type);
}
std::string ewol::Object::getTypeDescription() {
std::string ret("ewol::object::Shared<ewol::Object>");
for(auto element : m_listType) {
ret += "|";
ret += element;
}
return ret;
}
bool ewol::Object::isTypeCompatible(const std::string& _type) {
if (_type == "ewol::object::Shared<ewol::Object>") {
return true;
}
for(auto element : m_listType) {
if (_type == element) {
return true;
}
}
return false;
}
void ewol::Object::autoDestroy() {
getObjectManager().autoRemove(this);
}
void ewol::Object::removeObject() {
getObjectManager().autoRemove(this);
}
void ewol::Object::addEventId(const char * _generateEventId) {
if (NULL != _generateEventId) {
m_availlableEventId.push_back(_generateEventId);
}
}
void ewol::Object::generateEventId(const char * _generateEventId, const std::string& _data) {
int32_t nbObject = getObjectManager().getNumberObject();
EWOL_VERBOSE("try send message '" << _generateEventId << "'");
// for every element registered ...
for (size_t iii=0; iii<m_externEvent.size(); iii++) {
if (NULL==m_externEvent[iii]) {
EWOL_VERBOSE(" Null pointer");
continue;
}
// if we find the event ...
if (m_externEvent[iii]->localEventId != _generateEventId) {
EWOL_VERBOSE(" wrong event '" << m_externEvent[iii]->localEventId << "' != '" << _generateEventId << "'");
continue;
}
if (m_externEvent[iii]->destObject == NULL) {
EWOL_VERBOSE(" NULL dest");
continue;
}
if (m_externEvent[iii]->overloadData.size() <= 0){
ewol::object::Message tmpMsg(this, m_externEvent[iii]->destEventId, _data);
EWOL_VERBOSE("send message " << tmpMsg);
m_externEvent[iii]->destObject->onReceiveMessage(tmpMsg);
} else {
// set the user requested data ...
ewol::object::Message tmpMsg(this, m_externEvent[iii]->destEventId, m_externEvent[iii]->overloadData);
EWOL_VERBOSE("send message " << tmpMsg);
m_externEvent[iii]->destObject->onReceiveMessage(tmpMsg);
}
}
if (nbObject > getObjectManager().getNumberObject()) {
EWOL_CRITICAL("It if really dangerous ro remove (delete) element inside a callback ... use ->removObject() which is asynchronous");
}
}
void ewol::Object::sendMultiCast(const char* const _messageId, const std::string& _data) {
int32_t nbObject = getObjectManager().getNumberObject();
getMultiCast().send(this, _messageId, _data);
if (nbObject > getObjectManager().getNumberObject()) {
EWOL_CRITICAL("It if really dangerous ro remove (delete) element inside a callback ... use ->removObject() which is asynchronous");
}
}
void ewol::Object::registerMultiCast(const char* const _messageId) {
getMultiCast().add(this, _messageId);
}
void ewol::Object::registerOnEvent(ewol::object::Shared<ewol::Object> _destinationObject,
const char * _eventId,
const char * _eventIdgenerated,
const std::string& _overloadData) {
if (NULL == _destinationObject) {
EWOL_ERROR("Input ERROR NULL pointer Object ...");
return;
}
if (NULL == _eventId) {
EWOL_ERROR("Input ERROR NULL pointer Event Id...");
return;
}
if ( _eventId[0] == '*'
&& _eventId[1] == '\0') {
EWOL_VERBOSE("Register on all event ...");
for(size_t iii=0; iii<m_availlableEventId.size(); iii++) {
ewol::object::EventExtGen * tmpEvent = new ewol::object::EventExtGen();
if (NULL == tmpEvent) {
EWOL_ERROR("Allocation error in Register Event...");
continue;
}
tmpEvent->localEventId = m_availlableEventId[iii];
tmpEvent->destObject = _destinationObject;
tmpEvent->overloadData = _overloadData;
if (NULL != _eventIdgenerated) {
tmpEvent->destEventId = _eventIdgenerated;
} else {
tmpEvent->destEventId = m_availlableEventId[iii];
}
m_externEvent.push_back(tmpEvent);
}
return;
}
// check if event existed :
bool findIt = false;
for(size_t iii=0; iii<m_availlableEventId.size(); iii++) {
if (m_availlableEventId[iii] == _eventId) {
findIt = true;
break;
}
}
if (false == findIt) {
EWOL_VERBOSE("Try to register with a NON direct string name");
for(size_t iii=0; iii<m_availlableEventId.size(); iii++) {
if (0 == strncmp(m_availlableEventId[iii], _eventId, 1024)) {
findIt = true;
_eventId = m_availlableEventId[iii];
EWOL_VERBOSE("find event ID : '" << _eventId << "' ==> '" << _eventIdgenerated << "'");
break;
}
}
}
if (false == findIt) {
EWOL_ERROR("Can not register event on this Type=" << getObjectType() << " event=\"" << _eventId << "\" == > unknow event");
return;
}
ewol::object::EventExtGen * tmpEvent = new ewol::object::EventExtGen();
if (NULL == tmpEvent) {
EWOL_ERROR("Allocation error in Register Event...");
return;
}
tmpEvent->localEventId = _eventId;
tmpEvent->destObject = _destinationObject;
tmpEvent->overloadData = _overloadData;
if (NULL != _eventIdgenerated) {
tmpEvent->destEventId = _eventIdgenerated;
} else {
tmpEvent->destEventId = _eventId;
}
m_externEvent.push_back(tmpEvent);
}
void ewol::Object::unRegisterOnEvent(ewol::object::Shared<ewol::Object> _destinationObject,
const char * _eventId) {
if (NULL == _destinationObject) {
EWOL_ERROR("Input ERROR NULL pointer Object ...");
return;
}
// check if event existed :
for(int64_t iii = m_externEvent.size()-1; iii >= 0; --iii) {
if (m_externEvent[iii] == NULL) {
continue;
}
if (m_externEvent[iii]->destObject != _destinationObject) {
continue;
}
if (_eventId == NULL) {
m_externEvent.erase(m_externEvent.begin()+iii);
} else if (m_externEvent[iii]->localEventId == _eventId) {
m_externEvent.erase(m_externEvent.begin()+iii);
}
}
}
void ewol::Object::onObjectRemove(ewol::object::Shared<ewol::Object> _object) {
for(int32_t iii=m_externEvent.size()-1; iii >= 0; iii--) {
if ( m_externEvent[iii] != nullptr
&& m_externEvent[iii]->destObject.hasOwner() == false) {
m_externEvent.erase(m_externEvent.begin()+iii);
}
}
}
void ewol::Object::registerConfig(const char* _config,
const char* _type,
const char* _control,
const char* _description,
const char* _default) {
if (NULL == _config) {
EWOL_ERROR("Try to add NULL config");
return;
}
for(size_t iii=0 ; iii<m_listConfig.size() ; iii++) {
if (NULL != m_listConfig[iii].getConfig()) {
if (0 == strcmp(m_listConfig[iii].getConfig(), _config) ) {
EWOL_ERROR("Try to add config already added : " << _config << " at pos=" << iii);
}
}
}
m_listConfig.push_back(ewol::object::ConfigElement(_config, _type, _control, _description, _default));
}
bool ewol::Object::loadXML(exml::Element* _node) {
if (NULL == _node) {
return false;
}
bool errorOccured = true;
for(size_t iii=0 ; iii<m_listConfig.size() ; iii++) {
if (m_listConfig[iii].getConfig() == NULL) {
continue;
}
if (_node->existAttribute(m_listConfig[iii].getConfig()) == false) {
continue;
}
std::string value = _node->getAttribute(m_listConfig[iii].getConfig());
if (false == setConfig(ewol::object::Config(m_listConfig[iii].getConfig(), value) ) ) {
errorOccured = false;
}
}
return errorOccured;
}
bool ewol::Object::storeXML(exml::Element* _node) const {
if (NULL == _node) {
return false;
}
bool errorOccured = true;
for(size_t iii=0 ; iii<m_listConfig.size() ; iii++) {
if (m_listConfig[iii].getConfig() == NULL) {
continue;
}
std::string value = getConfig(m_listConfig[iii].getConfig());
if (NULL != m_listConfig[iii].getDefault() ) {
if (value == m_listConfig[iii].getDefault() ) {
// nothing to add on the XML :
continue;
}
}
// add attribute ... == > note : add special element when '"' element detected ...
_node->setAttribute(m_listConfig[iii].getConfig(), value);
}
return errorOccured;
}
bool ewol::Object::onSetConfig(const ewol::object::Config& _conf) {
EWOL_VERBOSE("[" << getId() << "] {" << getObjectType() << "} set config : " << _conf);
if (_conf.getConfig() == configName) {
EWOL_VERBOSE("[" << getId() << "] {" << getObjectType() << "} set config name : \"" << _conf.getData() << "\"");
setName(_conf.getData());
return true;
}
return false;
}
bool ewol::Object::onGetConfig(const char* _config, std::string& _result) const {
if (_config == configName) {
_result = getName();
return true;
}
return false;
}
bool ewol::Object::setConfig(const std::string& _config, const std::string& _value) {
for(size_t iii=0 ; iii<m_listConfig.size() ; iii++) {
if (NULL != m_listConfig[iii].getConfig()) {
if (_config == m_listConfig[iii].getConfig() ) {
// call config with standard parameter
return setConfig(ewol::object::Config(m_listConfig[iii].getConfig(), _value));
}
}
}
EWOL_ERROR(" parameter is not in the list : \"" << _config << "\"" );
return false;
}
std::string ewol::Object::getConfig(const char* _config) const {
std::string res="";
if (NULL != _config) {
onGetConfig(_config, res);
}
return res;
}
std::string ewol::Object::getConfig(const std::string& _config) const {
for(size_t iii=0 ; iii<m_listConfig.size() ; iii++) {
if (NULL != m_listConfig[iii].getConfig()) {
if (_config == m_listConfig[iii].getConfig() ) {
// call config with standard parameter
return getConfig(m_listConfig[iii].getConfig());
}
}
}
EWOL_ERROR(" parameter is not in the list : \"" << _config << "\"" );
return "";
}
bool ewol::Object::setConfigNamed(const std::string& _objectName, const ewol::object::Config& _conf) {
ewol::object::Shared<ewol::Object> object = getObjectManager().get(_objectName);
if (object == NULL) {
return false;
}
return object->setConfig(_conf);
}
bool ewol::Object::setConfigNamed(const std::string& _objectName, const std::string& _config, const std::string& _value) {
ewol::object::Shared<ewol::Object> object = getObjectManager().get(_objectName);
if (object == NULL) {
return false;
}
return object->setConfig(_config, _value);
}
ewol::object::Manager& ewol::Object::getObjectManager() {
return ewol::getContext().getEObjectManager();
}
ewol::object::MultiCast& ewol::Object::getMultiCast() {
return ewol::getContext().getEObjectManager().multiCast();
}
ewol::Context& ewol::Object::getContext() {
return ewol::getContext();
}