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-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>
36 types::InternalType* get_ports_property(const Adaptor& adaptor, object_properties_t port_kind, const Controller& controller, object_properties_t p)
38 static const wchar_t E[] = L"E";
39 static const wchar_t I[] = L"I";
40 model::Block* adaptee = adaptor.getAdaptee();
42 // Retrieve the identifiers
43 std::vector<ScicosID> ids;
44 controller.getObjectProperty(adaptee->id(), adaptee->kind(), port_kind, ids);
46 // Translate identifiers to return values
50 case CONNECTED_SIGNALS:
53 types::Double* o = new types::Double(ids.size(), 1, &v);
56 controller.getObjectProperty(adaptee->id(), adaptee->kind(), PARENT_DIAGRAM, diagram);
58 std::vector<ScicosID> children;
59 controller.getObjectProperty(diagram, DIAGRAM, CHILDREN, children);
61 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
64 controller.getObjectProperty(*it, PORT, p, id);
66 std::vector<ScicosID>::iterator found = std::find(children.begin(), children.end(), id);
68 if (found != children.end())
70 v[i] = std::distance(found, children.begin());
82 types::String* o = new types::String(ids.size(), 1);
83 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
86 controller.getObjectProperty(*it, PORT, p, s);
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) ? E : I);
106 types::Double* o = new types::Double(ids.size(), 1);
107 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
110 controller.getObjectProperty(*it, PORT, p, v);
121 * Set a Scilab encoded values as a property.
123 * \note this method will return false if one of the ports does not exist
125 template<typename Adaptor>
126 bool set_ports_property(const Adaptor& adaptor, object_properties_t port_kind, Controller& controller, object_properties_t p, types::InternalType* v)
128 static const wchar_t E[] = L"E";
129 static const wchar_t I[] = L"I";
130 model::Block* adaptee = adaptor.getAdaptee();
132 // Retrieve the ports identifiers
133 std::vector<ScicosID> ids;
134 controller.getObjectProperty(adaptee->id(), adaptee->kind(), port_kind, ids);
136 if (v->getType() == types::InternalType::ScilabString)
138 types::String* current = v->getAs<types::String>();
139 if (current->getCols() != 0 && current->getCols() != 1)
144 size_t rows = current->getRows();
145 if (rows != ids.size())
155 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
157 if (current->get(i) == I)
159 controller.setObjectProperty(*it, PORT, p, true);
161 else if (current->get(i) == E)
163 controller.setObjectProperty(*it, PORT, p, false);
175 std::vector<std::string> style = std::vector<std::string>(current->getSize());
176 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
178 char* c_str = wide_string_to_UTF8(current->get(i));
179 style[i] = std::string(c_str);
181 controller.setObjectProperty(*it, PORT, p, style[i]);
189 else if (v->getType() == types::InternalType::ScilabDouble)
191 types::Double* current = v->getAs<types::Double>();
192 if (current->getRows() != 0 || current->getCols() != 0)
200 // Do nothing, because if the sizes match, then there are already zero concerned ports, so no ports to update
207 * Update the ports with a specific property.
209 * Create ports if needed, remove ports if needed and set a default property on each port.
211 template<typename Adaptor>
212 bool update_ports_with_property(const Adaptor& adaptor, object_properties_t port_kind, Controller& controller, object_properties_t p, types::InternalType* v)
214 model::Block* adaptee = adaptor.getAdaptee();
216 if (v->getType() != types::InternalType::ScilabDouble)
220 types::Double* value = v->getAs<types::Double>();
222 ScicosID parentDiagram;
223 controller.getObjectProperty(adaptee->id(), BLOCK, PARENT_DIAGRAM, parentDiagram);
225 std::vector<ScicosID> children;
226 if (parentDiagram != 0)
228 controller.getObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children);
231 std::vector<int> newPorts = std::vector<int>(value->getSize());
234 std::vector<ScicosID> oldPorts;
235 controller.getObjectProperty(adaptee->id(), adaptee->kind(), port_kind, oldPorts);
236 std::vector<ScicosID> previousPorts = oldPorts;
238 double* d = value->getReal();
239 if (p == CONNECTED_SIGNALS)
241 for (std::vector<int>::iterator it = newPorts.begin(); it != newPorts.end(); ++it, ++d)
243 if (0 > *d && *d >= children.size())
253 // Here, we are modyfing either 'in', 'in2' or 'intyp', so the Port ids must remain the same as much as possible (copy the old ones),
254 // and set the new ones to zero (unconnected) if there are any (insert them at the beginning of newPorts).
255 if (newPorts.size() != 0)
258 if (newPorts.size() >= oldPorts.size())
260 std::fill(newPorts.begin(), newPorts.begin() + newPorts.size() - oldPorts.size(), 0);
261 std::copy(oldPorts.begin(), oldPorts.end(), newPorts.begin() + newPorts.size() - oldPorts.size() + 1);
263 else if (newPorts.size() < oldPorts.size())
265 std::copy(oldPorts.begin(), oldPorts.begin() + newPorts.size(), newPorts.begin());
269 std::vector<ScicosID> deletedObjects;
272 while (!oldPorts.empty() && !newPorts.empty())
274 ScicosID oldPort = oldPorts.back();
276 int newPort = newPorts.back();
280 controller.getObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, oldSignal);
281 ScicosID newSignal = children[newPort];
283 if (p == CONNECTED_SIGNALS)
285 if (oldSignal != newSignal)
287 // disconnect the old link
288 ScicosID oldSignalSrc;
289 controller.getObjectProperty(oldSignal, LINK, SOURCE_PORT, oldSignalSrc);
290 ScicosID oldSignalDst;
291 controller.getObjectProperty(oldSignal, LINK, DESTINATION_PORT, oldSignalDst);
293 ScicosID unconnected = 0;
294 if (oldSignalSrc == oldPort)
296 controller.setObjectProperty(oldSignalDst, PORT, CONNECTED_SIGNALS, unconnected);
298 else // oldSignalDst == oldPort
300 controller.setObjectProperty(oldSignalSrc, PORT, CONNECTED_SIGNALS, unconnected);
302 // Link de-association is not performed as the link will be removed
304 // connect the new link
305 controller.setObjectProperty(newSignal, LINK, SOURCE_PORT, 0);
306 controller.setObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, newSignal);
308 children.erase(std::find(children.begin(), children.end(), oldSignal));
309 deletedObjects.push_back(oldSignal);
314 // The common port ids (CONNECTED_SIGNALS property) remain the same, so just update the p property
315 controller.setObjectProperty(oldPort, PORT, p, d[newPorts.size() - 1]);
320 if (!oldPorts.empty())
322 previousPorts.erase(previousPorts.begin() + oldPorts.size(), previousPorts.end());
324 while (!oldPorts.empty())
326 ScicosID oldPort = oldPorts.back();
330 controller.getObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, signal);
333 // the link is connected, disconnect the other side
334 ScicosID oldSignalSrc;
335 controller.getObjectProperty(signal, LINK, SOURCE_PORT, oldSignalSrc);
336 ScicosID oldSignalDst;
337 controller.getObjectProperty(signal, LINK, DESTINATION_PORT, oldSignalDst);
339 ScicosID unconnected = 0;
340 if (oldSignalSrc == oldPort)
342 controller.setObjectProperty(oldSignalDst, PORT, CONNECTED_SIGNALS, unconnected);
344 else // oldSignalDst == oldPort
346 controller.setObjectProperty(oldSignalSrc, PORT, CONNECTED_SIGNALS, unconnected);
349 children.erase(std::find(children.begin(), children.end(), signal));
350 deletedObjects.push_back(signal);
353 deletedObjects.push_back(oldPort);
356 controller.setObjectProperty(adaptee->id(), BLOCK, port_kind, previousPorts);
360 if (!newPorts.empty())
362 while (!newPorts.empty())
364 int newPort = newPorts.back();
367 ScicosID id = controller.createObject(PORT);
368 controller.setObjectProperty(id, PORT, SOURCE_BLOCK, adaptee->id());
369 if (p != CONNECTED_SIGNALS)
371 // In addition to setting the signal to 0 (the 0s at the start of newPorts), set the requested property
372 controller.setObjectProperty(id, PORT, p, d[newPorts.size() - 1]);
374 // set the connected signal if applicable
377 ScicosID signal = children[newPort];
378 controller.setObjectProperty(id, PORT, CONNECTED_SIGNALS, signal);
381 previousPorts.push_back(id);
384 controller.setObjectProperty(adaptee->id(), BLOCK, port_kind, previousPorts);
387 // remove objects from the model after de-association
388 if (parentDiagram != 0)
390 controller.setObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children);
392 for (std::vector<ScicosID>::iterator it = deletedObjects.begin(); it != deletedObjects.end(); ++it)
394 controller.deleteObject(*it);
402 } /* namespace org_scilab_modules_scicos */
404 #endif /* PORTS_MANAGEMENT_HXX_ */