2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2014 - Scilab Enterprises - Paul Bignier
4 * Copyright (C) 2014 - Scilab Enterprises - Clement DAVID
6 * This file must be used under the terms of the CeCILL.
7 * This source file is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at
10 * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
14 #ifndef PORTS_MANAGEMENT_HXX_
15 #define PORTS_MANAGEMENT_HXX_
21 #include "internal.hxx"
25 #include "Controller.hxx"
27 namespace org_scilab_modules_scicos
33 * Return a Scilab encoded value for a property.
35 template<typename Adaptor, object_properties_t p>
36 types::InternalType* get_ports_property(const Adaptor& adaptor, object_properties_t port_kind, const Controller& controller)
38 model::Block* adaptee = adaptor.getAdaptee();
40 // Retrieve the identifiers
41 std::vector<ScicosID> ids;
42 controller.getObjectProperty(adaptee->id(), adaptee->kind(), port_kind, ids);
44 // Translate identifiers: shared variables
46 size_t datatypeIndex = -1;
47 // Translate identifiers to return values
53 types::String* o = new types::String(ids.size(), 1);
54 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
57 controller.getObjectProperty(*it, PORT, p, s);
72 types::Double* o = new types::Double(ids.size(), 1, &data);
73 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
76 controller.getObjectProperty(*it, PORT, DATATYPE, v);
77 data[i] = v[datatypeIndex];
84 types::Double* o = new types::Double(ids.size(), 1, &data);
85 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
87 controller.getObjectProperty(*it, PORT, p, data[i]);
93 types::String* o = new types::String(ids.size(), 1);
94 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
97 controller.getObjectProperty(*it, PORT, p, v);
98 o->set(i, (v == false) ? L"E" : L"I");
102 case CONNECTED_SIGNALS:
105 types::Double* o = new types::Double(ids.size(), 1, &v);
108 controller.getObjectProperty(adaptee->id(), adaptee->kind(), PARENT_DIAGRAM, diagram);
110 std::vector<ScicosID> children;
113 controller.getObjectProperty(diagram, DIAGRAM, CHILDREN, children);
116 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
119 controller.getObjectProperty(*it, PORT, p, id);
121 std::vector<ScicosID>::iterator found = std::find(children.begin(), children.end(), id);
123 if (found != children.end())
125 v[i] = std::distance(found, children.begin());
140 * Set a Scilab encoded values as a property.
142 * \note this method will ignore or return false if one of the ports does not exist, depending on the property setted.
144 template<typename Adaptor, object_properties_t p>
145 bool set_ports_property(const Adaptor& adaptor, object_properties_t port_kind, Controller& controller, types::InternalType* v)
147 model::Block* adaptee = adaptor.getAdaptee();
149 // Retrieve the ports identifiers
150 std::vector<ScicosID> ids;
151 controller.getObjectProperty(adaptee->id(), adaptee->kind(), port_kind, ids);
153 if (v->getType() == types::InternalType::ScilabString)
155 types::String* current = v->getAs<types::String>();
156 if (current->getSize() != ids.size())
161 // Translate identifiers: shared variables
163 // Translate identifiers from values
169 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
171 char* c_str = wide_string_to_UTF8(current->get(i));
172 controller.setObjectProperty(*it, PORT, p, std::string(c_str));
179 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
181 if (current->get(i) == L"I")
183 controller.setObjectProperty(*it, PORT, p, true);
185 else if (current->get(i) == L"E")
187 controller.setObjectProperty(*it, PORT, p, false);
200 else if (v->getType() == types::InternalType::ScilabDouble)
202 types::Double* current = v->getAs<types::Double>();
204 // Translate identifiers: shared variables
206 size_t datatypeIndex = -1;
207 // Translate identifiers from values
211 if (current->isEmpty())
216 if (current->getSize() != ids.size())
221 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
223 double firing = current->get(i);
225 controller.setObjectProperty(*it, PORT, p, firing);
230 // Do nothing, because if the sizes match, then there are already zero concerned ports, so no ports to update
243 // ignore the set without error
244 if (current->getSize() != ids.size())
249 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
252 controller.getObjectProperty(*it, PORT, DATATYPE, v);
254 double data = current->get(i);
255 if (std::floor(data) != data)
260 v[datatypeIndex] = static_cast<int>(data);
261 controller.setObjectProperty(*it, PORT, DATATYPE, v);
267 // Do nothing, because if the sizes match, then there are already zero concerned ports, so no ports to update
275 template<typename Adaptor, object_properties_t p>
276 bool fillNewPorts(std::vector<int>& newPorts, const std::vector<ScicosID>& children, double* d)
278 for (std::vector<int>::iterator it = newPorts.begin(); it != newPorts.end(); ++it, ++d)
281 if (p == CONNECTED_SIGNALS) // the associated link must exist
283 if (0 > *d && *d >= children.size())
287 } // no check is performed for other properties as newPorts will contains value not index
289 *it = static_cast<int>(*d);
294 template<typename Adaptor, object_properties_t p>
295 void updateNewPort(ScicosID oldPort, int newPort, Controller& controller,
296 std::vector<ScicosID>& children, std::vector<ScicosID>& deletedObjects)
298 if (p == CONNECTED_SIGNALS)
300 // update signal and manage deconnection, using newPort as a children index
302 controller.getObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, oldSignal);
303 ScicosID newSignal = children[newPort];
304 if (oldSignal != newSignal)
306 // disconnect the old link
307 ScicosID oldSignalSrc;
308 controller.getObjectProperty(oldSignal, LINK, SOURCE_PORT, oldSignalSrc);
309 ScicosID oldSignalDst;
310 controller.getObjectProperty(oldSignal, LINK, DESTINATION_PORT, oldSignalDst);
311 ScicosID unconnected = 0;
312 if (oldSignalSrc == oldPort)
314 controller.setObjectProperty(oldSignalDst, PORT, CONNECTED_SIGNALS, unconnected);
316 else // oldSignalDst == oldPort
318 controller.setObjectProperty(oldSignalSrc, PORT, CONNECTED_SIGNALS, unconnected);
320 // Link de-association is not performed as the link will be removed
321 // connect the new link
322 controller.setObjectProperty(newSignal, LINK, SOURCE_PORT, 0);
323 controller.setObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, newSignal);
324 children.erase(std::find(children.begin(), children.end(), oldSignal));
325 deletedObjects.push_back(oldSignal);
330 // update the p property, using newPort as a value
331 int datatypeIndex = -1;
343 std::vector<int> datatype;
344 controller.getObjectProperty(oldPort, PORT, DATATYPE, datatype);
345 datatype[datatypeIndex] = newPort;
346 controller.setObjectProperty(oldPort, PORT, DATATYPE, datatype);
350 controller.setObjectProperty(oldPort, PORT, p, newPort);
355 template<typename Adaptor, object_properties_t p>
356 bool addNewPort(ScicosID newPortID, int newPort, const std::vector<ScicosID>& children, Controller& controller)
359 if (p == CONNECTED_SIGNALS)
361 // set the connected signal if applicable, using newPort as a children index
364 ScicosID signal = children[newPort];
365 status = controller.setObjectProperty(newPortID, PORT, CONNECTED_SIGNALS, signal);
370 // set the requested property, using newPort as a value
371 int datatypeIndex = -1;
383 std::vector<int> datatype;
384 controller.getObjectProperty(newPortID, PORT, DATATYPE, datatype);
385 datatype[datatypeIndex] = newPort;
386 return controller.setObjectProperty(newPortID, PORT, DATATYPE, datatype);
389 return controller.setObjectProperty(newPortID, PORT, p, newPort);
397 * Update the ports with a specific property.
399 * Create ports if needed, remove ports if needed and set a default property on each port.
401 template<typename Adaptor, object_properties_t p>
402 bool update_ports_property(const Adaptor& adaptor, object_properties_t port_kind, Controller& controller, types::InternalType* v)
404 model::Block* adaptee = adaptor.getAdaptee();
406 if (v->getType() != types::InternalType::ScilabDouble)
410 types::Double* value = v->getAs<types::Double>();
412 ScicosID parentDiagram;
413 controller.getObjectProperty(adaptee->id(), BLOCK, PARENT_DIAGRAM, parentDiagram);
415 std::vector<ScicosID> children;
416 if (parentDiagram != 0)
418 controller.getObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children);
421 std::vector<int> newPorts (value->getSize());
424 std::vector<ScicosID> oldPorts;
425 controller.getObjectProperty(adaptee->id(), adaptee->kind(), port_kind, oldPorts);
426 std::vector<ScicosID> previousPorts = oldPorts;
428 double* d = value->getReal();
429 if (!fillNewPorts<Adaptor, p>(newPorts, children, d))
434 std::vector<ScicosID> deletedObjects;
437 while (!oldPorts.empty() && !newPorts.empty())
439 ScicosID oldPort = oldPorts.back();
441 int newPort = newPorts.back();
444 updateNewPort<Adaptor, p>(oldPort, newPort, controller, children, deletedObjects);
448 if (!oldPorts.empty())
450 previousPorts.erase(previousPorts.begin() + oldPorts.size(), previousPorts.end());
452 while (!oldPorts.empty())
454 ScicosID oldPort = oldPorts.back();
458 controller.getObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, signal);
461 // the link is connected, disconnect the other side
462 ScicosID oldSignalSrc;
463 controller.getObjectProperty(signal, LINK, SOURCE_PORT, oldSignalSrc);
464 ScicosID oldSignalDst;
465 controller.getObjectProperty(signal, LINK, DESTINATION_PORT, oldSignalDst);
467 ScicosID unconnected = 0;
468 if (oldSignalSrc == oldPort)
470 controller.setObjectProperty(oldSignalDst, PORT, CONNECTED_SIGNALS, unconnected);
472 else // oldSignalDst == oldPort
474 controller.setObjectProperty(oldSignalSrc, PORT, CONNECTED_SIGNALS, unconnected);
477 children.erase(std::find(children.begin(), children.end(), signal));
478 deletedObjects.push_back(signal);
481 deletedObjects.push_back(oldPort);
484 controller.setObjectProperty(adaptee->id(), BLOCK, port_kind, previousPorts);
488 if (!newPorts.empty())
490 while (!newPorts.empty())
492 int newPort = newPorts.back();
495 ScicosID id = controller.createObject(PORT);
496 controller.setObjectProperty(id, PORT, SOURCE_BLOCK, adaptee->id());
497 addNewPort<Adaptor, p>(id, newPort, children, controller);
498 previousPorts.push_back(id);
501 controller.setObjectProperty(adaptee->id(), BLOCK, port_kind, previousPorts);
504 // remove objects from the model after de-association
505 if (parentDiagram != 0)
507 controller.setObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children);
509 for (std::vector<ScicosID>::iterator it = deletedObjects.begin(); it != deletedObjects.end(); ++it)
511 controller.deleteObject(*it);
518 } /* namespace view_scilab */
519 } /* namespace org_scilab_modules_scicos */
521 #endif /* PORTS_MANAGEMENT_HXX_ */