Xcos MVC: implement from / to
[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 <algorithm>
16
17 #include "internal.hxx"
18 #include "list.hxx"
19 #include "types.hxx"
20 #include "user.hxx"
21 #include "double.hxx"
22
23 #include "Controller.hxx"
24 #include "LinkAdapter.hxx"
25
26 namespace org_scilab_modules_scicos
27 {
28 namespace view_scilab
29 {
30 namespace
31 {
32
33 struct xx
34 {
35
36     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
37     {
38         model::Link* adaptee = adaptor.getAdaptee();
39
40         std::vector<double> controlPoints;
41         controller.getObjectProperty(adaptee->id(), adaptee->kind(), CONTROL_POINTS, controlPoints);
42
43         double* data;
44         types::Double* o = new types::Double(controlPoints.size() / 2, 1, &data);
45
46         std::copy(controlPoints.begin(), controlPoints.begin() + controlPoints.size() / 2, data);
47         return o;
48     }
49
50     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
51     {
52         model::Link* adaptee = adaptor.getAdaptee();
53
54         if (v->getType() != types::InternalType::ScilabDouble)
55         {
56             return false;
57         }
58
59         types::Double* current = v->getAs<types::Double>();
60
61         std::vector<double> controlPoints;
62         controller.getObjectProperty(adaptee->id(), adaptee->kind(), CONTROL_POINTS, controlPoints);
63
64         if (current->getSize() != static_cast<int>(controlPoints.size() / 2))
65         {
66             return false;
67         }
68
69         std::copy(current->getReal(), current->getReal() + current->getSize(), controlPoints.begin());
70         controller.setObjectProperty(adaptee->id(), adaptee->kind(), CONTROL_POINTS, controlPoints);
71
72         return true;
73     }
74 };
75
76 struct yy
77 {
78
79     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
80     {
81         model::Link* adaptee = adaptor.getAdaptee();
82
83         std::vector<double> controlPoints;
84         controller.getObjectProperty(adaptee->id(), adaptee->kind(), CONTROL_POINTS, controlPoints);
85
86         double* data;
87         types::Double* o = new types::Double(controlPoints.size() / 2, 1, &data);
88
89         std::copy(controlPoints.begin() + controlPoints.size() / 2, controlPoints.end(), data);
90         return o;
91     }
92
93     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
94     {
95         model::Link* adaptee = adaptor.getAdaptee();
96
97         if (v->getType() != types::InternalType::ScilabDouble)
98         {
99             return false;
100         }
101
102         types::Double* current = v->getAs<types::Double>();
103
104         std::vector<double> controlPoints;
105         controller.getObjectProperty(adaptee->id(), adaptee->kind(), CONTROL_POINTS, controlPoints);
106
107         if (current->getSize() != static_cast<int>(controlPoints.size() / 2))
108         {
109             return false;
110         }
111
112         std::copy(current->getReal(), current->getReal() + current->getSize(), controlPoints.begin() + controlPoints.size() / 2);
113         controller.setObjectProperty(adaptee->id(), adaptee->kind(), CONTROL_POINTS, controlPoints);
114
115         return true;
116     }
117 };
118
119 struct id
120 {
121
122     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
123     {
124         model::Link* adaptee = adaptor.getAdaptee();
125
126         std::string id;
127         controller.getObjectProperty(adaptee->id(), adaptee->kind(), LABEL, id);
128
129         types::String* o = new types::String(1, 1);
130         o->set(0, id.data());
131
132         return o;
133     }
134
135     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
136     {
137         if (v->getType() != types::InternalType::ScilabString)
138         {
139             return false;
140         }
141
142         types::String* current = v->getAs<types::String>();
143         if (current->getSize() != 1)
144         {
145             return false;
146         }
147
148         model::Link* adaptee = adaptor.getAdaptee();
149
150         std::string id;
151         char* c_str = wide_string_to_UTF8(current->get(0));
152         id = std::string(c_str);
153         FREE(c_str);
154
155         controller.setObjectProperty(adaptee->id(), adaptee->kind(), LABEL, id);
156         return true;
157     }
158 };
159
160 struct thick
161 {
162
163     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
164     {
165         model::Link* adaptee = adaptor.getAdaptee();
166
167         std::vector<double> thick;
168         controller.getObjectProperty(adaptee->id(), adaptee->kind(), THICK, thick);
169
170         double* data;
171         types::Double* o = new types::Double(1, 2, &data);
172
173         data[0] = thick[0];
174         data[1] = thick[1];
175         return o;
176     }
177
178     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
179     {
180         model::Link* adaptee = adaptor.getAdaptee();
181
182         if (v->getType() != types::InternalType::ScilabDouble)
183         {
184             return false;
185         }
186
187         types::Double* current = v->getAs<types::Double>();
188         if (current->getRows() != 1 || current->getCols() != 2)
189         {
190             return false;
191         }
192
193         std::vector<double> thick (2);
194         thick[0] = current->get(0);
195         thick[1] = current->get(1);
196
197         controller.setObjectProperty(adaptee->id(), adaptee->kind(), THICK, thick);
198         return true;
199     }
200 };
201
202 struct ct
203 {
204
205     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
206     {
207         model::Link* adaptee = adaptor.getAdaptee();
208
209         int color;
210         int kind;
211         controller.getObjectProperty(adaptee->id(), adaptee->kind(), COLOR, color);
212         controller.getObjectProperty(adaptee->id(), adaptee->kind(), KIND, kind);
213
214         double* data;
215         types::Double* o = new types::Double(1, 2, &data);
216
217         data[0] = static_cast<double>(color);
218         data[1] = static_cast<double>(kind);
219         return o;
220     }
221
222     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
223     {
224         model::Link* adaptee = adaptor.getAdaptee();
225
226         if (v->getType() != types::InternalType::ScilabDouble)
227         {
228             return false;
229         }
230
231         types::Double* current = v->getAs<types::Double>();
232         if (current->getRows() != 1 || current->getCols() != 2)
233         {
234             return false;
235         }
236         if (floor(current->get(0)) != current->get(0) || floor(current->get(1)) != current->get(1))
237         {
238             return false;
239         }
240
241         int color = static_cast<int>(current->get(0));
242         int kind  = static_cast<int>(current->get(1));
243
244         controller.setObjectProperty(adaptee->id(), adaptee->kind(), COLOR, color);
245         controller.setObjectProperty(adaptee->id(), adaptee->kind(), KIND, kind);
246         return true;
247     }
248 };
249
250 static types::Double* getLinkEnd(const LinkAdapter& adaptor, const Controller& controller, object_properties_t end)
251 {
252     model::Link* adaptee = adaptor.getAdaptee();
253
254     double* data;
255     types::Double* o = new types::Double(1, 3, &data);
256     data[0] = 0;
257     data[1] = 0;
258     data[2] = 0;
259
260     ScicosID endID;
261     controller.getObjectProperty(adaptee->id(), adaptee->kind(), end, endID);
262     if (endID != 0)
263     {
264         ScicosID sourceBlock;
265         controller.getObjectProperty(endID, PORT, SOURCE_BLOCK, sourceBlock);
266         int kind;
267         controller.getObjectProperty(endID, PORT, PORT_KIND, kind);
268
269         data[0] = static_cast<double>(sourceBlock);
270         data[1] = static_cast<double>(endID);
271         data[2] = static_cast<double>(kind);
272     }
273     // Default case, the property was initialized at [].
274     return o;
275 }
276
277 static bool setLinkEnd(LinkAdapter& adaptor, Controller& controller, object_properties_t end, types::InternalType* v)
278 {
279     model::Link* adaptee = adaptor.getAdaptee();
280
281     if (v->getType() != types::InternalType::ScilabDouble)
282     {
283         return false;
284     }
285
286     types::Double* current = v->getAs<types::Double>();
287
288     if ((current->getRows() != 1 || current->getCols() != 3) && current->getSize() != 0)
289     {
290         return false; // Must be [] or [x y z]
291     }
292
293     ScicosID from;
294     controller.getObjectProperty(adaptee->id(), adaptee->kind(), SOURCE_PORT, from);
295     ScicosID to;
296     controller.getObjectProperty(adaptee->id(), adaptee->kind(), DESTINATION_PORT, to);
297     ScicosID concernedPort;
298     object_properties_t otherEnd;
299     object_properties_t portType;
300     switch (end)
301     {
302         case SOURCE_PORT:
303             concernedPort = from;
304             otherEnd = DESTINATION_PORT;
305             portType = OUTPUTS;
306             break;
307         case DESTINATION_PORT:
308             concernedPort = to;
309             otherEnd = SOURCE_PORT;
310             portType = INPUTS;
311             break;
312         default:
313             return false;
314     }
315     ScicosID unconnected = 0;
316
317     if (current->getSize() == 0 || (current->get(0) == 0 || current->get(1) == 0))
318     {
319         // We want to set an empty link
320         if (concernedPort == 0)
321         {
322             // In this case, the link was already empty, do a dummy call to display the console status.
323             controller.setObjectProperty(adaptee->id(), adaptee->kind(), end, concernedPort);
324         }
325         else
326         {
327             // Untie the old link on both ends and set the 2 concerned ports as unconnected
328             controller.setObjectProperty(from, PORT, CONNECTED_SIGNALS, unconnected);
329             controller.setObjectProperty(to, PORT, CONNECTED_SIGNALS, unconnected);
330
331             controller.setObjectProperty(adaptee->id(), adaptee->kind(), SOURCE_PORT, unconnected);
332             controller.setObjectProperty(adaptee->id(), adaptee->kind(), DESTINATION_PORT, unconnected);
333         }
334         return true;
335     }
336
337     if (current->get(2) != 0 && current->get(2) != 1)
338     {
339         return false; // "From" port must be output type or implicit.
340     }
341
342     if (floor(current->get(0)) != current->get(0) || floor(current->get(1)) != current->get(1))
343     {
344         return false; // Must be an integer value
345     }
346
347     // Disconnect the old port if it was connected
348     if (from != 0)
349     {
350         controller.setObjectProperty(concernedPort, PORT, CONNECTED_SIGNALS, unconnected);
351     }
352
353     // Connect the new one
354     int blk  = static_cast<int>(current->get(0));
355     int port = static_cast<int>(current->get(1));
356     int kind = static_cast<int>(current->get(2));
357     std::vector<ScicosID> sourceBlockPorts;
358     controller.getObjectProperty(blk, BLOCK, portType, sourceBlockPorts);
359     int nBlockPorts = sourceBlockPorts.size();
360     // Create as many ports as necessary
361     while (nBlockPorts < port)
362     {
363         ScicosID createdPort = controller.createObject(PORT);
364         controller.setObjectProperty(createdPort, PORT, SOURCE_BLOCK, blk);
365         controller.setObjectProperty(createdPort, PORT, CONNECTED_SIGNALS, unconnected);
366         nBlockPorts++;
367     }
368     controller.getObjectProperty(blk, BLOCK, portType, sourceBlockPorts);
369     ScicosID newPort = sourceBlockPorts[port - 1];
370     ScicosID oldLink;
371     controller.getObjectProperty(newPort, PORT, CONNECTED_SIGNALS, oldLink);
372     if (oldLink != 0)
373     {
374         // Disconnect the old other end port and delete the old link
375         ScicosID oldPort;
376         controller.getObjectProperty(oldLink, LINK, otherEnd, oldPort);
377         controller.setObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, unconnected);
378         controller.deleteObject(oldLink);
379     }
380
381     // Connect the new source and destination ports together
382     controller.setObjectProperty(newPort, PORT, PORT_KIND, kind);
383     controller.setObjectProperty(newPort, PORT, CONNECTED_SIGNALS, adaptee->id());
384     controller.setObjectProperty(concernedPort, PORT, CONNECTED_SIGNALS, adaptee->id());
385     controller.setObjectProperty(adaptee->id(), adaptee->kind(), end, newPort);
386     return true;
387 }
388
389 struct from
390 {
391
392     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
393     {
394         return getLinkEnd(adaptor, controller, SOURCE_PORT);
395     }
396
397     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
398     {
399         return setLinkEnd(adaptor, controller, SOURCE_PORT, v);
400     }
401 };
402
403 struct to
404 {
405
406     static types::InternalType* get(const LinkAdapter& adaptor, const Controller& controller)
407     {
408         return getLinkEnd(adaptor, controller, DESTINATION_PORT);
409     }
410
411     static bool set(LinkAdapter& adaptor, types::InternalType* v, Controller& controller)
412     {
413         return setLinkEnd(adaptor, controller, DESTINATION_PORT, v);
414     }
415 };
416
417 } /* namespace */
418
419 template<> property<LinkAdapter>::props_t property<LinkAdapter>::fields = property<LinkAdapter>::props_t();
420
421 LinkAdapter::LinkAdapter(const LinkAdapter& o) :
422     BaseAdapter<LinkAdapter, org_scilab_modules_scicos::model::Link>(o) {}
423
424 LinkAdapter::LinkAdapter(org_scilab_modules_scicos::model::Link* o) :
425     BaseAdapter<LinkAdapter, org_scilab_modules_scicos::model::Link>(o)
426 {
427     if (property<LinkAdapter>::properties_has_not_been_set())
428     {
429         property<LinkAdapter>::fields.reserve(7);
430         property<LinkAdapter>::add_property(L"xx", &xx::get, &xx::set);
431         property<LinkAdapter>::add_property(L"yy", &yy::get, &yy::set);
432         property<LinkAdapter>::add_property(L"id", &id::get, &id::set);
433         property<LinkAdapter>::add_property(L"thick", &thick::get, &thick::set);
434         property<LinkAdapter>::add_property(L"ct", &ct::get, &ct::set);
435         property<LinkAdapter>::add_property(L"from", &from::get, &from::set);
436         property<LinkAdapter>::add_property(L"to", &to::get, &to::set);
437     }
438 }
439
440 LinkAdapter::~LinkAdapter()
441 {
442 }
443
444 std::wstring LinkAdapter::getTypeStr()
445 {
446     return getSharedTypeStr();
447 }
448 std::wstring LinkAdapter::getShortTypeStr()
449 {
450     return getSharedTypeStr();
451 }
452
453 } /* namespace view_scilab */
454 } /* namespace org_scilab_modules_scicos */