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