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