Xcos MVC: fix memleak in list insertion
[scilab.git] / scilab / modules / scicos / src / cpp / view_scilab / ParamsAdapter.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 "double.hxx"
18 #include "string.hxx"
19 #include "bool.hxx"
20 #include "list.hxx"
21 #include "tlist.hxx"
22
23 #include "utilities.hxx"
24 #include "Controller.hxx"
25 #include "controller_helpers.hxx"
26 #include "ParamsAdapter.hxx"
27
28 extern "C" {
29 #include "sci_malloc.h"
30 #include "charEncoding.h"
31 #include "localization.h"
32 }
33
34 namespace org_scilab_modules_scicos
35 {
36 namespace view_scilab
37 {
38 namespace
39 {
40
41 const std::wstring scsopt(L"scsopt");
42 const std::wstring ThreeD(L"3D");
43 const std::wstring Background(L"Background");
44 const std::wstring Link(L"Link");
45 const std::wstring ID(L"ID");
46 const std::wstring Cmap(L"Cmap");
47
48 struct dummy_property
49 {
50
51     static types::InternalType* get(const ParamsAdapter& /*adaptor*/, const Controller& /*controller*/)
52     {
53         // Return a default empty matrix.
54         return types::Double::Empty();
55     }
56
57     static bool set(ParamsAdapter& /*adaptor*/, types::InternalType* /*v*/, Controller& /*controller*/)
58     {
59         // everything should be right as the properties mapped using this adapter do not perform anything
60         return true;
61     }
62 };
63
64 struct wpar
65 {
66
67     static types::InternalType* get(const ParamsAdapter& adaptor, const Controller& controller)
68     {
69         types::Double* ret = new types::Double(1, 6);
70         ret->set(0, 600);
71         ret->set(1, 450);
72         ret->set(2, 0);
73         ret->set(3, 0);
74         ret->set(4, 600);
75         ret->set(5, 450);
76         return ret;
77     }
78
79     static bool set(ParamsAdapter& adaptor, types::InternalType* v, Controller& controller)
80     {
81         // The model does not store 'wpar'.
82         return dummy_property::set(adaptor, v, controller);
83     }
84 };
85
86 struct title
87 {
88
89     static types::InternalType* get(const ParamsAdapter& adaptor, const Controller& controller)
90     {
91         ScicosID adaptee = adaptor.getAdaptee()->id();
92
93         std::string title;
94         controller.getObjectProperty(adaptee, DIAGRAM, TITLE, title);
95         std::string path;
96         controller.getObjectProperty(adaptee, DIAGRAM, PATH, path);
97
98         types::String* o = new types::String(2, 1);
99         o->set(0, title.data());
100         o->set(1, path.data());
101
102         return o;
103     }
104
105     static bool set(ParamsAdapter& adaptor, types::InternalType* v, Controller& controller)
106     {
107         if (v->getType() != types::InternalType::ScilabString)
108         {
109             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: String expected.\n"), "params", "title");
110             return false;
111         }
112
113         ScicosID adaptee = adaptor.getAdaptee()->id();
114
115         std::string path;
116         std::string title;
117         types::String* current = v->getAs<types::String>();
118         if (current->getSize() == 1)
119         {
120             // Pass an empty path
121         }
122         else if (current->getSize() == 2)
123         {
124             char* Path = wide_string_to_UTF8(current->get(1));
125             path = std::string(Path);
126             FREE(Path);
127         }
128         else
129         {
130             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: String expected.\n"), "params", "title");
131             return false;
132         }
133
134         char* Title = wide_string_to_UTF8(current->get(0));
135         title = std::string(Title);
136         FREE(Title);
137
138         controller.setObjectProperty(adaptee, DIAGRAM, TITLE, title);
139         controller.setObjectProperty(adaptee, DIAGRAM, PATH, path);
140         return true;
141     }
142 };
143
144 struct tol
145 {
146
147     static types::InternalType* get(const ParamsAdapter& adaptor, const Controller& controller)
148     {
149         ScicosID adaptee = adaptor.getAdaptee()->id();
150
151         double* data;
152         types::Double* o = new types::Double(1, 7, &data);
153
154         std::vector<double> tol;
155         controller.getObjectProperty(adaptee, DIAGRAM, PROPERTIES, tol);
156 #ifdef _MSC_VER
157         std::copy(tol.begin() + 1, tol.end(), stdext::checked_array_iterator<double*>( data, 7 ));
158 #else
159         std::copy(tol.begin() + 1, tol.end(), data);
160 #endif
161
162         return o;
163     }
164
165     static bool set(ParamsAdapter& adaptor, types::InternalType* v, Controller& controller)
166     {
167
168         if (v->getType() != types::InternalType::ScilabDouble)
169         {
170             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Real matrix expected.\n"), "params", "tol");
171             return false;
172         }
173
174         types::Double* current = v->getAs<types::Double>();
175         if (current->getSize() != 6 && current->getSize() != 7)
176         {
177             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: %d-by-%d expected.\n"), "params", "tol", 7, 1);
178             return false;
179         }
180
181         ScicosID adaptee = adaptor.getAdaptee()->id();
182
183         std::vector<double> tol;
184         controller.getObjectProperty(adaptee, DIAGRAM, PROPERTIES, tol);
185
186         std::copy(current->getReal(), current->getReal() + current->getSize(), tol.begin() + 1);
187
188         // In case the last parameter is missing
189         if (current->getSize() == 6)
190         {
191             tol[7] = 0;
192         }
193
194         controller.setObjectProperty(adaptee, DIAGRAM, PROPERTIES, tol);
195         return true;
196     }
197 };
198
199 struct tf
200 {
201
202     static types::InternalType* get(const ParamsAdapter& adaptor, const Controller& controller)
203     {
204         ScicosID adaptee = adaptor.getAdaptee()->id();
205
206         std::vector<double> tf;
207         controller.getObjectProperty(adaptee, DIAGRAM, PROPERTIES, tf);
208
209         return new types::Double(tf[0]);
210     }
211
212     static bool set(ParamsAdapter& adaptor, types::InternalType* v, Controller& controller)
213     {
214
215         if (v->getType() != types::InternalType::ScilabDouble)
216         {
217             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s: Real expected.\n"), "params", "tf");
218             return false;
219         }
220
221         types::Double* current = v->getAs<types::Double>();
222         if (current->getSize() != 1)
223         {
224             get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: Real expected.\n"), "params", "tf");
225             return false;
226         }
227
228         ScicosID adaptee = adaptor.getAdaptee()->id();
229
230         std::vector<double> tol;
231         controller.getObjectProperty(adaptee, DIAGRAM, PROPERTIES, tol);
232
233         tol[0] = current->get(0);
234
235         controller.setObjectProperty(adaptee, DIAGRAM, PROPERTIES, tol);
236         return true;
237     }
238 };
239
240 struct context
241 {
242
243     static types::InternalType* get(const ParamsAdapter& adaptor, const Controller& controller)
244     {
245         ScicosID adaptee = adaptor.getAdaptee()->id();
246
247         std::vector<std::string> context;
248         controller.getObjectProperty(adaptee, DIAGRAM, DIAGRAM_CONTEXT, context);
249
250         if (context.size() == 0)
251         {
252             // An empty context returns an empty matrix
253             return types::Double::Empty();
254         }
255
256         types::String* o = new types::String((int)context.size(), 1);
257         for (int i = 0; i < (int)context.size(); ++i)
258         {
259             o->set(i, context[i].data());
260         }
261
262         return o;
263     }
264
265     static bool set(ParamsAdapter& adaptor, types::InternalType* v, Controller& controller)
266     {
267         if (v->getType() == types::InternalType::ScilabString)
268         {
269             types::String* current = v->getAs<types::String>();
270             // Only allow vectors and empty matrices
271             if (!current->isVector() && current->getSize() != 0)
272             {
273                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong dimension for field %s.%s: m-by-1 expected.\n"), "params", "context");
274                 return false;
275             }
276
277             ScicosID adaptee = adaptor.getAdaptee()->id();
278
279             std::vector<std::string> context (current->getSize());
280             for (int i = 0; i < (int)context.size(); ++i)
281             {
282                 char* c_str = wide_string_to_UTF8(current->get(i));
283                 context[i] = std::string(c_str);
284                 FREE(c_str);
285             }
286
287             controller.setObjectProperty(adaptee, DIAGRAM, DIAGRAM_CONTEXT, context);
288             return true;
289         }
290         else if (v->getType() == types::InternalType::ScilabDouble)
291         {
292             types::Double* current = v->getAs<types::Double>();
293             if (!current->isEmpty())
294             {
295                 get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : string expected.\n"), "params", "context");
296                 return false;
297             }
298
299             ScicosID adaptee = adaptor.getAdaptee()->id();
300
301             std::vector<std::string> context;
302             controller.setObjectProperty(adaptee, DIAGRAM, DIAGRAM_CONTEXT, context);
303             return true;
304         }
305
306         get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s.%s : string expected.\n"), "params", "context");
307         return false;
308     }
309 };
310
311 struct options
312 {
313
314     static types::InternalType* get(const ParamsAdapter& /*adaptor*/, const Controller& /*controller*/)
315     {
316         // Return a default 'scsopt'-typed tlist.
317         types::String* header = new types::String(1, 6);
318         header->set(0, scsopt.c_str());
319         header->set(1, ThreeD.c_str());
320         header->set(2, Background.c_str());
321         header->set(3, Link.c_str());
322         header->set(4, ID.c_str());
323         header->set(5, Cmap.c_str());
324
325         types::TList* Scsopt = new types::TList();
326         Scsopt->append(header);
327
328         types::List* ThreeDField = new types::List();
329         types::Bool* ThreeD1 = new types::Bool(1);
330         ThreeDField->append(ThreeD1);
331         types::Double* ThreeD2 = new types::Double(33);
332         ThreeDField->append(ThreeD2);
333         Scsopt->append(ThreeDField);
334         ThreeDField->killMe();
335
336         types::Double* BackgroundField = new types::Double(1, 2);
337         BackgroundField->set(0, 8);
338         BackgroundField->set(1, 1);
339         Scsopt->append(BackgroundField);
340
341         types::Double* LinkField = new types::Double(1, 2);
342         LinkField->set(0, 1);
343         LinkField->set(1, 5);
344         Scsopt->append(LinkField);
345
346         types::List* IDField = new types::List();
347         types::Double* ID1 = new types::Double(1, 4);
348         ID1->set(0, 4);
349         ID1->set(1, 1);
350         ID1->set(2, 10);
351         ID1->set(3, 1);
352         IDField->append(ID1);
353         types::Double* ID2 = new types::Double(1, 4);
354         ID2->set(0, 4);
355         ID2->set(1, 1);
356         ID2->set(2, 2);
357         ID2->set(3, 1);
358         IDField->append(ID2);
359         Scsopt->append(IDField);
360         IDField->killMe();
361
362         types::Double* CmapField = new types::Double(1, 3);
363         CmapField->set(0, 0.8);
364         CmapField->set(1, 0.8);
365         CmapField->set(2, 0.8);
366         Scsopt->append(CmapField);
367
368         return Scsopt;
369     }
370
371     static bool set(ParamsAdapter& adaptor, types::InternalType* v, Controller& controller)
372     {
373         // The model does not store 'options'.
374         return dummy_property::set(adaptor, v, controller);
375     }
376 };
377
378 struct doc
379 {
380     static types::InternalType* get(const ParamsAdapter& adaptor, const Controller& /*controller*/)
381     {
382         return adaptor.getDocContent();
383     }
384
385     static bool set(ParamsAdapter& adaptor, types::InternalType* v, Controller& /*controller*/)
386     {
387         adaptor.setDocContent(v->clone());
388         return true;
389     }
390 };
391
392 } /* namespace */
393
394 template<> property<ParamsAdapter>::props_t property<ParamsAdapter>::fields = property<ParamsAdapter>::props_t();
395 static void initialize_fields()
396 {
397     if (property<ParamsAdapter>::properties_have_not_been_set())
398     {
399         property<ParamsAdapter>::fields.reserve(10);
400         property<ParamsAdapter>::add_property(L"wpar", &wpar::get, &wpar::set);
401         property<ParamsAdapter>::add_property(L"title", &title::get, &title::set);
402         property<ParamsAdapter>::add_property(L"tol", &tol::get, &tol::set);
403         property<ParamsAdapter>::add_property(L"tf", &tf::get, &tf::set);
404         property<ParamsAdapter>::add_property(L"context", &context::get, &context::set);
405         property<ParamsAdapter>::add_property(L"void1", &dummy_property::get, &dummy_property::set);
406         property<ParamsAdapter>::add_property(L"options", &options::get, &options::set);
407         property<ParamsAdapter>::add_property(L"void2", &dummy_property::get, &dummy_property::set);
408         property<ParamsAdapter>::add_property(L"void3", &dummy_property::get, &dummy_property::set);
409         property<ParamsAdapter>::add_property(L"doc", &doc::get, &doc::set);
410     }
411 }
412
413 ParamsAdapter::ParamsAdapter() :
414     BaseAdapter<ParamsAdapter, org_scilab_modules_scicos::model::Diagram>(),
415     doc_content(new types::List())
416 {
417     initialize_fields();
418 }
419
420 ParamsAdapter::ParamsAdapter(const Controller& c, org_scilab_modules_scicos::model::Diagram* adaptee) :
421     BaseAdapter<ParamsAdapter, org_scilab_modules_scicos::model::Diagram>(c, adaptee),
422     doc_content(new types::List())
423 {
424     initialize_fields();
425 }
426
427 ParamsAdapter::~ParamsAdapter()
428 {
429     doc_content->DecreaseRef();
430     doc_content->killMe();
431 }
432
433 std::wstring ParamsAdapter::getTypeStr()
434 {
435     return getSharedTypeStr();
436 }
437 std::wstring ParamsAdapter::getShortTypeStr()
438 {
439     return getSharedTypeStr();
440 }
441
442 types::InternalType* ParamsAdapter::getDocContent() const
443 {
444     doc_content->IncreaseRef();
445     return doc_content;
446 }
447
448 void ParamsAdapter::setDocContent(types::InternalType* v)
449 {
450     doc_content->DecreaseRef();
451     doc_content->killMe();
452
453     v->IncreaseRef();
454     doc_content = v;
455 }
456
457 } /* namespace view_scilab */
458 } /* namespace org_scilab_modules_scicos */