Xcos MVC: Fixed default datatype
[scilab.git] / scilab / modules / scicos / src / cpp / view_scilab / LinkAdapter.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2014-2014 - Scilab Enterprises - Clement DAVID
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10  *
11  */
12
13 #include <string>
14 #include <vector>
15 #include <iterator>
16 #include <algorithm>
17
18 #include "internal.hxx"
19 #include "list.hxx"
20 #include "types.hxx"
21 #include "user.hxx"
22 #include "double.hxx"
23
24 #include "Controller.hxx"
25 #include "LinkAdapter.hxx"
26 #include "model/Port.hxx"
27 #include "model/Link.hxx"
28
29 extern "C" {
30 #include "sci_malloc.h"
31 #include "charEncoding.h"
32 }
33
34 namespace org_scilab_modules_scicos
35 {
36 namespace view_scilab
37 {
38 namespace
39 {
40
41 struct xx
42 {
43
44     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
45     {
46         model::Link* adaptee = adaptor.getAdaptee();
47
48         std::vector<double> controlPoints;
49         controller.getObjectProperty(adaptee->id(), adaptee->kind(), CONTROL_POINTS, controlPoints);
50
51         double* data;
52         int size = (int)controlPoints.size() / 2;
53         types::Double* o = new types::Double(size, 1, &data);
54
55 #ifdef _MSC_VER
56         std::copy(controlPoints.begin(), controlPoints.begin() + size, stdext::checked_array_iterator<double*>(data, size));
57 #else
58         std::copy(controlPoints.begin(), controlPoints.begin() + size, data);
59 #endif
60         return o;
61     }
62
63     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
64     {
65         model::Link* adaptee = adaptor.getAdaptee();
66
67         if (v->getType() != types::InternalType::ScilabDouble)
68         {
69             return false;
70         }
71
72         types::Double* current = v->getAs<types::Double>();
73
74         std::vector<double> controlPoints;
75         controller.getObjectProperty(adaptee->id(), adaptee->kind(), CONTROL_POINTS, controlPoints);
76
77         if (current->getSize() != static_cast<int>(controlPoints.size() / 2))
78         {
79             return false;
80         }
81
82         std::copy(current->getReal(), current->getReal() + current->getSize(), controlPoints.begin());
83         controller.setObjectProperty(adaptee->id(), adaptee->kind(), CONTROL_POINTS, controlPoints);
84
85         return true;
86     }
87 };
88
89 struct yy
90 {
91
92     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
93     {
94         model::Link* adaptee = adaptor.getAdaptee();
95
96         std::vector<double> controlPoints;
97         controller.getObjectProperty(adaptee->id(), adaptee->kind(), CONTROL_POINTS, controlPoints);
98
99         double* data;
100         int size = (int)controlPoints.size() / 2;
101         types::Double* o = new types::Double(size, 1, &data);
102
103 #ifdef _MSC_VER
104         std::copy(controlPoints.begin() + size, controlPoints.end(), stdext::checked_array_iterator<double*>(data, size));
105 #else
106         std::copy(controlPoints.begin() + size, controlPoints.end(), data);
107 #endif
108         return o;
109     }
110
111     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
112     {
113         model::Link* adaptee = adaptor.getAdaptee();
114
115         if (v->getType() != types::InternalType::ScilabDouble)
116         {
117             return false;
118         }
119
120         types::Double* current = v->getAs<types::Double>();
121
122         std::vector<double> controlPoints;
123         controller.getObjectProperty(adaptee->id(), adaptee->kind(), CONTROL_POINTS, controlPoints);
124
125         if (current->getSize() != static_cast<int>(controlPoints.size() / 2))
126         {
127             return false;
128         }
129
130         std::copy(current->getReal(), current->getReal() + current->getSize(), controlPoints.begin() + controlPoints.size() / 2);
131         controller.setObjectProperty(adaptee->id(), adaptee->kind(), CONTROL_POINTS, controlPoints);
132
133         return true;
134     }
135 };
136
137 struct id
138 {
139
140     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
141     {
142         model::Link* adaptee = adaptor.getAdaptee();
143
144         std::string id;
145         controller.getObjectProperty(adaptee->id(), adaptee->kind(), LABEL, id);
146
147         types::String* o = new types::String(1, 1);
148         o->set(0, id.data());
149
150         return o;
151     }
152
153     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
154     {
155         if (v->getType() != types::InternalType::ScilabString)
156         {
157             return false;
158         }
159
160         types::String* current = v->getAs<types::String>();
161         if (current->getSize() != 1)
162         {
163             return false;
164         }
165
166         model::Link* adaptee = adaptor.getAdaptee();
167
168         std::string id;
169         char* c_str = wide_string_to_UTF8(current->get(0));
170         id = std::string(c_str);
171         FREE(c_str);
172
173         controller.setObjectProperty(adaptee->id(), adaptee->kind(), LABEL, id);
174         return true;
175     }
176 };
177
178 struct thick
179 {
180
181     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
182     {
183         model::Link* adaptee = adaptor.getAdaptee();
184
185         std::vector<double> thick;
186         controller.getObjectProperty(adaptee->id(), adaptee->kind(), THICK, thick);
187
188         double* data;
189         types::Double* o = new types::Double(1, 2, &data);
190
191         data[0] = thick[0];
192         data[1] = thick[1];
193         return o;
194     }
195
196     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
197     {
198         model::Link* adaptee = adaptor.getAdaptee();
199
200         if (v->getType() != types::InternalType::ScilabDouble)
201         {
202             return false;
203         }
204
205         types::Double* current = v->getAs<types::Double>();
206         if (current->getRows() != 1 || current->getCols() != 2)
207         {
208             return false;
209         }
210
211         std::vector<double> thick (2);
212         thick[0] = current->get(0);
213         thick[1] = current->get(1);
214
215         controller.setObjectProperty(adaptee->id(), adaptee->kind(), THICK, thick);
216         return true;
217     }
218 };
219
220 struct ct
221 {
222
223     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
224     {
225         model::Link* adaptee = adaptor.getAdaptee();
226
227         int color;
228         int kind;
229         controller.getObjectProperty(adaptee->id(), adaptee->kind(), COLOR, color);
230         controller.getObjectProperty(adaptee->id(), adaptee->kind(), KIND, kind);
231
232         double* data;
233         types::Double* o = new types::Double(1, 2, &data);
234
235         data[0] = static_cast<double>(color);
236         data[1] = static_cast<double>(kind);
237         return o;
238     }
239
240     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
241     {
242         model::Link* adaptee = adaptor.getAdaptee();
243
244         if (v->getType() != types::InternalType::ScilabDouble)
245         {
246             return false;
247         }
248
249         types::Double* current = v->getAs<types::Double>();
250         if (current->getRows() != 1 || current->getCols() != 2)
251         {
252             return false;
253         }
254         if (floor(current->get(0)) != current->get(0) || floor(current->get(1)) != current->get(1))
255         {
256             return false;
257         }
258
259         int color = static_cast<int>(current->get(0));
260         int kind  = static_cast<int>(current->get(1));
261
262         controller.setObjectProperty(adaptee->id(), adaptee->kind(), COLOR, color);
263         controller.setObjectProperty(adaptee->id(), adaptee->kind(), KIND, kind);
264         return true;
265     }
266 };
267
268 static types::Double* getLinkEnd(const LinkAdapter& adaptor, const Controller& controller, object_properties_t end)
269 {
270     model::Link* adaptee = adaptor.getAdaptee();
271
272     double* data;
273     types::Double* o = new types::Double(1, 3, &data);
274     data[0] = 0;
275     data[1] = 0;
276     data[2] = 0;
277
278     ScicosID endID;
279     controller.getObjectProperty(adaptee->id(), adaptee->kind(), end, endID);
280     if (endID != 0)
281     {
282         ScicosID sourceBlock;
283         controller.getObjectProperty(endID, PORT, SOURCE_BLOCK, sourceBlock);
284
285         // Looking for the block number among the block IDs
286         ScicosID parentDiagram;
287         controller.getObjectProperty(adaptee->id(), BLOCK, PARENT_DIAGRAM, parentDiagram);
288         std::vector<ScicosID> children;
289         if (parentDiagram == 0)
290         {
291             return o;
292         }
293         controller.getObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children);
294         data[0] = static_cast<double>(std::distance(children.begin(), std::find(children.begin(), children.end(), sourceBlock)) + 1);
295
296         std::vector<ScicosID> sourceBlockPorts;
297         switch (end)
298         {
299             case SOURCE_PORT:
300                 controller.getObjectProperty(sourceBlock, BLOCK, OUTPUTS, sourceBlockPorts);
301                 break;
302             case DESTINATION_PORT:
303                 controller.getObjectProperty(sourceBlock, BLOCK, INPUTS, sourceBlockPorts);
304                 break;
305             default:
306                 return 0;
307         }
308         data[1] = static_cast<double>(std::distance(sourceBlockPorts.begin(), std::find(sourceBlockPorts.begin(), sourceBlockPorts.end(), endID)) + 1);
309
310         bool isImplicit;
311         controller.getObjectProperty(endID, PORT, IMPLICIT, isImplicit);
312
313         if (isImplicit == false)
314         {
315             int kind;
316             controller.getObjectProperty(endID, PORT, PORT_KIND, kind);
317             if (kind == model::IN || kind == model::EIN)
318             {
319                 data[2] = 1;
320             }
321         }
322     }
323     // Default case, the property was initialized at [].
324     return o;
325 }
326
327 enum startOrEnd
328 {
329     Start = 0,
330     End = 1
331 };
332
333 static bool setLinkEnd(LinkAdapter& adaptor, Controller& controller, object_properties_t end, types::InternalType* v)
334 {
335     model::Link* adaptee = adaptor.getAdaptee();
336
337     if (v->getType() != types::InternalType::ScilabDouble)
338     {
339         return false;
340     }
341
342     types::Double* current = v->getAs<types::Double>();
343
344     if ((current->getRows() != 1 || current->getCols() != 3) && current->getSize() != 0)
345     {
346         return false; // Must be [] or [x y z]
347     }
348
349     ScicosID from;
350     controller.getObjectProperty(adaptee->id(), adaptee->kind(), SOURCE_PORT, from);
351     ScicosID to;
352     controller.getObjectProperty(adaptee->id(), adaptee->kind(), DESTINATION_PORT, to);
353     ScicosID concernedPort;
354     ScicosID otherPort;
355     object_properties_t otherEnd;
356     switch (end)
357     {
358         case SOURCE_PORT:
359             concernedPort = from;
360             otherPort = to;
361             otherEnd = DESTINATION_PORT;
362             break;
363         case DESTINATION_PORT:
364             concernedPort = to;
365             otherPort = from;
366             otherEnd = SOURCE_PORT;
367             break;
368         default:
369             return false;
370     }
371     ScicosID unconnected = 0;
372
373     if (current->getSize() == 0 || (current->get(0) == 0 || current->get(1) == 0))
374     {
375         // We want to set an empty link
376         if (concernedPort == 0)
377         {
378             // In this case, the link was already empty, do a dummy call to display the console status.
379             controller.setObjectProperty(adaptee->id(), adaptee->kind(), end, concernedPort);
380         }
381         else
382         {
383             // Untie the old link on both ends and set the 2 concerned ports as unconnected
384             controller.setObjectProperty(from, PORT, CONNECTED_SIGNALS, unconnected);
385             controller.setObjectProperty(to, PORT, CONNECTED_SIGNALS, unconnected);
386
387             controller.setObjectProperty(adaptee->id(), adaptee->kind(), SOURCE_PORT, unconnected);
388             controller.setObjectProperty(adaptee->id(), adaptee->kind(), DESTINATION_PORT, unconnected);
389         }
390         return true;
391     }
392
393     if (current->get(2) != 0 && current->get(2) != 1)
394     {
395         return false;
396     }
397
398     if (floor(current->get(0)) != current->get(0) || floor(current->get(1)) != current->get(1))
399     {
400         return false; // Must be an integer value
401     }
402
403     ScicosID parentDiagram;
404     controller.getObjectProperty(adaptee->id(), BLOCK, PARENT_DIAGRAM, parentDiagram);
405     std::vector<ScicosID> children;
406     if (parentDiagram != 0)
407     {
408         controller.getObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children);
409     }
410
411     // Connect the new one
412     int blk  = static_cast<int>(current->get(0));
413     int port = static_cast<int>(current->get(1));
414     int kind = static_cast<int>(current->get(2));
415     if (kind != Start && kind != End)
416     {
417         return false;
418     }
419     // kind == 0: trying to set the start of the link (output port)
420     // kind == 1: trying to set the end of the link (input port)
421
422     if (blk < 0 || blk > static_cast<int>(children.size()))
423     {
424         return false; // Trying to link to a non-existing block
425     }
426     ScicosID blkID = children[blk - 1];
427
428     std::vector<ScicosID> sourceBlockPorts;
429     int nBlockPorts;
430     bool newPortIsImplicit = false;
431     int newPortKind = static_cast<int>(model::UNDEF);
432     int linkType;
433     controller.getObjectProperty(adaptee->id(), adaptee->kind(), KIND, linkType);
434     if (linkType == model::activation)
435     {
436         std::vector<ScicosID> evtin;
437         std::vector<ScicosID> evtout;
438         controller.getObjectProperty(blkID, BLOCK, EVENT_INPUTS, evtin);
439         controller.getObjectProperty(blkID, BLOCK, EVENT_OUTPUTS, evtout);
440
441         if (kind == Start)
442         {
443             if (otherPort != 0)
444             {
445                 // The other end must be an input
446                 int otherPortKind;
447                 controller.getObjectProperty(otherPort, PORT, PORT_KIND, otherPortKind);
448                 if (otherPortKind != model::EIN)
449                 {
450                     return false;
451                 }
452             }
453             newPortKind = static_cast<int>(model::EOUT);
454             sourceBlockPorts = evtout;
455         }
456         else
457         {
458             if (otherPort != 0)
459             {
460                 // The other end must be an output
461                 int otherPortKind;
462                 controller.getObjectProperty(otherPort, PORT, PORT_KIND, otherPortKind);
463                 if (otherPortKind != model::EOUT)
464                 {
465                     return false;
466                 }
467             }
468             newPortKind = static_cast<int>(model::EIN);
469             sourceBlockPorts = evtin;
470         }
471
472     }
473     else if (linkType == model::regular || linkType == model::implicit)
474     {
475         std::vector<ScicosID> in;
476         std::vector<ScicosID> out;
477         controller.getObjectProperty(blkID, BLOCK, INPUTS, in);
478         controller.getObjectProperty(blkID, BLOCK, OUTPUTS, out);
479
480         if (linkType == model::regular)
481         {
482             if (kind == Start)
483             {
484                 if (otherPort != 0)
485                 {
486                     // The other end must be an input
487                     int otherPortKind;
488                     controller.getObjectProperty(otherPort, PORT, PORT_KIND, otherPortKind);
489                     if (otherPortKind != model::IN)
490                     {
491                         return false;
492                     }
493                 }
494                 newPortKind = static_cast<int>(model::OUT);
495                 sourceBlockPorts = out;
496             }
497             else
498             {
499                 if (otherPort != 0)
500                 {
501                     // The other end must be an output
502                     int otherPortKind = 1;
503                     controller.getObjectProperty(otherPort, PORT, PORT_KIND, otherPortKind);
504                     if (otherPortKind != model::OUT)
505                     {
506                         return false;
507                     }
508                 }
509                 newPortKind = static_cast<int>(model::IN);
510                 sourceBlockPorts = in;
511             }
512
513             // Rule out the implicit ports
514             for (std::vector<ScicosID>::iterator it = sourceBlockPorts.begin(); it != sourceBlockPorts.end(); ++it)
515             {
516                 bool isImplicit;
517                 controller.getObjectProperty(*it, PORT, IMPLICIT, isImplicit);
518                 if (isImplicit == true)
519                 {
520                     sourceBlockPorts.erase(it);
521                 }
522             }
523         }
524         else // model::implicit
525         {
526             newPortIsImplicit = true;
527             sourceBlockPorts.insert(sourceBlockPorts.begin(), in.begin(), in.end());
528             sourceBlockPorts.insert(sourceBlockPorts.begin(), out.begin(), out.end());
529
530             // Rule out the explicit ports
531             for (std::vector<ScicosID>::iterator it = sourceBlockPorts.begin(); it != sourceBlockPorts.end(); ++it)
532             {
533                 bool isImplicit;
534                 controller.getObjectProperty(*it, PORT, IMPLICIT, isImplicit);
535                 if (isImplicit == false)
536                 {
537                     sourceBlockPorts.erase(it);
538                 }
539             }
540         }
541     }
542
543     // Disconnect the old port if it was connected. After that, concernedPort will be reused to designate the new port
544     if (concernedPort != 0)
545     {
546         controller.setObjectProperty(concernedPort, PORT, CONNECTED_SIGNALS, unconnected);
547     }
548
549     nBlockPorts = static_cast<int>(sourceBlockPorts.size());
550     if (nBlockPorts >= port)
551     {
552         concernedPort = sourceBlockPorts[port - 1];
553     }
554     else
555     {
556         while (nBlockPorts < port) // Create as many ports as necessary
557         {
558             concernedPort = controller.createObject(PORT);
559             controller.setObjectProperty(concernedPort, PORT, IMPLICIT, newPortIsImplicit);
560             controller.setObjectProperty(concernedPort, PORT, PORT_KIND, newPortKind);
561             controller.setObjectProperty(concernedPort, PORT, SOURCE_BLOCK, blkID);
562             controller.setObjectProperty(concernedPort, PORT, CONNECTED_SIGNALS, unconnected);
563             std::vector<int> dataType;
564             controller.getObjectProperty(concernedPort, PORT, DATATYPE, dataType);
565             dataType[0] = -1; // Default number of rows for new ports
566             controller.setObjectProperty(concernedPort, PORT, DATATYPE, dataType);
567
568             std::vector<ScicosID> concernedPorts;
569             if (linkType == model::activation)
570             {
571                 if (kind == Start)
572                 {
573                     controller.getObjectProperty(blkID, BLOCK, EVENT_OUTPUTS, concernedPorts);
574                     concernedPorts.push_back(concernedPort);
575                     controller.setObjectProperty(blkID, BLOCK, EVENT_OUTPUTS, concernedPorts);
576                 }
577                 else
578                 {
579                     controller.getObjectProperty(blkID, BLOCK, EVENT_INPUTS, concernedPorts);
580                     concernedPorts.push_back(concernedPort);
581                     controller.setObjectProperty(blkID, BLOCK, EVENT_INPUTS, concernedPorts);
582                 }
583             }
584             else // model::regular || model::implicit
585             {
586                 if (kind == Start)
587                 {
588                     controller.getObjectProperty(blkID, BLOCK, OUTPUTS, concernedPorts);
589                     concernedPorts.push_back(concernedPort);
590                     controller.setObjectProperty(blkID, BLOCK, OUTPUTS, concernedPorts);
591                 }
592                 else
593                 {
594                     controller.getObjectProperty(blkID, BLOCK, INPUTS, concernedPorts);
595                     concernedPorts.push_back(concernedPort);
596                     controller.setObjectProperty(blkID, BLOCK, INPUTS, concernedPorts);
597                 }
598             }
599
600             nBlockPorts++;
601         }
602     }
603     ScicosID oldLink;
604     controller.getObjectProperty(concernedPort, PORT, CONNECTED_SIGNALS, oldLink);
605     if (oldLink != 0)
606     {
607         // Disconnect the old other end port and delete the old link
608         ScicosID oldPort;
609         controller.getObjectProperty(oldLink, LINK, otherEnd, oldPort);
610         controller.setObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, unconnected);
611         controller.deleteObject(oldLink);
612     }
613
614     // Connect the new source and destination ports together
615     controller.setObjectProperty(concernedPort, PORT, CONNECTED_SIGNALS, adaptee->id());
616     controller.setObjectProperty(adaptee->id(), adaptee->kind(), end, concernedPort);
617     return true;
618 }
619
620 struct from
621 {
622
623     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
624     {
625         return getLinkEnd(adaptor, controller, SOURCE_PORT);
626     }
627
628     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
629     {
630         return setLinkEnd(adaptor, controller, SOURCE_PORT, v);
631     }
632 };
633
634 struct to
635 {
636
637     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
638     {
639         return getLinkEnd(adaptor, controller, DESTINATION_PORT);
640     }
641
642     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
643     {
644         return setLinkEnd(adaptor, controller, DESTINATION_PORT, v);
645     }
646 };
647
648 } /* namespace */
649
650 template<> property<LinkAdapter>::props_t property<LinkAdapter>::fields = property<LinkAdapter>::props_t();
651
652 LinkAdapter::LinkAdapter(const LinkAdapter& o) :
653     BaseAdapter<LinkAdapter, org_scilab_modules_scicos::model::Link>(o) {}
654
655 LinkAdapter::LinkAdapter(org_scilab_modules_scicos::model::Link* o) :
656     BaseAdapter<LinkAdapter, org_scilab_modules_scicos::model::Link>(o)
657 {
658     if (property<LinkAdapter>::properties_have_not_been_set())
659     {
660         property<LinkAdapter>::fields.reserve(7);
661         property<LinkAdapter>::add_property(L"xx", &xx::get, &xx::set);
662         property<LinkAdapter>::add_property(L"yy", &yy::get, &yy::set);
663         property<LinkAdapter>::add_property(L"id", &id::get, &id::set);
664         property<LinkAdapter>::add_property(L"thick", &thick::get, &thick::set);
665         property<LinkAdapter>::add_property(L"ct", &ct::get, &ct::set);
666         property<LinkAdapter>::add_property(L"from", &from::get, &from::set);
667         property<LinkAdapter>::add_property(L"to", &to::get, &to::set);
668     }
669 }
670
671 LinkAdapter::~LinkAdapter()
672 {
673 }
674
675 std::wstring LinkAdapter::getTypeStr()
676 {
677     return getSharedTypeStr();
678 }
679 std::wstring LinkAdapter::getShortTypeStr()
680 {
681     return getSharedTypeStr();
682 }
683
684 } /* namespace view_scilab */
685 } /* namespace org_scilab_modules_scicos */