2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2014-2016 - Scilab Enterprises - Clement DAVID
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
7 * This file is hereby licensed under the terms of the GNU GPL v2.0,
8 * pursuant to article 5.3.4 of the CeCILL v.2.1.
9 * This file was originally licensed under the terms of the CeCILL v2.1,
10 * and continues to be available under such terms.
11 * For more information, see the COPYING file which you should have received
12 * along with this program.
30 #include "utilities.hxx"
31 #include "Controller.hxx"
32 #include "GraphicsAdapter.hxx"
33 #include "ports_management.hxx"
34 #include "controller_helpers.hxx"
36 #include "var2vec.hxx"
37 #include "vec2var.hxx"
40 #include "localization.h"
41 #include "sci_malloc.h"
42 #include "charEncoding.h"
45 namespace org_scilab_modules_scicos
52 const std::wstring MBLOCK (L"MBLOCK");
53 const std::wstring MPBLOCK (L"MPBLOCK");
54 const std::wstring in (L"in");
55 const std::wstring intype (L"intype");
56 const std::wstring out (L"out");
57 const std::wstring outtype (L"outtype");
58 const std::wstring param (L"param");
59 const std::wstring paramv (L"paramv");
60 const std::wstring pprop (L"pprop");
61 const std::wstring nameF (L"nameF");
62 const std::wstring funtxt (L"funtxt");
64 // shared informations for relinking across adapters hierarchy
65 std::map<ScicosID, std::vector<int> > partial_pin;
66 std::map<ScicosID, std::vector<int> > partial_pout;
67 std::map<ScicosID, std::vector<int> > partial_pein;
68 std::map<ScicosID, std::vector<int> > partial_peout;
73 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& controller)
76 types::Double* o = new types::Double(1, 2, &data);
77 model::Block* adaptee = adaptor.getAdaptee();
79 std::vector<double> geom;
80 controller.getObjectProperty(adaptee, GEOMETRY, geom);
88 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& controller)
91 if (v->getType() != types::InternalType::ScilabDouble)
93 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Real matrix expected.\n"), "graphics", "orig");
97 types::Double* current = v->getAs<types::Double>();
98 if (current->getSize() != 2)
100 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: %d-by-%d expected.\n"), "graphics", "orig", 1, 2);
104 model::Block* adaptee = adaptor.getAdaptee();
105 std::vector<double> geom;
106 controller.getObjectProperty(adaptee, GEOMETRY, geom);
108 geom[0] = current->get(0);
109 geom[1] = current->get(1);
111 controller.setObjectProperty(adaptee, GEOMETRY, geom);
119 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& controller)
122 types::Double* o = new types::Double(1, 2, &data);
123 model::Block* adaptee = adaptor.getAdaptee();
125 std::vector<double> geom;
126 controller.getObjectProperty(adaptee, GEOMETRY, geom);
133 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& controller)
135 if (v->getType() != types::InternalType::ScilabDouble)
137 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Real matrix expected.\n"), "graphics", "sz");
141 types::Double* current = v->getAs<types::Double>();
142 if (current->getSize() != 2)
144 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: %d-by-%d expected.\n"), "graphics", "sz", 1, 2);
148 model::Block* adaptee = adaptor.getAdaptee();
149 std::vector<double> geom;
150 controller.getObjectProperty(adaptee, GEOMETRY, geom);
152 geom[2] = current->get(0);
153 geom[3] = current->get(1);
155 controller.setObjectProperty(adaptee, GEOMETRY, geom);
163 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& controller)
165 model::Block* adaptee = adaptor.getAdaptee();
167 std::vector<double> exprs;
168 controller.getObjectProperty(adaptee, EXPRS, exprs);
170 types::InternalType* res;
171 if (!vec2var(exprs, res))
173 // if invalid data, return a valid value
174 return types::Double::Empty();
179 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& controller)
181 model::Block* adaptee = adaptor.getAdaptee();
183 // Corner-case the content is an empty matrix
184 if (v->getType() == types::InternalType::ScilabDouble)
186 types::Double* current = v->getAs<types::Double>();
187 if (!current->isEmpty())
193 std::vector<double> exprs;
194 if (!var2vec(v, exprs))
198 controller.setObjectProperty(adaptee, EXPRS, exprs);
203 std::vector<int> cached_ports_init(std::map<ScicosID, std::vector<int> >& cache, model::Block* adaptee, const object_properties_t port_kind, const Controller& controller)
205 auto it = cache.find(adaptee->id());
206 if (it != cache.end())
208 // if already present, do not refresh it !
212 std::vector<ScicosID> ids;
213 controller.getObjectProperty(adaptee, port_kind, ids);
215 std::vector<ScicosID> children;
216 ScicosID parentBlock;
217 controller.getObjectProperty(adaptee, PARENT_BLOCK, parentBlock);
218 if (parentBlock == ScicosID())
220 // Adding to a diagram
221 ScicosID parentDiagram;
222 controller.getObjectProperty(adaptee, PARENT_DIAGRAM, parentDiagram);
224 controller.getObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children);
228 // Adding to a superblock
229 controller.getObjectProperty(parentBlock, BLOCK, CHILDREN, children);
232 std::vector<int> ret(ids.size());
233 // foreach ports, resolve it or discard
235 for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
238 controller.getObjectProperty(*it, PORT, CONNECTED_SIGNALS, id);
240 if (id == ScicosID())
242 // Unconnected port, no need to search in 'children'
247 std::vector<ScicosID>::iterator found = std::find(children.begin(), children.end(), id);
248 if (found != children.end())
250 ret[i] = static_cast<int>(std::distance(children.begin(), found)) + 1;
254 // connected link not found ; discard it !
260 cache.insert({adaptee->id(), ret});
264 types::InternalType* cached_ports_get(std::map<ScicosID, std::vector<int> >& cache, const GraphicsAdapter& adaptor, const object_properties_t port_kind, const Controller& controller)
266 auto it = cache.find(adaptor.getAdaptee()->id());
267 if (it == cache.end())
269 return get_ports_property<GraphicsAdapter, CONNECTED_SIGNALS>(adaptor, port_kind, controller);
272 std::vector<int> const& ports = it->second;
275 types::Double* ret = new types::Double(static_cast<int>(ports.size()), 1, &data);
278 std::transform(ports.begin(), ports.end(), stdext::checked_array_iterator<double*>(data, ports.size()), [](int p)
283 std::transform(ports.begin(), ports.end(), data, [](int p)
291 bool cached_ports_set(std::map<ScicosID, std::vector<int> >& cache, GraphicsAdapter& adaptor, const object_properties_t port_kind, Controller& controller, types::InternalType* v)
293 auto it = cache.find(adaptor.getAdaptee()->id());
294 if (it == cache.end())
296 return update_ports_property<GraphicsAdapter, CONNECTED_SIGNALS>(adaptor, port_kind, controller, v);
299 if (v->getType() != types::InternalType::ScilabDouble)
303 types::Double* value = v->getAs<types::Double>();
305 // store the updated value locally
307 std::vector<int>& ports = it->second;
309 ports.resize(value->getSize());
310 for (int i = 0; i < value->getSize(); ++i)
312 ports[i] = static_cast<int>(value->get(i));
316 // enforce a the same number of port on the Model
318 const std::vector<int>& ports = it->second;
320 std::vector<ScicosID> objects;
321 controller.getObjectProperty(adaptor.getAdaptee(), port_kind, objects);
323 if (ports.size() < objects.size())
325 // remove existing ports
326 for (size_t i = ports.size(); i < objects.size(); ++i)
328 ScicosID p = objects[i];
331 controller.getObjectProperty(p, PORT, CONNECTED_SIGNALS, signal);
332 if (signal != ScicosID())
334 model::Link* link = controller.getBaseObject<model::Link>(signal);
336 controller.getObjectProperty(link, DESTINATION_PORT, opposite);
339 controller.setObjectProperty(link, DESTINATION_PORT, ScicosID());
341 controller.getObjectProperty(link, SOURCE_PORT, opposite);
344 controller.setObjectProperty(link, SOURCE_PORT, ScicosID());
347 controller.deleteObject(p);
349 objects.resize(ports.size());
354 for (size_t i = objects.size(); i < ports.size(); ++i)
356 model::Port* p = controller.createBaseObject<model::Port>(PORT);
358 controller.setObjectProperty(p, SOURCE_BLOCK, adaptor.getAdaptee()->id());
359 controller.setObjectProperty(p, PORT_KIND, port_from_property(port_kind));
361 objects.push_back(p->id());
364 controller.setObjectProperty(adaptor.getAdaptee(), port_kind, objects);
372 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& controller)
374 return cached_ports_get(partial_pin, adaptor, INPUTS, controller);
377 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& controller)
379 return cached_ports_set(partial_pin, adaptor, INPUTS, controller, v);
386 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& controller)
388 return cached_ports_get(partial_pout, adaptor, OUTPUTS, controller);
391 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& controller)
393 return cached_ports_set(partial_pout, adaptor, OUTPUTS, controller, v);
400 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& controller)
402 return cached_ports_get(partial_pein, adaptor, EVENT_INPUTS, controller);
405 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& controller)
407 return cached_ports_set(partial_pein, adaptor, EVENT_INPUTS, controller, v);
414 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& controller)
416 return cached_ports_get(partial_peout, adaptor, EVENT_OUTPUTS, controller);
419 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& controller)
421 return cached_ports_set(partial_peout, adaptor, EVENT_OUTPUTS, controller, v);
428 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& /*controller*/)
430 return adaptor.getGrIContent();
433 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& /*controller*/)
435 adaptor.setGrIContent(v);
443 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& controller)
445 ScicosID adaptee = adaptor.getAdaptee()->id();
448 controller.getObjectProperty(adaptee, BLOCK, DESCRIPTION, id);
450 types::String* o = new types::String(1, 1);
451 o->set(0, id.data());
456 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& controller)
458 if (v->getType() != types::InternalType::ScilabString)
460 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: string expected.\n"), "graphics", "id");
464 types::String* current = v->getAs<types::String>();
465 if (!current->isScalar())
467 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: %d-by-%d expected.\n"), "graphics", "id", 1, 1);
471 ScicosID adaptee = adaptor.getAdaptee()->id();
473 char* c_str = wide_string_to_UTF8(current->get(0));
474 std::string id(c_str);
477 controller.setObjectProperty(adaptee, BLOCK, DESCRIPTION, id);
485 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& controller)
487 return get_ports_property<GraphicsAdapter, IMPLICIT>(adaptor, INPUTS, controller);
490 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& controller)
492 return set_ports_property<GraphicsAdapter, IMPLICIT>(adaptor, INPUTS, controller, v);
499 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& controller)
501 return get_ports_property<GraphicsAdapter, IMPLICIT>(adaptor, OUTPUTS, controller);
504 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& controller)
506 return set_ports_property<GraphicsAdapter, IMPLICIT>(adaptor, OUTPUTS, controller, v);
513 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& controller)
515 return get_ports_property<GraphicsAdapter, STYLE>(adaptor, INPUTS, controller);
518 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& controller)
520 return set_ports_property<GraphicsAdapter, STYLE>(adaptor, INPUTS, controller, v);
527 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& controller)
529 return get_ports_property<GraphicsAdapter, STYLE>(adaptor, OUTPUTS, controller);
532 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& controller)
534 return set_ports_property<GraphicsAdapter, STYLE>(adaptor, OUTPUTS, controller, v);
541 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& controller)
543 return get_ports_property<GraphicsAdapter, LABEL>(adaptor, INPUTS, controller);
546 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& controller)
548 return set_ports_property<GraphicsAdapter, LABEL>(adaptor, INPUTS, controller, v);
555 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& controller)
557 return get_ports_property<GraphicsAdapter, LABEL>(adaptor, OUTPUTS, controller);
560 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& controller)
562 return set_ports_property<GraphicsAdapter, LABEL>(adaptor, OUTPUTS, controller, v);
569 static types::InternalType* get(const GraphicsAdapter& adaptor, const Controller& controller)
571 model::Block* adaptee = adaptor.getAdaptee();
574 controller.getObjectProperty(adaptee, STYLE, style);
576 return new types::String(style.c_str());
579 static bool set(GraphicsAdapter& adaptor, types::InternalType* v, Controller& controller)
581 model::Block* adaptee = adaptor.getAdaptee();
582 if (v->getType() == types::InternalType::ScilabString)
584 types::String* current = v->getAs<types::String>();
585 if (!current->isScalar())
587 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: %d-by-%d expected.\n"), "graphics", "style", 1, 1);
591 char* c_str = wide_string_to_UTF8(current->get(0));
592 std::string style(c_str);
595 controller.setObjectProperty(adaptee, STYLE, style);
598 else if (v->getType() == types::InternalType::ScilabDouble)
600 types::Double* current = v->getAs<types::Double>();
601 if (current->getSize() != 0)
603 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: string expected.\n"), "graphics", "style");
608 controller.setObjectProperty(adaptee, STYLE, style);
612 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: string expected.\n"), "graphics", "style");
619 template<> property<GraphicsAdapter>::props_t property<GraphicsAdapter>::fields = property<GraphicsAdapter>::props_t();
620 static void initialize_fields()
622 if (property<GraphicsAdapter>::properties_have_not_been_set())
624 property<GraphicsAdapter>::reserve_properties(16);
625 property<GraphicsAdapter>::add_property(L"orig", &orig::get, &orig::set);
626 property<GraphicsAdapter>::add_property(L"sz", &sz::get, &sz::set);
627 property<GraphicsAdapter>::add_property(L"exprs", &exprs::get, &exprs::set);
628 property<GraphicsAdapter>::add_property(L"pin", &pin::get, &pin::set);
629 property<GraphicsAdapter>::add_property(L"pout", &pout::get, &pout::set);
630 property<GraphicsAdapter>::add_property(L"pein", &pein::get, &pein::set);
631 property<GraphicsAdapter>::add_property(L"peout", &peout::get, &peout::set);
632 property<GraphicsAdapter>::add_property(L"gr_i", &gr_i::get, &gr_i::set);
633 property<GraphicsAdapter>::add_property(L"id", &id::get, &id::set);
634 property<GraphicsAdapter>::add_property(L"in_implicit", &in_implicit::get, &in_implicit::set);
635 property<GraphicsAdapter>::add_property(L"out_implicit", &out_implicit::get, &out_implicit::set);
636 property<GraphicsAdapter>::add_property(L"in_style", &in_style::get, &in_style::set);
637 property<GraphicsAdapter>::add_property(L"out_style", &out_style::get, &out_style::set);
638 property<GraphicsAdapter>::add_property(L"in_label", &in_label::get, &in_label::set);
639 property<GraphicsAdapter>::add_property(L"out_label", &out_label::get, &out_label::set);
640 property<GraphicsAdapter>::add_property(L"style", &style::get, &style::set);
641 property<GraphicsAdapter>::shrink_to_fit();
645 GraphicsAdapter::GraphicsAdapter() :
646 BaseAdapter<GraphicsAdapter, org_scilab_modules_scicos::model::Block>(),
647 gr_i_content(reference_value(types::Double::Empty()))
652 GraphicsAdapter::GraphicsAdapter(const Controller& c, model::Block* adaptee) :
653 BaseAdapter<GraphicsAdapter, org_scilab_modules_scicos::model::Block>(c, adaptee),
654 gr_i_content(reference_value(types::Double::Empty()))
658 Controller controller;
659 cached_ports_init(partial_pin, adaptee, INPUTS, controller);
660 cached_ports_init(partial_pout, adaptee, OUTPUTS, controller);
661 cached_ports_init(partial_pein, adaptee, EVENT_INPUTS, controller);
662 cached_ports_init(partial_peout, adaptee, EVENT_OUTPUTS, controller);
665 GraphicsAdapter::~GraphicsAdapter()
667 gr_i_content->DecreaseRef();
668 gr_i_content->killMe();
670 if (getAdaptee() != nullptr && getAdaptee()->refCount() == 0)
672 partial_pin.erase(getAdaptee()->id());
673 partial_pout.erase(getAdaptee()->id());
674 partial_pein.erase(getAdaptee()->id());
675 partial_peout.erase(getAdaptee()->id());
679 std::wstring GraphicsAdapter::getTypeStr() const
681 return getSharedTypeStr();
684 std::wstring GraphicsAdapter::getShortTypeStr() const
686 return getSharedTypeStr();
689 types::InternalType* GraphicsAdapter::getGrIContent() const
694 void GraphicsAdapter::setGrIContent(types::InternalType* v)
696 types::InternalType* temp = gr_i_content;
705 static void relink_cached(Controller& controller, model::BaseObject* adaptee, const std::vector<ScicosID>& children, std::map<ScicosID, std::vector<int> >& cache, object_properties_t p)
707 auto it = cache.find(adaptee->id());
708 if (it == cache.end())
710 // unable to relink as there is no information to do so
713 std::vector<int>& cached_information = it->second;
715 std::vector<ScicosID> ports;
716 controller.getObjectProperty(adaptee, p, ports);
718 if (cached_information.size() != ports.size())
720 // defensive programming: unable to relink as something goes wrong on the adapters
724 bool isConnected = true;
725 for (size_t i = 0; i < cached_information.size(); ++i)
727 ScicosID connectedSignal;
728 controller.getObjectProperty(ports[i], PORT, CONNECTED_SIGNALS, connectedSignal);
730 if (connectedSignal != ScicosID())
732 cached_information[i] = (int)std::distance(children.begin(), std::find(children.begin(), children.end(), connectedSignal));
746 void GraphicsAdapter::relink(Controller& controller, model::Block* adaptee, const std::vector<ScicosID>& children)
748 relink_cached(controller, adaptee, children, partial_pin, INPUTS);
749 relink_cached(controller, adaptee, children, partial_pout, OUTPUTS);
750 relink_cached(controller, adaptee, children, partial_pein, EVENT_INPUTS);
751 relink_cached(controller, adaptee, children, partial_peout, EVENT_OUTPUTS);
754 void copyOnClone(model::BaseObject* original, model::BaseObject* cloned, std::map<ScicosID, std::vector<int> >& cache)
757 auto it = cache.find(original->id());
758 if (it != cache.end())
759 cache.insert({cloned->id(), it->second});
762 void GraphicsAdapter::add_partial_links_information(Controller& controller, model::BaseObject* original, model::BaseObject* cloned)
765 if (cloned == nullptr)
770 if (original->kind() == BLOCK)
772 // add the from / to information if applicable
773 copyOnClone(original, cloned, partial_pin);
774 copyOnClone(original, cloned, partial_pout);
775 copyOnClone(original, cloned, partial_pein);
776 copyOnClone(original, cloned, partial_peout);
779 switch (original->kind())
785 std::vector<ScicosID> originalChildren;
786 controller.getObjectProperty(original, CHILDREN, originalChildren);
787 std::vector<ScicosID> clonedChildren;
788 controller.getObjectProperty(cloned, CHILDREN, clonedChildren);
790 for (size_t i = 0; i < originalChildren.size(); ++i)
792 // a clone preserve position thus null ID, ignore them on
794 if (originalChildren[i] != ScicosID())
796 add_partial_links_information(controller, controller.getBaseObject(originalChildren[i]), controller.getBaseObject(clonedChildren[i]));
807 void GraphicsAdapter::remove_partial_links_information(model::Block* o)
809 partial_pin.erase(o->id());
810 partial_pout.erase(o->id());
811 partial_pein.erase(o->id());
812 partial_peout.erase(o->id());
815 } /* namespace view_scilab */
816 } /* namespace org_scilab_modules_scicos */