303d30175c8f1aaba33f0c22f9829dba14a3e5b1
[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  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
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.
13  *
14  */
15
16 #include <string>
17 #include <vector>
18 #include <iterator>
19 #include <algorithm>
20
21 #include "internal.hxx"
22 #include "list.hxx"
23 #include "types.hxx"
24 #include "user.hxx"
25 #include "double.hxx"
26
27 #include "utilities.hxx"
28 #include "adapters_utilities.hxx"
29 #include "Controller.hxx"
30 #include "LinkAdapter.hxx"
31 #include "controller_helpers.hxx"
32 #include "model/Link.hxx"
33 #include "model/Port.hxx"
34
35 extern "C" {
36 #include "sci_malloc.h"
37 #include "charEncoding.h"
38 #include "localization.h"
39 }
40
41 namespace org_scilab_modules_scicos
42 {
43 namespace view_scilab
44 {
45 namespace
46 {
47
48 const std::string split ("split");
49 const std::string lsplit ("lsplit");
50 const std::string limpsplit ("limpsplit");
51
52 struct xx
53 {
54
55     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
56     {
57         ScicosID adaptee = adaptor.getAdaptee()->id();
58
59         std::vector<double> controlPoints;
60         controller.getObjectProperty(adaptee, LINK, CONTROL_POINTS, controlPoints);
61
62         double* data;
63         int size = (int)controlPoints.size() / 2;
64         types::Double* o = new types::Double(size, 1, &data);
65
66         for (int i = 0; i < size; ++i)
67         {
68             data[i] = controlPoints[2 * i];
69         }
70         return o;
71     }
72
73     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
74     {
75         ScicosID adaptee = adaptor.getAdaptee()->id();
76
77         if (v->getType() != types::InternalType::ScilabDouble)
78         {
79             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s: Real matrix object.\n"), "xx");
80             return false;
81         }
82
83         types::Double* current = v->getAs<types::Double>();
84
85         std::vector<double> controlPoints;
86         controller.getObjectProperty(adaptee, LINK, CONTROL_POINTS, controlPoints);
87
88         int newXSize = current->getSize();
89         int oldXSize = static_cast<int>(controlPoints.size() / 2);
90         std::vector<double> newControlPoints (controlPoints);
91
92         if (newXSize == oldXSize)
93         {
94             for (int i = 0; i < newXSize; ++i)
95             {
96                 newControlPoints[2 * i] = current->getReal()[i];
97             }
98         }
99         else
100         {
101             newControlPoints.resize(2 * current->getSize(), 0);
102
103             for (int i = 0; i < newXSize; ++i)
104             {
105                 newControlPoints[2 * i] = current->getReal()[i];
106             }
107         }
108
109         controller.setObjectProperty(adaptee, LINK, CONTROL_POINTS, newControlPoints);
110         return true;
111     }
112 };
113
114 struct yy
115 {
116
117     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
118     {
119         ScicosID adaptee = adaptor.getAdaptee()->id();
120
121         std::vector<double> controlPoints;
122         controller.getObjectProperty(adaptee, LINK, CONTROL_POINTS, controlPoints);
123
124         double* data;
125         int size = (int)controlPoints.size() / 2;
126         types::Double* o = new types::Double(size, 1, &data);
127
128         for (int i = 0; i < size; ++i)
129         {
130             data[i] = controlPoints[2 * i + 1];
131         }
132         return o;
133     }
134
135     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
136     {
137         ScicosID adaptee = adaptor.getAdaptee()->id();
138
139         if (v->getType() != types::InternalType::ScilabDouble)
140         {
141             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s: Real matrix object.\n"), "yy");
142             return false;
143         }
144
145         types::Double* current = v->getAs<types::Double>();
146
147         std::vector<double> controlPoints;
148         controller.getObjectProperty(adaptee, LINK, CONTROL_POINTS, controlPoints);
149
150         int newYSize = current->getSize();
151         int oldYSize = static_cast<int>(controlPoints.size() / 2);
152         std::vector<double> newControlPoints (controlPoints);
153
154         if (newYSize == oldYSize)
155         {
156             for (int i = 0; i < newYSize; ++i)
157             {
158                 newControlPoints[2 * i + 1] = current->getReal()[i];
159             }
160         }
161         else
162         {
163             newControlPoints.resize(2 * current->getSize());
164
165             for (int i = 0; i < newYSize; ++i)
166             {
167                 newControlPoints[2 * i + 1] = current->getReal()[i];
168             }
169         }
170
171         controller.setObjectProperty(adaptee, LINK, CONTROL_POINTS, newControlPoints);
172         return true;
173     }
174 };
175
176 struct id
177 {
178
179     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
180     {
181         ScicosID adaptee = adaptor.getAdaptee()->id();
182
183         std::string id;
184         controller.getObjectProperty(adaptee, LINK, LABEL, id);
185
186         types::String* o = new types::String(1, 1);
187         o->set(0, id.data());
188
189         return o;
190     }
191
192     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
193     {
194         if (v->getType() != types::InternalType::ScilabString)
195         {
196             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s: String matrix expected.\n"), "id");
197             return false;
198         }
199
200         types::String* current = v->getAs<types::String>();
201         if (current->getSize() != 1)
202         {
203             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s: %d-by-%d expected.\n"), "id", 1, 1);
204             return false;
205         }
206
207         ScicosID adaptee = adaptor.getAdaptee()->id();
208
209         char* c_str = wide_string_to_UTF8(current->get(0));
210         std::string id(c_str);
211         FREE(c_str);
212
213         controller.setObjectProperty(adaptee, LINK, LABEL, id);
214         return true;
215     }
216 };
217
218 struct thick
219 {
220
221     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
222     {
223         ScicosID adaptee = adaptor.getAdaptee()->id();
224
225         std::vector<double> thick;
226         controller.getObjectProperty(adaptee, LINK, THICK, thick);
227
228         double* data;
229         types::Double* o = new types::Double(1, 2, &data);
230
231         data[0] = thick[0];
232         data[1] = thick[1];
233         return o;
234     }
235
236     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
237     {
238         ScicosID adaptee = adaptor.getAdaptee()->id();
239
240         if (v->getType() != types::InternalType::ScilabDouble)
241         {
242             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s: Real matrix expected.\n"), "thick");
243             return false;
244         }
245
246         types::Double* current = v->getAs<types::Double>();
247         if (current->getSize() != 2)
248         {
249             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s: %d-by-%d expected.\n"), "thick", 2, 1);
250             return false;
251         }
252
253         std::vector<double> thick (2);
254         thick[0] = current->get(0);
255         thick[1] = current->get(1);
256
257         controller.setObjectProperty(adaptee, LINK, THICK, thick);
258         return true;
259     }
260 };
261
262 struct ct
263 {
264
265     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
266     {
267         ScicosID adaptee = adaptor.getAdaptee()->id();
268
269         int color;
270         int kind;
271         controller.getObjectProperty(adaptee, LINK, COLOR, color);
272         controller.getObjectProperty(adaptee, LINK, KIND, kind);
273
274         double* data;
275         types::Double* o = new types::Double(1, 2, &data);
276
277         data[0] = color;
278         data[1] = kind;
279         return o;
280     }
281
282     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
283     {
284         ScicosID adaptee = adaptor.getAdaptee()->id();
285
286         if (v->getType() != types::InternalType::ScilabDouble)
287         {
288             return false;
289         }
290
291         types::Double* current = v->getAs<types::Double>();
292         if (current->getSize() != 2)
293         {
294             return false;
295         }
296         if (floor(current->get(0)) != current->get(0) || floor(current->get(1)) != current->get(1))
297         {
298             return false;
299         }
300
301         int color = static_cast<int>(current->get(0));
302         int kind  = static_cast<int>(current->get(1));
303
304         controller.setObjectProperty(adaptee, LINK, COLOR, color);
305         controller.setObjectProperty(adaptee, LINK, KIND, kind);
306         return true;
307     }
308 };
309
310 link_t getLinkEnd(const LinkAdapter& adaptor, const Controller& controller, const object_properties_t end)
311 {
312     ScicosID adaptee = adaptor.getAdaptee()->id();
313
314     link_t ret {0, 0, Start};
315
316     ScicosID endID;
317     controller.getObjectProperty(adaptee, LINK, end, endID);
318     if (endID != 0)
319     {
320         ScicosID sourceBlock;
321         controller.getObjectProperty(endID, PORT, SOURCE_BLOCK, sourceBlock);
322
323         // Looking for the block number among the block IDs
324         ScicosID parent;
325         kind_t parentKind = BLOCK;
326         controller.getObjectProperty(adaptee, LINK, PARENT_BLOCK, parent);
327         std::vector<ScicosID> children;
328         // Added to a superblock
329         if (parent == 0)
330         {
331             // Added to a diagram
332             controller.getObjectProperty(adaptee, LINK, PARENT_DIAGRAM, parent);
333             parentKind = DIAGRAM;
334             if (parent == 0)
335             {
336                 return ret;
337             }
338         }
339         controller.getObjectProperty(parent, parentKind, CHILDREN, children);
340
341         ret.block = static_cast<int>(std::distance(children.begin(), std::find(children.begin(), children.end(), sourceBlock)) + 1);
342
343         // To find the port index from its 'endID' ID, search through all the block's ports lists
344         std::vector<ScicosID> sourceBlockPorts;
345         controller.getObjectProperty(sourceBlock, BLOCK, INPUTS, sourceBlockPorts);
346
347         std::vector<ScicosID>::iterator found = std::find(sourceBlockPorts.begin(), sourceBlockPorts.end(), endID);
348         if (found == sourceBlockPorts.end()) // Not found in the data inputs
349         {
350             sourceBlockPorts.clear();
351             controller.getObjectProperty(sourceBlock, BLOCK, OUTPUTS, sourceBlockPorts);
352             found = std::find(sourceBlockPorts.begin(), sourceBlockPorts.end(), endID);
353             if (found == sourceBlockPorts.end()) // Not found in the data outputs
354             {
355                 sourceBlockPorts.clear();
356                 controller.getObjectProperty(sourceBlock, BLOCK, EVENT_INPUTS, sourceBlockPorts);
357                 found = std::find(sourceBlockPorts.begin(), sourceBlockPorts.end(), endID);
358                 if (found == sourceBlockPorts.end()) // Not found in the event inputs
359                 {
360                     sourceBlockPorts.clear();
361                     controller.getObjectProperty(sourceBlock, BLOCK, EVENT_OUTPUTS, sourceBlockPorts);
362                     found = std::find(sourceBlockPorts.begin(), sourceBlockPorts.end(), endID);
363                     if (found == sourceBlockPorts.end()) // Not found in the event outputs
364                     {
365                         return ret;
366                     }
367                 }
368             }
369         }
370         ret.port = static_cast<int>(std::distance(sourceBlockPorts.begin(), found) + 1);
371
372         bool isImplicit;
373         controller.getObjectProperty(endID, PORT, IMPLICIT, isImplicit);
374
375         if (isImplicit == false)
376         {
377             int kind;
378             controller.getObjectProperty(endID, PORT, PORT_KIND, kind);
379             if (kind == PORT_IN || kind == PORT_EIN)
380             {
381                 ret.kind = End;
382             }
383         }
384     }
385     // Default case, the property was initialized at [].
386     return ret;
387 }
388
389 /*
390  * Connectivity is ensured if 'port' is of the desired type or if either of the concerned blocks is a split block,
391  * because they are connectable to anything
392  */
393 bool checkConnectivity(const int neededType, const ScicosID port, const ScicosID blk1, Controller& controller)
394 {
395     int portKind;
396     controller.getObjectProperty(port, PORT, PORT_KIND, portKind);
397
398     if (portKind != neededType)
399     {
400         // Last chance if one of the connecting blocks is just a split block
401         std::string name1;
402         controller.getObjectProperty(blk1, BLOCK, SIM_FUNCTION_NAME, name1);
403         if (name1 != split && name1 != lsplit && name1 != limpsplit)
404         {
405             ScicosID blk2;
406             controller.getObjectProperty(port, PORT, SOURCE_BLOCK, blk2);
407             std::string name2;
408             controller.getObjectProperty(blk2, BLOCK, SIM_FUNCTION_NAME, name2);
409             if (name2 != split && name2 != lsplit && name2 != limpsplit)
410             {
411                 return false;
412             }
413         }
414     }
415     return true;
416 }
417
418 void setLinkEnd(const ScicosID id, Controller& controller, const object_properties_t end, const link_t& v)
419 {
420
421     ScicosID from;
422     controller.getObjectProperty(id, LINK, SOURCE_PORT, from);
423     ScicosID to;
424     controller.getObjectProperty(id, LINK, DESTINATION_PORT, to);
425     ScicosID concernedPort;
426     ScicosID otherPort;
427     switch (end)
428     {
429         case SOURCE_PORT:
430             concernedPort = from;
431             otherPort = to;
432             break;
433         case DESTINATION_PORT:
434             concernedPort = to;
435             otherPort = from;
436             break;
437         default:
438             return;
439     }
440     ScicosID unconnected = 0;
441
442     if (v.block == 0 || v.port == 0)
443     {
444         // We want to set an empty link
445         if (concernedPort == 0)
446         {
447             // In this case, the link was already empty, do a dummy call to display the console status.
448             controller.setObjectProperty(id, LINK, end, concernedPort);
449         }
450         else
451         {
452             // Untie the old link on the concerned end and set its port as unconnected
453             controller.setObjectProperty(concernedPort, PORT, CONNECTED_SIGNALS, unconnected);
454             controller.setObjectProperty(id, LINK, end, unconnected);
455         }
456         return;
457     }
458
459     ScicosID parentDiagram;
460     controller.getObjectProperty(id, LINK, PARENT_DIAGRAM, parentDiagram);
461     std::vector<ScicosID> children;
462     if (parentDiagram != 0)
463     {
464         // Adding to a diagram
465         controller.getObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children);
466     }
467     else
468     {
469         ScicosID parentBlock;
470         controller.getObjectProperty(id, LINK, PARENT_BLOCK, parentBlock);
471         if (parentBlock != 0)
472         {
473             // Adding to a superblock
474             controller.getObjectProperty(parentBlock, BLOCK, CHILDREN, children);
475         }
476     }
477
478     // Connect the new one
479
480     if (v.kind != Start && v.kind != End)
481     {
482         return;
483     }
484     // kind == 0: trying to set the start of the link (output port)
485     // kind == 1: trying to set the end of the link (input port)
486
487     if (v.block < 0 || v.block > static_cast<int>(children.size()))
488     {
489         return; // Trying to link to a non-existing block
490     }
491     ScicosID blkID = children[v.block - 1];
492
493     if (blkID == 0)
494     {
495         // Deleted Block
496         return;
497     }
498
499     // Check that the ID designates a BLOCK (and not an ANNOTATION)
500     if (controller.getObject(blkID)->kind() != BLOCK)
501     {
502         return;
503     }
504
505     // v.port may be decremented locally to square with the port indexes
506     int portIndex = v.port;
507
508     std::vector<ScicosID> sourceBlockPorts;
509     bool newPortIsImplicit = false;
510     enum portKind newPortKind = PORT_UNDEF;
511     int linkType;
512     controller.getObjectProperty(id, LINK, KIND, linkType);
513     if (linkType == model::activation)
514     {
515         std::vector<ScicosID> evtin;
516         std::vector<ScicosID> evtout;
517         controller.getObjectProperty(blkID, BLOCK, EVENT_INPUTS, evtin);
518         controller.getObjectProperty(blkID, BLOCK, EVENT_OUTPUTS, evtout);
519
520         if (v.kind == Start)
521         {
522             if (otherPort != 0)
523             {
524                 if (!checkConnectivity(PORT_EIN, otherPort, blkID, controller))
525                 {
526                     return;
527                 }
528             }
529             newPortKind = PORT_EOUT;
530             sourceBlockPorts = evtout;
531         }
532         else
533         {
534             if (otherPort != 0)
535             {
536                 if (!checkConnectivity(PORT_EOUT, otherPort, blkID, controller))
537                 {
538                     return;
539                 }
540             }
541             newPortKind = PORT_EIN;
542             sourceBlockPorts = evtin;
543         }
544
545     }
546     else if (linkType == model::regular || linkType == model::implicit)
547     {
548         std::vector<ScicosID> in;
549         std::vector<ScicosID> out;
550         controller.getObjectProperty(blkID, BLOCK, INPUTS, in);
551         controller.getObjectProperty(blkID, BLOCK, OUTPUTS, out);
552
553         if (linkType == model::regular)
554         {
555             if (v.kind == Start)
556             {
557                 if (otherPort != 0)
558                 {
559                     if (!checkConnectivity(PORT_IN, otherPort, blkID, controller))
560                     {
561                         return;
562                     }
563                 }
564                 newPortKind = PORT_OUT;
565                 sourceBlockPorts = out;
566             }
567             else
568             {
569                 if (otherPort != 0)
570                 {
571                     if (!checkConnectivity(PORT_OUT, otherPort, blkID, controller))
572                     {
573                         return;
574                     }
575                 }
576                 newPortKind = PORT_IN;
577                 sourceBlockPorts = in;
578             }
579
580             // Rule out the implicit ports
581             for (int i = 0; i < static_cast<int>(sourceBlockPorts.size()); ++i)
582             {
583                 bool isImplicit;
584                 controller.getObjectProperty(sourceBlockPorts[i], PORT, IMPLICIT, isImplicit);
585                 if (isImplicit == true)
586                 {
587                     sourceBlockPorts.erase(sourceBlockPorts.begin() + i);
588                     if (portIndex > i + 1)
589                     {
590                         portIndex--; // Keep portIndex consistent with the port indexes
591                     }
592                 }
593             }
594         }
595         else // model::implicit
596         {
597             newPortIsImplicit = true;
598             if (v.kind == Start)
599             {
600                 sourceBlockPorts = out;
601             }
602             else // End
603             {
604                 sourceBlockPorts = in;
605             }
606
607             // Rule out the explicit ports
608             for (size_t i = 0; i < sourceBlockPorts.size(); ++i)
609             {
610                 bool isImplicit;
611                 controller.getObjectProperty(sourceBlockPorts[i], PORT, IMPLICIT, isImplicit);
612                 if (isImplicit == false)
613                 {
614                     sourceBlockPorts.erase(sourceBlockPorts.begin() + i);
615                     if (portIndex > static_cast<int>(i + 1))
616                     {
617                         portIndex--; // Keep portIndex consistent with the port indexes
618                     }
619                 }
620             }
621         }
622     }
623
624     // Disconnect the old port if it was connected. After that, concernedPort will be reused to designate the new port
625     if (concernedPort != 0)
626     {
627         controller.setObjectProperty(concernedPort, PORT, CONNECTED_SIGNALS, unconnected);
628     }
629
630     int nBlockPorts = static_cast<int>(sourceBlockPorts.size());
631     if (nBlockPorts >= portIndex)
632     {
633         concernedPort = sourceBlockPorts[portIndex - 1];
634     }
635     else
636     {
637         while (nBlockPorts < portIndex) // Create as many ports as necessary
638         {
639             concernedPort = controller.createObject(PORT);
640             controller.setObjectProperty(concernedPort, PORT, IMPLICIT, newPortIsImplicit);
641             controller.setObjectProperty(concernedPort, PORT, PORT_KIND, static_cast<int>(newPortKind));
642             controller.setObjectProperty(concernedPort, PORT, SOURCE_BLOCK, blkID);
643             controller.setObjectProperty(concernedPort, PORT, CONNECTED_SIGNALS, unconnected);
644             // Set the default dataType so it is saved in the model
645             std::vector<int> dataType;
646             controller.getObjectProperty(concernedPort, PORT, DATATYPE, dataType);
647             controller.setObjectProperty(concernedPort, PORT, DATATYPE, dataType);
648
649             std::vector<ScicosID> concernedPorts;
650             if (linkType == model::activation)
651             {
652                 if (v.kind == Start)
653                 {
654                     controller.getObjectProperty(blkID, BLOCK, EVENT_OUTPUTS, concernedPorts);
655                     concernedPorts.push_back(concernedPort);
656                     controller.setObjectProperty(blkID, BLOCK, EVENT_OUTPUTS, concernedPorts);
657                 }
658                 else
659                 {
660                     controller.getObjectProperty(blkID, BLOCK, EVENT_INPUTS, concernedPorts);
661                     concernedPorts.push_back(concernedPort);
662                     controller.setObjectProperty(blkID, BLOCK, EVENT_INPUTS, concernedPorts);
663                 }
664             }
665             else // model::regular || model::implicit
666             {
667                 if (v.kind == Start)
668                 {
669                     controller.getObjectProperty(blkID, BLOCK, OUTPUTS, concernedPorts);
670                     concernedPorts.push_back(concernedPort);
671                     controller.setObjectProperty(blkID, BLOCK, OUTPUTS, concernedPorts);
672                 }
673                 else
674                 {
675                     controller.getObjectProperty(blkID, BLOCK, INPUTS, concernedPorts);
676                     concernedPorts.push_back(concernedPort);
677                     controller.setObjectProperty(blkID, BLOCK, INPUTS, concernedPorts);
678                 }
679             }
680
681             nBlockPorts++;
682         }
683     }
684     ScicosID oldLink;
685     controller.getObjectProperty(concernedPort, PORT, CONNECTED_SIGNALS, oldLink);
686     if (oldLink != 0)
687     {
688         // Disconnect the old link
689         controller.setObjectProperty(oldLink, LINK, end, unconnected);
690         controller.setObjectProperty(concernedPort, PORT, CONNECTED_SIGNALS, unconnected);
691     }
692
693     // Connect the new source and destination ports together
694     controller.setObjectProperty(concernedPort, PORT, CONNECTED_SIGNALS, id);
695     controller.setObjectProperty(id, LINK, end, concernedPort);
696 }
697
698 // Check if the Link is valid
699 bool is_valid(types::Double* o)
700 {
701     if (o->getSize() == 0)
702     {
703         return true;
704     }
705
706     if (o->getSize() == 2 || o->getSize() == 3)
707     {
708         if (floor(o->get(0)) != o->get(0) || floor(o->get(1)) != o->get(1))
709         {
710             return false; // Block and Port numbers must be integer values
711         }
712         if (o->get(1) < 0)
713         {
714             return false; // Port number must be positive
715         }
716
717         if (o->getSize() == 3)
718         {
719             if (floor(o->get(2)) != o->get(2))
720             {
721                 return false; // Kind must be an integer value
722             }
723             if (o->get(2) < 0)
724             {
725                 return false; // Kind must be positive
726             }
727         }
728
729         return true;
730     }
731
732     return false;
733 }
734
735
736 struct from
737 {
738
739     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& /*controller*/)
740     {
741         link_t from_content = adaptor.getFrom();
742
743         double* data;
744         types::Double* o = new types::Double(1, 3, &data);
745
746         data[0] = from_content.block;
747         data[1] = from_content.port;
748         data[2] = from_content.kind;
749         return o;
750     }
751
752     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
753     {
754         if (v->getType() != types::InternalType::ScilabDouble)
755         {
756             return false;
757         }
758
759         types::Double* current = v->getAs<types::Double>();
760
761         if (!is_valid(current))
762         {
763             return false;
764         }
765
766         link_t from_content {0, 0, Start};
767         if (current->getSize() >= 2)
768         {
769             from_content.block = static_cast<int>(current->get(0));
770             from_content.port = static_cast<int>(current->get(1));
771             // By default, 'kind' designates an output (set to 0)
772
773             if (current->getSize() == 3)
774             {
775                 from_content.kind = (current->get(2) == 0.) ? Start : End;
776             }
777         }
778
779         adaptor.setFromInModel(from_content, controller);
780         return true;
781     }
782 };
783
784 struct to
785 {
786
787     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& /*controller*/)
788     {
789         link_t to_content = adaptor.getTo();
790
791         double* data;
792         types::Double* o = new types::Double(1, 3, &data);
793
794         data[0] = to_content.block;
795         data[1] = to_content.port;
796         data[2] = to_content.kind;
797         return o;
798     }
799
800     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
801     {
802         if (v->getType() != types::InternalType::ScilabDouble)
803         {
804             return false;
805         }
806
807         types::Double* current = v->getAs<types::Double>();
808
809         if (current->getSize() != 0 && current->getSize() != 2 && current->getSize() != 3)
810         {
811             return false;
812         }
813
814         if (!is_valid(current))
815         {
816             return false;
817         }
818
819         link_t to_content {0, 0, End};
820         if (current->getSize() >= 2)
821         {
822             to_content.block = static_cast<int>(current->get(0));
823             to_content.port = static_cast<int>(current->get(1));
824             // By default, 'kind' designates an input (set to 1)
825
826             if (current->getSize() == 3)
827             {
828                 to_content.kind = (current->get(2) == 0.) ? Start : End;
829             }
830         }
831
832         adaptor.setToInModel(to_content, controller);
833         return true;
834     }
835 };
836
837 } /* namespace */
838
839 template<> property<LinkAdapter>::props_t property<LinkAdapter>::fields = property<LinkAdapter>::props_t();
840
841 LinkAdapter::LinkAdapter(const Controller& c, org_scilab_modules_scicos::model::Link* adaptee) :
842     BaseAdapter<LinkAdapter, org_scilab_modules_scicos::model::Link>(c, adaptee),
843     m_from(),
844     m_to()
845 {
846     if (property<LinkAdapter>::properties_have_not_been_set())
847     {
848         property<LinkAdapter>::fields.reserve(7);
849         property<LinkAdapter>::add_property(L"xx", &xx::get, &xx::set);
850         property<LinkAdapter>::add_property(L"yy", &yy::get, &yy::set);
851         property<LinkAdapter>::add_property(L"id", &id::get, &id::set);
852         property<LinkAdapter>::add_property(L"thick", &thick::get, &thick::set);
853         property<LinkAdapter>::add_property(L"ct", &ct::get, &ct::set);
854         property<LinkAdapter>::add_property(L"from", &from::get, &from::set);
855         property<LinkAdapter>::add_property(L"to", &to::get, &to::set);
856     }
857
858     // If the Link has been added to a diagram, the following lines will dig up its information at model-level
859     Controller controller;
860     m_from = getLinkEnd(*this, controller, SOURCE_PORT);
861     m_to   = getLinkEnd(*this, controller, DESTINATION_PORT);
862 }
863
864 LinkAdapter::LinkAdapter(const LinkAdapter& adapter) :
865     BaseAdapter<LinkAdapter, org_scilab_modules_scicos::model::Link>(adapter),
866     m_from(adapter.getFrom()),
867     m_to(adapter.getTo())
868 {
869 }
870
871 LinkAdapter::~LinkAdapter()
872 {
873 }
874
875 std::wstring LinkAdapter::getTypeStr()
876 {
877     return getSharedTypeStr();
878 }
879 std::wstring LinkAdapter::getShortTypeStr()
880 {
881     return getSharedTypeStr();
882 }
883
884 link_t LinkAdapter::getFrom() const
885 {
886     return m_from;
887 }
888
889 void LinkAdapter::setFrom(const link_t& v)
890 {
891     m_from = v;
892 }
893
894 void LinkAdapter::setFromInModel(const link_t& v, Controller& controller)
895 {
896     m_from = v;
897
898     ScicosID parentDiagram;
899     controller.getObjectProperty(getAdaptee()->id(), LINK, PARENT_DIAGRAM, parentDiagram);
900     ScicosID parentBlock;
901     controller.getObjectProperty(getAdaptee()->id(), LINK, PARENT_BLOCK, parentBlock);
902
903     if (parentDiagram != 0 || parentBlock != 0)
904     {
905         // If the Link has been added to a diagram, do the linking at model-level
906         // If the provided values are wrong, the model is not updated but the info is stored in the Adapter for future attempts
907         setLinkEnd(getAdaptee()->id(), controller, SOURCE_PORT, v);
908     }
909 }
910
911 link_t LinkAdapter::getTo() const
912 {
913     return m_to;
914 }
915
916 void LinkAdapter::setTo(const link_t& v)
917 {
918     m_to = v;
919 }
920
921 void LinkAdapter::setToInModel(const link_t& v, Controller& controller)
922 {
923     m_to = v;
924
925     ScicosID parentDiagram;
926     controller.getObjectProperty(getAdaptee()->id(), LINK, PARENT_DIAGRAM, parentDiagram);
927     ScicosID parentBlock;
928     controller.getObjectProperty(getAdaptee()->id(), LINK, PARENT_BLOCK, parentBlock);
929
930     if (parentDiagram != 0 || parentBlock != 0)
931     {
932         // If the Link has been added to a diagram, do the linking at model-level
933         // If the provided values are wrong, the model is not updated but the info is stored in the Adapter for future attempts
934         setLinkEnd(getAdaptee()->id(), controller, DESTINATION_PORT, v);
935     }
936 }
937
938 } /* namespace view_scilab */
939 } /* namespace org_scilab_modules_scicos */