Xcos MVC: detect deleted objects
[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  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 #include <cwchar>
17
18 #include <string>
19 #include <vector>
20
21 #include "internal.hxx"
22 #include "list.hxx"
23 #include "mlist.hxx"
24 #include "string.hxx"
25 #include "types.hxx"
26
27 #include "utilities.hxx"
28 #include "adapters_utilities.hxx"
29 #include "Controller.hxx"
30 #include "model/Block.hxx"
31 #include "BlockAdapter.hxx"
32 #include "DiagramAdapter.hxx"
33 #include "GraphicsAdapter.hxx"
34 #include "LinkAdapter.hxx"
35 #include "ModelAdapter.hxx"
36 #include "TextAdapter.hxx"
37
38 extern "C" {
39 #include "sci_malloc.h"
40 #include "charEncoding.h"
41 }
42
43 namespace org_scilab_modules_scicos
44 {
45 namespace view_scilab
46 {
47 namespace
48 {
49
50 struct graphics
51 {
52     static types::InternalType* get(const BlockAdapter& adaptor, const Controller& controller)
53     {
54         GraphicsAdapter localAdaptor(controller, controller.referenceObject(adaptor.getAdaptee()));
55         types::InternalType* v = localAdaptor.getAsTList(new types::MList(), controller);
56         return v;
57     }
58
59     static bool set(BlockAdapter& adaptor, types::InternalType* v, Controller& controller)
60     {
61         GraphicsAdapter localAdaptor(controller, controller.referenceObject(adaptor.getAdaptee()));
62         return localAdaptor.setAsTList(v, controller);
63     }
64 };
65
66 struct model
67 {
68     static types::InternalType* get(const BlockAdapter& adaptor, const Controller& controller)
69     {
70         // If we are in a Superblock (has children) then reconstruct a DiagramAdapter, referencing the children
71         DiagramAdapter* subDiagram = nullptr;
72         std::vector<ScicosID> children;
73         controller.getObjectProperty(adaptor.getAdaptee()->id(), BLOCK, CHILDREN, children);
74         if (!children.empty())
75         {
76             if (adaptor.getListObjects()->getSize() > 0)
77             {
78                 Controller neededController = const_cast<Controller&>(controller);
79                 ScicosID newDiag = neededController.createObject(DIAGRAM);
80                 subDiagram = new DiagramAdapter(controller, static_cast<org_scilab_modules_scicos::model::Diagram*>(controller.getObject(newDiag)));
81                 neededController.setObjectProperty(newDiag, DIAGRAM, CHILDREN, children);
82
83                 for (const ScicosID id : children)
84                 {
85                     if (id == ScicosID())
86                     {
87                         // Deleted object
88                     }
89                     else
90                     {
91                         auto o = controller.getObject(id);
92                         neededController.setObjectProperty(o->id(), o->kind(), PARENT_DIAGRAM, newDiag);
93                         neededController.referenceObject(o->id());
94                     }
95                 }
96                 subDiagram->setFrom(adaptor.getFrom());
97                 subDiagram->setTo(adaptor.getTo());
98                 subDiagram->setListObjects(adaptor.getListObjects());
99                 subDiagram->setContribContent(adaptor.getContribContent());
100
101                 std::vector<std::string> context;
102                 controller.getObjectProperty(adaptor.getAdaptee()->id(), BLOCK, DIAGRAM_CONTEXT, context);
103                 neededController.setObjectProperty(newDiag, DIAGRAM, DIAGRAM_CONTEXT, context);
104             }
105             else
106             {
107                 // The children adapters list has not been set yet. Create it, update the adapter and return.
108                 types::List* listObjects = new types::List();
109                 std::vector<link_t> from;
110                 std::vector<link_t> to;
111                 for (const ScicosID id : children)
112                 {
113                     if (id == ScicosID())
114                     {
115                         // Deleted object
116                     }
117                     else
118                     {
119                         auto o = controller.getObject(id);
120                         controller.referenceObject(o);
121
122                         switch (o->kind())
123                         {
124                             case ANNOTATION :
125                                 listObjects->append(new TextAdapter(controller, static_cast<org_scilab_modules_scicos::model::Annotation*>(o)));
126                                 break;
127                             case BLOCK :
128                             {
129                                 BlockAdapter* block = new BlockAdapter(controller, static_cast<org_scilab_modules_scicos::model::Block*>(o));
130                                 listObjects->append(block);
131                                 break;
132                             }
133                             default : // LINK
134                                 LinkAdapter* link = new LinkAdapter(controller, static_cast<org_scilab_modules_scicos::model::Link*>(o));
135                                 from.push_back(link->getFrom());
136                                 to.push_back(link->getTo());
137                                 listObjects->append(link);
138                                 break;
139                         }
140                     }
141                 }
142                 const_cast<BlockAdapter&>(adaptor).setFrom(from);
143                 const_cast<BlockAdapter&>(adaptor).setTo(to);
144                 const_cast<BlockAdapter&>(adaptor).setListObjects(listObjects);
145                 return nullptr;
146             }
147         }
148
149         ModelAdapter localAdaptor(controller, controller.referenceObject(adaptor.getAdaptee()), subDiagram);
150         types::InternalType* mlist = localAdaptor.getAsTList(new types::MList(), controller)->getAs<types::MList>();
151
152         if (localAdaptor.getDiagram() != nullptr)
153         {
154             // To handle the copy constructor case calling model::set
155             const_cast<BlockAdapter&>(adaptor).setFrom(localAdaptor.getDiagram()->getFrom());
156             const_cast<BlockAdapter&>(adaptor).setTo(localAdaptor.getDiagram()->getTo());
157             const_cast<BlockAdapter&>(adaptor).setListObjects(localAdaptor.getDiagram()->getListObjects());
158             const_cast<BlockAdapter&>(adaptor).setContribContent(localAdaptor.getDiagram()->getContribContent());
159         }
160
161         return mlist;
162     }
163
164     static bool set(BlockAdapter& adaptor, types::InternalType* v, Controller& controller)
165     {
166         ModelAdapter localAdaptor(controller, controller.referenceObject(adaptor.getAdaptee()), nullptr);
167         if (!localAdaptor.setAsTList(v, controller))
168         {
169             return false;
170         }
171
172         if (localAdaptor.getDiagram() != nullptr)
173         {
174             adaptor.setFrom(localAdaptor.getDiagram()->getFrom());
175             adaptor.setTo(localAdaptor.getDiagram()->getTo());
176             adaptor.setListObjects(localAdaptor.getDiagram()->getListObjects());
177             adaptor.setContribContent(localAdaptor.getDiagram()->getContribContent());
178         }
179         return true;
180     }
181 };
182
183 struct gui
184 {
185     static types::InternalType* get(const BlockAdapter& adaptor, const Controller& controller)
186     {
187         std::string Interface;
188         ScicosID adaptee = adaptor.getAdaptee()->id();
189         controller.getObjectProperty(adaptee, BLOCK, INTERFACE_FUNCTION, Interface);
190
191         return new types::String(Interface.data());
192     }
193
194     static bool set(BlockAdapter& adaptor, types::InternalType* v, Controller& controller)
195     {
196         if (v->getType() != types::InternalType::ScilabString)
197         {
198             return false;
199         }
200
201         types::String* current = v->getAs<types::String>();
202         if (!current->isScalar())
203         {
204             return false;
205         }
206
207         wchar_t* w_name = current->get(0);
208         char* name = wide_string_to_UTF8(w_name);
209         std::string stName(name);
210         FREE(name);
211
212         ScicosID adaptee = adaptor.getAdaptee()->id();
213         controller.setObjectProperty(adaptee, BLOCK, INTERFACE_FUNCTION, stName);
214         return true;
215     }
216 };
217
218 struct doc
219 {
220     static types::InternalType* get(const BlockAdapter& adaptor, const Controller& /*controller*/)
221     {
222         return adaptor.getDocContent();
223     }
224
225     static bool set(BlockAdapter& adaptor, types::InternalType* v, Controller& /*controller*/)
226     {
227         adaptor.setDocContent(v->clone());
228         return true;
229     }
230 };
231
232 } /* namespace */
233
234 template<> property<BlockAdapter>::props_t property<BlockAdapter>::fields = property<BlockAdapter>::props_t();
235
236 BlockAdapter::BlockAdapter(const Controller& c, org_scilab_modules_scicos::model::Block* adaptee) :
237     BaseAdapter<BlockAdapter, org_scilab_modules_scicos::model::Block>(c, adaptee),
238     doc_content(nullptr),
239     from_vec(),
240     to_vec(),
241     list_objects(nullptr),
242     contrib_content(nullptr)
243 {
244     if (property<BlockAdapter>::properties_have_not_been_set())
245     {
246         property<BlockAdapter>::fields.reserve(4);
247         property<BlockAdapter>::add_property(L"graphics", &graphics::get, &graphics::set);
248         property<BlockAdapter>::add_property(L"model", &model::get, &model::set);
249         property<BlockAdapter>::add_property(L"gui", &gui::get, &gui::set);
250         property<BlockAdapter>::add_property(L"doc", &doc::get, &doc::set);
251     }
252
253     setListObjects(new types::List());
254     setContribContent(new types::List());
255     setDocContent(new types::List());
256
257     // model::get will set the adapter's content (listObjects, from_vec & to_vec) if needed
258     Controller controller;
259     model::get(*this, controller);
260
261 }
262
263 BlockAdapter::BlockAdapter(const BlockAdapter& adapter) :
264     BaseAdapter<BlockAdapter, org_scilab_modules_scicos::model::Block>(adapter, false),
265     doc_content(nullptr),
266     from_vec(),
267     to_vec(),
268     list_objects(nullptr),
269     contrib_content(nullptr)
270 {
271     Controller controller;
272
273     if (adapter.getListObjects()->getSize() > 0)
274     {
275         types::InternalType* model = model::get(adapter, controller);
276         model::set(*this, model, controller);
277         model->killMe();
278     }
279     else
280     {
281         setListObjects(new types::List());
282         setContribContent(new types::List());
283     }
284
285     setDocContent(adapter.getDocContent());
286 }
287
288 BlockAdapter::~BlockAdapter()
289 {
290     // CHILDREN will be unreferenced on Controller::deleteObject
291
292     if (list_objects != nullptr)
293     {
294         list_objects->DecreaseRef();
295         list_objects->killMe();
296     }
297
298     if (contrib_content != nullptr)
299     {
300         contrib_content->DecreaseRef();
301         contrib_content->killMe();
302     }
303
304     doc_content->DecreaseRef();
305     doc_content->killMe();
306 }
307
308 std::wstring BlockAdapter::getTypeStr()
309 {
310     return getSharedTypeStr();
311 }
312
313 std::wstring BlockAdapter::getShortTypeStr()
314 {
315     return getSharedTypeStr();
316 }
317
318 types::InternalType* BlockAdapter::getDocContent() const
319 {
320     return doc_content;
321 }
322
323 void BlockAdapter::setDocContent(types::InternalType* v)
324 {
325     types::InternalType* temp = doc_content;
326
327     v->IncreaseRef();
328     doc_content = v;
329
330     if (temp != nullptr)
331     {
332         temp->DecreaseRef();
333         temp->killMe();
334     }
335 }
336
337 std::vector<link_t> BlockAdapter::getFrom() const
338 {
339     return from_vec;
340 }
341
342 void BlockAdapter::setFrom(const std::vector<link_t>& from)
343 {
344     from_vec = from;
345 }
346
347 std::vector<link_t> BlockAdapter::getTo() const
348 {
349     return to_vec;
350 }
351
352 void BlockAdapter::setTo(const std::vector<link_t>& to)
353 {
354     to_vec = to;
355 }
356
357 types::List* BlockAdapter::getListObjects() const
358 {
359     return list_objects;
360 }
361
362 void BlockAdapter::setListObjects(types::List* v)
363 {
364     types::InternalType* temp = list_objects;
365
366     // Do not check if v is nullptr on purpose ; it *should* not
367     v->IncreaseRef();
368     list_objects = v;
369
370     if (temp != nullptr)
371     {
372         temp->DecreaseRef();
373         temp->killMe();
374     }
375 }
376
377 types::InternalType* BlockAdapter::getContribContent() const
378 {
379     return contrib_content;
380 }
381
382 void BlockAdapter::setContribContent(types::InternalType* v)
383 {
384     types::InternalType* temp = contrib_content;
385
386     // do not check if v is nullptr on purpose ; it *should* not
387     v->IncreaseRef();
388     contrib_content = v;
389
390     if (temp != nullptr)
391     {
392         temp->DecreaseRef();
393         temp->killMe();
394     }
395 }
396
397 } /* namespace view_scilab */
398 } /* namespace org_scilab_modules_scicos */