ea95544b284f90ae8c665c6d782cddc844a4c3ed
[scilab.git] / scilab / modules / scicos / src / cpp / view_scilab / BlockAdapter.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 <memory>
16
17 #include "internal.hxx"
18 #include "list.hxx"
19 #include "mlist.hxx"
20 #include "string.hxx"
21 #include "types.hxx"
22 #include "user.hxx"
23
24 #include "Controller.hxx"
25 #include "model/Block.hxx"
26 #include "BlockAdapter.hxx"
27 #include "DiagramAdapter.hxx"
28 #include "GraphicsAdapter.hxx"
29 #include "LinkAdapter.hxx"
30 #include "ModelAdapter.hxx"
31 #include "TextAdapter.hxx"
32
33 extern "C" {
34 #include "sci_malloc.h"
35 #include "charEncoding.h"
36 }
37
38 namespace org_scilab_modules_scicos
39 {
40 namespace view_scilab
41 {
42 namespace
43 {
44
45 struct graphics
46 {
47     static types::InternalType* get(const BlockAdapter& adaptor, const Controller& controller)
48     {
49         GraphicsAdapter localAdaptor = GraphicsAdapter(adaptor.getAdaptee());
50         return localAdaptor.getAsTList(new types::MList(), controller);
51     }
52
53     static bool set(BlockAdapter& adaptor, types::InternalType* v, Controller& controller)
54     {
55         GraphicsAdapter localAdaptor = GraphicsAdapter(adaptor.getAdaptee());
56         return localAdaptor.setAsTList(v, controller);
57     }
58 };
59
60 struct model
61 {
62     static types::InternalType* get(const BlockAdapter& adaptor, const Controller& controller)
63     {
64         ModelAdapter localAdaptor = ModelAdapter(adaptor.getAdaptee());
65         localAdaptor.setDiagram(adaptor.getDiagram());
66
67         return localAdaptor.getAsTList(new types::MList(), controller)->getAs<types::MList>();
68     }
69
70     static bool set(BlockAdapter& adaptor, types::InternalType* v, Controller& controller)
71     {
72         ModelAdapter localAdaptor = ModelAdapter(adaptor.getAdaptee());
73         if (!localAdaptor.setAsTList(v, controller))
74         {
75             return false;
76         }
77
78         adaptor.setDiagram(localAdaptor.getRpar());
79
80         return true;
81     }
82 };
83
84 struct gui
85 {
86     static types::InternalType* get(const BlockAdapter& adaptor, const Controller& controller)
87     {
88         std::string Interface;
89         ScicosID adaptee = adaptor.getAdaptee()->id();
90         controller.getObjectProperty(adaptee, BLOCK, INTERFACE_FUNCTION, Interface);
91
92         return new types::String(Interface.data());
93     }
94
95     static bool set(BlockAdapter& adaptor, types::InternalType* v, Controller& controller)
96     {
97         if (v->getType() != types::InternalType::ScilabString)
98         {
99             return false;
100         }
101
102         types::String* current = v->getAs<types::String>();
103         if (current->getRows() != 1 || current->getCols() != 1)
104         {
105             return false;
106         }
107
108         wchar_t* w_name = current->get(0);
109         char* name = wide_string_to_UTF8(w_name);
110         std::string stName(name);
111         FREE(name);
112
113         ScicosID adaptee = adaptor.getAdaptee()->id();
114         controller.setObjectProperty(adaptee, BLOCK, INTERFACE_FUNCTION, stName);
115         return true;
116     }
117 };
118
119 struct doc
120 {
121     static types::InternalType* get(const BlockAdapter& adaptor, const Controller& /*controller*/)
122     {
123         return adaptor.getDocContent();
124     }
125
126     static bool set(BlockAdapter& adaptor, types::InternalType* v, Controller& /*controller*/)
127     {
128         adaptor.setDocContent(v->clone());
129         return true;
130     }
131 };
132
133 } /* namespace */
134
135 template<> property<BlockAdapter>::props_t property<BlockAdapter>::fields = property<BlockAdapter>::props_t();
136
137 BlockAdapter::BlockAdapter(std::shared_ptr<org_scilab_modules_scicos::model::Block> adaptee) :
138     BaseAdapter<BlockAdapter, org_scilab_modules_scicos::model::Block>(adaptee),
139     diagramAdapter(nullptr),
140     doc_content(new types::List())
141 {
142     if (property<BlockAdapter>::properties_have_not_been_set())
143     {
144         property<BlockAdapter>::fields.reserve(4);
145         property<BlockAdapter>::add_property(L"graphics", &graphics::get, &graphics::set);
146         property<BlockAdapter>::add_property(L"model", &model::get, &model::set);
147         property<BlockAdapter>::add_property(L"gui", &gui::get, &gui::set);
148         property<BlockAdapter>::add_property(L"doc", &doc::get, &doc::set);
149     }
150 }
151
152 BlockAdapter::BlockAdapter(const BlockAdapter& adapter) :
153     BaseAdapter<BlockAdapter, org_scilab_modules_scicos::model::Block>(adapter),
154     diagramAdapter(),
155     doc_content(adapter.getDocContent())
156 {
157     Controller controller;
158     std::vector<ScicosID> diagramChild;
159     controller.getObjectProperty(getAdaptee()->id(), BLOCK, CHILDREN, diagramChild);
160
161     if (!diagramChild.empty())
162     {
163         std::shared_ptr<org_scilab_modules_scicos::model::Diagram> diagram = std::static_pointer_cast<org_scilab_modules_scicos::model::Diagram>(controller.getObject(diagramChild[0]));
164         diagramAdapter = new DiagramAdapter(diagram);
165
166         // Extract the information of the old cloned diagram
167         DiagramAdapter* oldDiagram = adapter.getDiagram();
168         types::List* oldList_objects = oldDiagram->getListObjects()->getAs<types::List>();
169         std::vector<link_t> from_vec = oldDiagram->getFrom();
170         std::vector<link_t> to_vec = oldDiagram->getTo();
171
172         std::vector<ScicosID> diagramChildren;
173         controller.getObjectProperty(diagram->id(), DIAGRAM, CHILDREN, diagramChildren);
174
175         // FIXME: factor the following code with DiagramAdapter copy constructor?
176         std::vector<LinkAdapter*> linkListView; // Store the new LinkAdapters to make the linking at model-level after the loop
177         types::List* List_objects = new types::List();
178         for (int i = 0; i < static_cast<int>(diagramChildren.size()); ++i)
179         {
180             std::shared_ptr<org_scilab_modules_scicos::model::BaseObject> item = controller.getObject(diagramChildren[i]);
181             switch (item->kind())
182             {
183                 case ANNOTATION:
184                 {
185                     std::shared_ptr<org_scilab_modules_scicos::model::Annotation> annotation = std::static_pointer_cast<org_scilab_modules_scicos::model::Annotation>(item);
186                     TextAdapter* localAdaptor = new TextAdapter(annotation);
187
188                     List_objects->set(i, localAdaptor);
189                     continue;
190                 }
191                 case BLOCK:
192                 {
193                     std::shared_ptr<org_scilab_modules_scicos::model::Block> block = std::static_pointer_cast<org_scilab_modules_scicos::model::Block>(item);
194                     BlockAdapter* localAdaptor = new BlockAdapter(block);
195
196                     // If the diagram's block was a SuperBlock, make its new adapter point to its old diagram
197                     if (i < oldList_objects->getSize())
198                     {
199                         BlockAdapter* oldBlock = oldList_objects->get(i)->getAs<BlockAdapter>();
200                         DiagramAdapter* oldBlockDiagram = oldBlock->getDiagram();
201                         if (oldBlockDiagram != nullptr)
202                         {
203                             oldBlockDiagram->IncreaseRef();
204                         }
205                         localAdaptor->setDiagram(oldBlockDiagram);
206                     }
207
208                     List_objects->set(i, localAdaptor);
209                     continue;
210                 }
211                 case LINK:
212                 {
213                     std::shared_ptr<org_scilab_modules_scicos::model::Link> link = std::static_pointer_cast<org_scilab_modules_scicos::model::Link>(item);
214                     LinkAdapter* localAdaptor = new LinkAdapter(link);
215
216                     // Do the model linking in the next loop, in case the Link points to a Block that has not been added yet
217                     linkListView.push_back(localAdaptor);
218
219                     List_objects->set(i, localAdaptor);
220                     continue;
221                 }
222                 default:
223                 {
224                 }
225             }
226         }
227
228         // Do the linking at model-level, from the old 'from_vec' and 'to_vec'
229         for (int i = 0; i < static_cast<int>(linkListView.size()); ++i)
230         {
231             // Trigger 'from' and 'to' properties
232             linkListView[i]->setFromInModel(from_vec[i], controller);
233             linkListView[i]->setToInModel(to_vec[i], controller);
234         }
235
236         diagramAdapter->setListObjects(List_objects);
237         diagramAdapter->setFrom(from_vec);
238         diagramAdapter->setTo(to_vec);
239     }
240 }
241
242 BlockAdapter::~BlockAdapter()
243 {
244     if (diagramAdapter != nullptr)
245     {
246         // Update the model if the adaptee is being deleted
247         if (getAdaptee().use_count() == 3)
248         {
249             Controller controller;
250             controller.setObjectProperty(getAdaptee()->id(), BLOCK, CHILDREN, std::vector<ScicosID>());
251         }
252
253         diagramAdapter->DecreaseRef();
254         diagramAdapter->killMe();
255     }
256
257     doc_content->DecreaseRef();
258     doc_content->killMe();
259 }
260
261 std::wstring BlockAdapter::getTypeStr()
262 {
263     return getSharedTypeStr();
264 }
265
266 std::wstring BlockAdapter::getShortTypeStr()
267 {
268     return getSharedTypeStr();
269 }
270
271 DiagramAdapter* BlockAdapter::getDiagram() const
272 {
273     if (diagramAdapter != nullptr)
274     {
275         diagramAdapter->IncreaseRef();
276     }
277     return diagramAdapter;
278 }
279
280 void BlockAdapter::setDiagram(DiagramAdapter* v)
281 {
282     if (v != nullptr)
283     {
284         // The old 'diagramAdapter' needs to be freed after setting it to 'v'
285         DiagramAdapter* temp = diagramAdapter;
286
287         diagramAdapter = v;
288
289         if (temp != nullptr)
290         {
291             temp->DecreaseRef();
292             temp->killMe();
293         }
294     }
295 }
296
297 types::InternalType* BlockAdapter::getDocContent() const
298 {
299     doc_content->IncreaseRef();
300     return doc_content;
301 }
302
303 void BlockAdapter::setDocContent(types::InternalType* v)
304 {
305     doc_content->DecreaseRef();
306     doc_content->killMe();
307
308     v->IncreaseRef();
309     doc_content = v;
310 }
311
312 } /* namespace view_scilab */
313 } /* namespace org_scilab_modules_scicos */