X-Git-Url: http://gitweb.scilab.org/?p=scilab.git;a=blobdiff_plain;f=scilab%2Fmodules%2Fscicos%2Fsrc%2Fcpp%2Fview_scilab%2Fports_management.hxx;h=8a549a4e211318761f11a6cb580f1121fc521bef;hp=492be051b132fa1d481fbf3118548fd33230faf1;hb=fa2dfb05ec2781159d22f1285410be765621bc53;hpb=e0ae7e0fce1334dda7c9077726bd081d57f36e38 diff --git a/scilab/modules/scicos/src/cpp/view_scilab/ports_management.hxx b/scilab/modules/scicos/src/cpp/view_scilab/ports_management.hxx index 492be05..8a549a4 100644 --- a/scilab/modules/scicos/src/cpp/view_scilab/ports_management.hxx +++ b/scilab/modules/scicos/src/cpp/view_scilab/ports_management.hxx @@ -16,11 +16,13 @@ #include #include +#include #include "internal.hxx" +#include "double.hxx" +#include "string.hxx" #include "Controller.hxx" -#include "GraphicsAdapter.hxx" namespace org_scilab_modules_scicos { @@ -30,21 +32,432 @@ namespace view_scilab /* * Return a Scilab encoded value for a property. */ -types::InternalType* get_ports_property(const GraphicsAdapter& adaptor, object_properties_t port_kind, const Controller& controller, object_properties_t p); +template +types::InternalType* get_ports_property(const Adaptor& adaptor, object_properties_t port_kind, const Controller& controller) +{ + model::Block* adaptee = adaptor.getAdaptee(); + + // Retrieve the identifiers + std::vector ids; + controller.getObjectProperty(adaptee->id(), adaptee->kind(), port_kind, ids); + + // Translate identifiers: shared variables + int i = 0; + size_t datatypeIndex = 0; + // Translate identifiers to return values + switch (p) + { + case STYLE: + case LABEL: + { + types::String* o = new types::String(ids.size(), 1); + for (std::vector::iterator it = ids.begin(); it != ids.end(); ++it, ++i) + { + std::string s; + controller.getObjectProperty(*it, PORT, p, s); + o->set(i, s.data()); + } + return o; + } + case DATATYPE_ROWS: + datatypeIndex = 0; + // no break + case DATATYPE_COLS: + datatypeIndex = 1; + // no break + case DATATYPE_TYPE: + { + datatypeIndex = 2; + + types::Double* o = new types::Double(ids.size(), 1); + for (std::vector::iterator it = ids.begin(); it != ids.end(); ++it, ++i) + { + std::vector v; + controller.getObjectProperty(*it, PORT, DATATYPE, v); + o[i] = v[datatypeIndex]; + } + return o; + } + case IMPLICIT: + { + static const wchar_t E[] = L"E"; + static const wchar_t I[] = L"I"; + types::String* o = new types::String(ids.size(), 1); + for (std::vector::iterator it = ids.begin(); it != ids.end(); ++it, ++i) + { + bool v; + controller.getObjectProperty(*it, PORT, p, v); + o->set(i, (v == false) ? E : I); + } + return o; + } + case CONNECTED_SIGNALS: + { + double* v; + types::Double* o = new types::Double(ids.size(), 1, &v); + + ScicosID diagram; + controller.getObjectProperty(adaptee->id(), adaptee->kind(), PARENT_DIAGRAM, diagram); + + std::vector children; + controller.getObjectProperty(diagram, DIAGRAM, CHILDREN, children); + + for (std::vector::iterator it = ids.begin(); it != ids.end(); ++it, ++i) + { + ScicosID id; + controller.getObjectProperty(*it, PORT, p, id); + + std::vector::iterator found = std::find(children.begin(), children.end(), id); + + if (found != children.end()) + { + v[i] = std::distance(found, children.begin()); + } + else + { + v[i] = 0; + } + } + return o; + } + default: + return 0; + } +} /* * Set a Scilab encoded values as a property. * * \note this method will return false if one of the ports does not exist */ -bool set_ports_property(const GraphicsAdapter& adaptor, object_properties_t port_kind, Controller& controller, object_properties_t p, types::InternalType* v); +template +bool set_ports_property(const Adaptor& adaptor, object_properties_t port_kind, Controller& controller, types::InternalType* v) +{ + model::Block* adaptee = adaptor.getAdaptee(); + + // Retrieve the ports identifiers + std::vector ids; + controller.getObjectProperty(adaptee->id(), adaptee->kind(), port_kind, ids); + + if (v->getType() == types::InternalType::ScilabString) + { + types::String* current = v->getAs(); + if (current->getCols() != 0 && current->getCols() != 1) + { + return false; + } + + size_t rows = current->getRows(); + if (rows != ids.size()) + { + return false; + } + + // Translate identifiers: shared variables + int i = 0; + // Translate identifiers from values + switch (p) + { + case STYLE: + case LABEL: + { + for (std::vector::iterator it = ids.begin(); it != ids.end(); ++it, ++i) + { + char* c_str = wide_string_to_UTF8(current->get(i)); + controller.setObjectProperty(*it, PORT, p, std::string(c_str)); + FREE(c_str); + } + return true; + } + case IMPLICIT: + { + static const wchar_t E[] = L"E"; + static const wchar_t I[] = L"I"; + + for (std::vector::iterator it = ids.begin(); it != ids.end(); ++it, ++i) + { + if (current->get(i) == I) + { + controller.setObjectProperty(*it, PORT, p, true); + } + else if (current->get(i) == E) + { + controller.setObjectProperty(*it, PORT, p, false); + } + else + { + return false; + } + } + return true; + } + default: + return false; + } + } + else if (v->getType() == types::InternalType::ScilabDouble) + { + types::Double* current = v->getAs(); + if (current->getCols() != 0 && current->getCols() != 1) + { + return false; + } + + size_t rows = current->getRows(); + if (rows != ids.size()) + { + return false; + } + + // Translate identifiers: shared variables + int i = 0; + size_t datatypeIndex = 0; + // Translate identifiers from values + switch (p) + { + case STYLE: + case LABEL: + // Do nothing, because if the sizes match, then there are already zero concerned ports, so no ports to update + return true; + + case DATATYPE_ROWS: + datatypeIndex = 0; + // no break + case DATATYPE_COLS: + datatypeIndex = 1; + // no break + case DATATYPE_TYPE: + { + datatypeIndex = 2; + + for (std::vector::iterator it = ids.begin(); it != ids.end(); ++it, ++i) + { + std::vector v; + controller.getObjectProperty(*it, PORT, DATATYPE, v); + + double data = current->get(i); + if (std::floor(data) != data) + { + return false; + } + + v[datatypeIndex] = static_cast(data); + controller.setObjectProperty(*it, PORT, DATATYPE, v); + } + return true; + } + + case IMPLICIT: + // Do nothing, because if the sizes match, then there are already zero concerned ports, so no ports to update + return true; + } + + } + return false; +} + +template +bool fillNewPorts(std::vector& newPorts, const std::vector& children, double* d) +{ + for (std::vector::iterator it = newPorts.begin(); it != newPorts.end(); ++it, ++d) + { + + if (p == CONNECTED_SIGNALS) // the associated link must exist + { + if (0 > *d && *d >= children.size()) + { + return false; + } + } // no check is performed for other properties as newPorts will contains value not index + + *it = static_cast(*d); + } + return true; +} + +template +void updateNewPort(ScicosID oldPort, int newPort, Controller& controller, + std::vector& children, std::vector& deletedObjects) +{ + if (p == CONNECTED_SIGNALS) + { + // update signal and manage deconnection, using newPort as a children index + ScicosID oldSignal; + controller.getObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, oldSignal); + ScicosID newSignal = children[newPort]; + if (oldSignal != newSignal) + { + // disconnect the old link + ScicosID oldSignalSrc; + controller.getObjectProperty(oldSignal, LINK, SOURCE_PORT, oldSignalSrc); + ScicosID oldSignalDst; + controller.getObjectProperty(oldSignal, LINK, DESTINATION_PORT, oldSignalDst); + ScicosID unconnected = 0; + if (oldSignalSrc == oldPort) + { + controller.setObjectProperty(oldSignalDst, PORT, CONNECTED_SIGNALS, unconnected); + } + else // oldSignalDst == oldPort + { + controller.setObjectProperty(oldSignalSrc, PORT, CONNECTED_SIGNALS, unconnected); + } + // Link de-association is not performed as the link will be removed + // connect the new link + controller.setObjectProperty(newSignal, LINK, SOURCE_PORT, 0); + controller.setObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, newSignal); + children.erase(std::find(children.begin(), children.end(), oldSignal)); + deletedObjects.push_back(oldSignal); + } + } + else + { + // update the p property, using newPort as a value + controller.setObjectProperty(oldPort, PORT, p, newPort); + } +} + +template +bool addNewPort(ScicosID newPortID, int newPort, const std::vector& children, Controller& controller) +{ + bool status = true; + if (p == CONNECTED_SIGNALS) + { + // set the connected signal if applicable, using newPort as a children index + if (newPort != 0) + { + ScicosID signal = children[newPort]; + status = controller.setObjectProperty(newPortID, PORT, CONNECTED_SIGNALS, signal); + } + } + else + { + // set the requested property, using newPort as a value + status = controller.setObjectProperty(newPortID, PORT, p, newPort); + } + + return status; +} /** * Update the ports with a specific property. * * Create ports if needed, remove ports if needed and set a default property on each port. */ -bool update_ports_with_property(const GraphicsAdapter& adaptor, object_properties_t port_kind, Controller& controller, object_properties_t p, types::InternalType* v); +template +bool update_ports_property(const Adaptor& adaptor, object_properties_t port_kind, Controller& controller, types::InternalType* v) +{ + model::Block* adaptee = adaptor.getAdaptee(); + + if (v->getType() != types::InternalType::ScilabDouble) + { + return false; + } + types::Double* value = v->getAs(); + + ScicosID parentDiagram; + controller.getObjectProperty(adaptee->id(), BLOCK, PARENT_DIAGRAM, parentDiagram); + + std::vector children; + if (parentDiagram != 0) + { + controller.getObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children); + } + + std::vector newPorts = std::vector(value->getSize()); + + // retrieve old data + std::vector oldPorts; + controller.getObjectProperty(adaptee->id(), adaptee->kind(), port_kind, oldPorts); + std::vector previousPorts = oldPorts; + + double* d = value->getReal(); + if (!fillNewPorts(newPorts, children, d)) + { + return false; + } + + std::vector deletedObjects; + + // updated ports + while (!oldPorts.empty() && !newPorts.empty()) + { + ScicosID oldPort = oldPorts.back(); + oldPorts.pop_back(); + int newPort = newPorts.back(); + newPorts.pop_back(); + + updateNewPort(oldPort, newPort, controller, children, deletedObjects); + } + + // removed ports + if (!oldPorts.empty()) + { + previousPorts.erase(previousPorts.begin() + oldPorts.size(), previousPorts.end()); + + while (!oldPorts.empty()) + { + ScicosID oldPort = oldPorts.back(); + oldPorts.pop_back(); + + ScicosID signal; + controller.getObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, signal); + if (signal != 0) + { + // the link is connected, disconnect the other side + ScicosID oldSignalSrc; + controller.getObjectProperty(signal, LINK, SOURCE_PORT, oldSignalSrc); + ScicosID oldSignalDst; + controller.getObjectProperty(signal, LINK, DESTINATION_PORT, oldSignalDst); + + ScicosID unconnected = 0; + if (oldSignalSrc == oldPort) + { + controller.setObjectProperty(oldSignalDst, PORT, CONNECTED_SIGNALS, unconnected); + } + else // oldSignalDst == oldPort + { + controller.setObjectProperty(oldSignalSrc, PORT, CONNECTED_SIGNALS, unconnected); + } + + children.erase(std::find(children.begin(), children.end(), signal)); + deletedObjects.push_back(signal); + } + + deletedObjects.push_back(oldPort); + } + + controller.setObjectProperty(adaptee->id(), BLOCK, port_kind, previousPorts); + } + + // added ports + if (!newPorts.empty()) + { + while (!newPorts.empty()) + { + int newPort = newPorts.back(); + oldPorts.pop_back(); + + ScicosID id = controller.createObject(PORT); + controller.setObjectProperty(id, PORT, SOURCE_BLOCK, adaptee->id()); + addNewPort(id, newPort, children, controller); + previousPorts.push_back(id); + } + + controller.setObjectProperty(adaptee->id(), BLOCK, port_kind, previousPorts); + } + + // remove objects from the model after de-association + if (parentDiagram != 0) + { + controller.setObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children); + } + for (std::vector::iterator it = deletedObjects.begin(); it != deletedObjects.end(); ++it) + { + controller.deleteObject(*it); + } + + return true; +} } /* view_scilab */