keep user_data in C
[scilab.git] / scilab / modules / graphic_objects / src / cpp / ScilabView.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2011-2011 - DIGITEO - Bruno JOFRET
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 <algorithm>
14 #include <iostream>
15 #include <map>
16 #include <list>
17 #include <cstring>
18 #include <limits.h>
19
20 #include "ScilabView.hxx"
21 #include "CallGraphicController.hxx"
22
23 extern "C"
24 {
25 #include "CurrentObject.h"
26 #include "createGraphicObject.h"
27 #include "setGraphicObjectProperty.h"
28 #include "getGraphicObjectProperty.h"
29 #include "graphicObjectProperties.h"
30 #include "getScilabJavaVM.h"
31 #include "deleteGraphicObject.h"
32 #include "MALLOC.h"
33 }
34
35 /**
36  * C Wrapping functions
37  * \{
38  */
39 void ScilabNativeView__createObject(int iUID)
40 {
41     ScilabView::createObject(iUID);
42 }
43
44 void ScilabNativeView__deleteObject(int iUID)
45 {
46     ScilabView::deleteObject(iUID);
47 }
48
49 void ScilabNativeView__updateObject(int iUID, int iProperty)
50 {
51     ScilabView::updateObject(iUID, iProperty);
52 }
53
54 void ScilabNativeView__setCurrentFigure(int iUID)
55 {
56     ScilabView::setCurrentFigure(iUID);
57 }
58
59 void ScilabNativeView__setCurrentSubWin(int iUID)
60 {
61     ScilabView::setCurrentSubWin(iUID);
62 }
63
64 void ScilabNativeView__setCurrentObject(int iUID)
65 {
66     ScilabView::setCurrentObject(iUID);
67 }
68
69 int ScilabNativeView__getValidDefaultFigureId()
70 {
71     return ScilabView::getValidDefaultFigureId();
72 }
73
74 /**
75  * \}
76  */
77
78 int ScilabView::getValidDefaultFigureId()
79 {
80     if (m_figureList.empty())
81     {
82         return 0;
83     }
84     else
85     {
86         int max = INT_MIN;
87         for (__figureList_iterator it = m_figureList.begin(); it != m_figureList.end(); ++it)
88         {
89             if (it->second > max)
90             {
91                 max = it->second;
92             }
93         }
94
95         return max + 1;
96     }
97 }
98
99 bool ScilabView::isEmptyFigureList()
100 {
101     return m_figureList.empty();
102 }
103
104 int ScilabView::getFigureFromIndex(int figNum)
105 {
106     __figureList_iterator it;
107
108     for (it = m_figureList.begin(); it != m_figureList.end(); ++it)
109     {
110         if (it->second == figNum)
111         {
112             return it->first;
113         }
114     }
115     return 0;
116 }
117
118 bool ScilabView::existsFigureId(int id)
119 {
120     __figureList_iterator it;
121
122     for (it = m_figureList.begin(); it != m_figureList.end(); ++it)
123     {
124         if (it->second == id)
125         {
126             return true;
127         }
128     }
129     return false;
130 }
131
132 void ScilabView::getFiguresId(int ids[])
133 {
134     //__figureList_iterator it;
135     //int i = (int)(m_figureList.size() - 1);
136
137     //for (it = m_figureList.begin(); it != m_figureList.end(); ++it, --i)
138     //{
139     //    //std::cerr << "[ScilabView] DEBUG " << it->first << " <-> " << it->second << std::endl;
140     //    ids[i] = it->second;
141     //}
142
143     __figureList_reverse_iterator it;
144     int i = (int)(m_figureList.size() - 1);
145
146     for (it = m_figureList.rbegin(); it != m_figureList.rend(); ++it, --i)
147     {
148         //std::cerr << "[ScilabView] DEBUG " << it->first << " <-> " << it->second << std::endl;
149         ids[i] = it->second;
150     }
151 }
152
153 int ScilabView::getNbFigure(void)
154 {
155     return (int)m_figureList.size();
156 }
157
158 void ScilabView::createObject(int iUID)
159 {
160     //std::cerr << "[ScilabView] ++ createObject UID=" << iUID << std::endl;
161     int iType = -1;
162     int *piType = &iType;
163
164     getGraphicObjectProperty(iUID, __GO_TYPE__, jni_int, (void **)&piType);
165     if (iType != -1 && iType == __GO_FIGURE__)
166     {
167         m_figureList[iUID] = -1;
168         setCurrentFigure(iUID);
169     }
170
171     // Register object handle.
172     getObjectHandle(iUID);
173
174     PathItem* item = new PathItem();
175     item->uid = iUID;
176
177     m_pathList[iUID] = item;
178
179     m_userdata[iUID]; //create an empty vector<int>
180
181     //get existing information from current object
182     updateObject(iUID, __GO_PARENT__);
183     updateObject(iUID, __GO_CHILDREN__);
184     updateObject(iUID, __GO_TAG__);
185 }
186
187 void ScilabView::deleteObject(int iUID)
188 {
189     //std::cerr << "[ScilabView] -- deleteObject UID=" << iUID << std::endl;
190     int iType = -1;
191     int *piType = &iType;
192     int iParentUID = 0;
193
194     /*
195     ** If deleting a figure, remove from figure list.
196     */
197     m_figureList.erase(iUID);
198
199     /*
200     ** If deleting current figure find another current one,
201     ** if there is no more figure : NULL
202     */
203     if (m_currentFigure == iUID) // Deleting current figure
204     {
205         int iAxesUID = 0;
206         int* piAxesUID = &iAxesUID;
207
208         if (getNbFigure() != 0)
209         {
210             m_currentFigure = m_figureList.begin()->first;
211             getGraphicObjectProperty(m_currentFigure, __GO_SELECTED_CHILD__, jni_int,  (void**)&piAxesUID);
212             setCurrentSubWin(iAxesUID);
213         }
214         else
215         {
216             setCurrentFigure(0);
217             setCurrentSubWin(0);
218         }
219     }
220
221     /*
222     ** If deleting current entity, set parent as new current.
223     */
224     if (m_currentObject == iUID) // Deleting current object
225     {
226         iParentUID = getParentObject(iUID);
227         setCurrentObject(iParentUID);
228     }
229
230     // Remove the corresponding handle.
231     __handleList_iterator it = m_handleList.find(iUID);
232     if (it != m_handleList.end())
233     {
234         m_uidList.erase(it->second);
235         m_handleList.erase(it);
236     }
237
238     deleteDataObject(iUID);
239
240     m_pathList.erase(iUID);
241     m_userdata.erase(iUID);
242 }
243
244 void ScilabView::updateObject(int iUID, int iProperty)
245 {
246     //std::cerr << "[ScilabView] == updateObject UID=" << iUID << " PROPERTY=" << pstProperty << std::endl;
247
248     /*
249     ** Take care of update if the value update is ID and object type is a Figure I manage.
250     */
251     switch (iProperty)
252     {
253         case __GO_ID__ :
254         {
255             if (m_figureList.find(iUID) != m_figureList.end())
256             {
257                 int iNewId = 0;
258                 int *piNewId = &iNewId;
259
260                 getGraphicObjectProperty(iUID, __GO_ID__, jni_int, (void **)&piNewId);
261
262                 m_figureList[iUID] = iNewId;
263                 //std::cerr << "### [ScilabView] updateMap UID=" << iUID << " id=" << iNewId << std::endl;
264             }
265             break;
266         }
267         case __GO_CHILDREN__ :
268         {
269             int childrenCount = 0;
270             int* pChildrenCount = &childrenCount;
271             getGraphicObjectProperty(iUID, __GO_CHILDREN_COUNT__, jni_int, (void**)&pChildrenCount);
272
273             __pathList_iterator it = m_pathList.find(iUID);
274             if (it != m_pathList.end())
275             {
276                 //update existing item
277
278                 PathItem* item = (*it).second;
279                 //reset children
280                 item->children.clear();
281                 if (childrenCount != 0)
282                 {
283                     int* children = NULL;
284                     getGraphicObjectProperty(iUID, __GO_CHILDREN__, jni_int_vector, (void**)&children);
285                     item->children.assign(children, children + childrenCount);
286                 }
287             }
288             break;
289         }
290         case __GO_PARENT__ :
291         {
292             int iParent = 0;
293             int* piParent = &iParent;
294             getGraphicObjectProperty(iUID, __GO_PARENT__, jni_int, (void**)&piParent);
295
296             __pathList_iterator it = m_pathList.find(iUID);
297
298             if (it != m_pathList.end())
299             {
300                 //update existing item
301
302                 PathItem* item = (*it).second;
303                 item->parent = iParent;
304             }
305             break;
306         }
307         case __GO_TAG__ :
308         {
309             int iType = 0;
310             int* piType = &iType;
311             getGraphicObjectProperty(iUID, __GO_TYPE__, jni_int, (void**)&piType);
312
313             char* tag = NULL;
314             getGraphicObjectProperty(iUID, __GO_TAG__, jni_string, (void**)&tag);
315
316             if (tag[0] != 0 && iType == __GO_FIGURE__)
317             {
318                 //not empty string
319
320                 //add figure in list of path starter
321                 m_pathFigList[tag] = iUID;
322             }
323
324             __pathList_iterator it = m_pathList.find(iUID);
325
326             if (it != m_pathList.end())
327             {
328                 //update existing item
329
330                 PathItem* item = (*it).second;
331                 item->tag = tag;
332                 free(tag);
333             }
334             break;
335         }
336         default:
337             break;
338     }
339 }
340
341 /*
342 ** Register ScilabView to Controller.
343 ** Must be done after Graphics models are created.
344 */
345 void ScilabView::registerToController(void)
346 {
347     org_scilab_modules_graphic_objects::CallGraphicController::registerScilabView(getScilabJavaVM());
348     m_figureList.get_allocator().allocate(4096);
349     m_handleList.get_allocator().allocate(4096);
350     m_uidList.get_allocator().allocate(4096);
351 }
352
353 /*
354 ** Reove ScilabView from Controller.
355 */
356 void ScilabView::unregisterToController(void)
357 {
358     org_scilab_modules_graphic_objects::CallGraphicController::unregisterScilabView(getScilabJavaVM());
359 }
360
361 /*
362 ** Set Current Figure UID
363 */
364 void ScilabView::setCurrentFigure(int UID)
365 {
366     m_currentFigure = UID;
367 }
368
369 /*
370 ** Get Current Figure UID
371 */
372 int ScilabView::getCurrentFigure()
373 {
374     //std::cerr << "[ScilaView] currentFigure = " << (m_currentFigure == 0 ? "NULL !!" : m_currentFigure) << std::endl;
375     return m_currentFigure;
376 }
377
378 /*
379 ** Set Current Object UID
380 */
381 void ScilabView::setCurrentObject(int UID)
382 {
383     m_currentObject = UID;
384 }
385
386 /*
387 ** Get Current Figure UID
388 */
389 int ScilabView::getCurrentObject()
390 {
391     //std::cerr << "[ScilaView] currentObject = " << m_currentObject << std::endl;
392     return m_currentObject;
393 }
394
395 /*
396 ** Set Current SubWin UID
397 */
398 void ScilabView::setCurrentSubWin(int UID)
399 {
400     m_currentSubWin = UID;
401 }
402
403 /*
404 ** Get Current Figure UID
405 */
406 int ScilabView::getCurrentSubWin()
407 {
408     //std::cerr << "[ScilaView] currentSubWin = " << m_currentSubWin << std::endl;
409     return m_currentSubWin;
410 }
411
412 /*
413 ** Scilab only can store long as handle
414 */
415 long ScilabView::getObjectHandle(int UID)
416 {
417     /*
418      * if (UID != NULL)
419      * {
420      * std::cerr << "UID = " << UID << std::endl;
421      * }
422      * else
423      * {
424      * std::cerr << "UID is null :-S" << std::endl;
425      * }
426      * __handleList_iterator it2;
427      * std::cerr << "[DEBUG] +++ handleMap +++" << std::endl;
428      * for (it2 = m_handleList.begin() ; it2 != m_handleList.end() ; ++it2)
429      * {
430      * std::cerr << "UID " << it2->first << " <-> handle " << it2->second << std::endl;
431      * }
432      * std::cerr << "[DEBUG] +++ handleMap +++" << std::endl;
433      */
434     __handleList_iterator it = m_handleList.find(UID);
435
436     if (it != m_handleList.end())
437     {
438         return it->second;
439     }
440
441     // increase maximum value
442     // register new handle and return it.
443     m_topHandleValue++;
444     m_handleList[UID] = m_topHandleValue;
445     m_uidList[m_topHandleValue] = UID;
446
447     return m_topHandleValue;
448 }
449
450 int ScilabView::getObjectFromHandle(long handle)
451 {
452     __uidList_iterator it = m_uidList.find(handle);
453     if (it == m_uidList.end())
454     {
455         return 0;
456     }
457
458     return it->second;
459 }
460
461 int ScilabView::getFigureModel(void)
462 {
463     //std::cerr << "[ScilabView] getFigureModel = " << (m_figureModel == 0 ? "!! NULL !!" : m_figureModel) << std::endl;
464     return m_figureModel;
465 }
466
467 void ScilabView::setFigureModel(int UID)
468 {
469     m_figureModel = UID;
470 }
471
472 int ScilabView::getAxesModel(void)
473 {
474     //std::cerr << "[ScilabView] getAxesModel = " << (m_axesModel == 0 ? "!! NULL !!" : m_axesModel) << std::endl;
475     return m_axesModel;
476 }
477
478 void ScilabView::setAxesModel(int UID)
479 {
480     m_axesModel = UID;
481 }
482
483 PathItem* ScilabView::getItem(int uid)
484 {
485     __pathList_iterator it = m_pathList.find(uid);
486     if (it != m_pathList.end())
487     {
488         return it->second;
489     }
490
491     return NULL;
492 }
493
494 PathItem* ScilabView::getItem(std::string _pstTag)
495 {
496     std::list<int> ignored;
497     return getItem(_pstTag, ignored);
498 }
499
500 PathItem* ScilabView::getItem(std::string _pstTag, std::list<int>& _ignoredList)
501 {
502     __pathList_iterator it = m_pathList.begin();
503     for (; it != m_pathList.end(); it++)
504     {
505         PathItem * item = it->second;
506         if (item->tag == _pstTag)
507         {
508             if (std::find(_ignoredList.begin(), _ignoredList.end(), item->uid) == _ignoredList.end())
509             {
510                 return item;
511             }
512         }
513     }
514     return NULL;
515 }
516
517 PathItem* ScilabView::getFigureItem(std::string _pstTag)
518 {
519
520     __pathFigList_iterator it = m_pathFigList.find(_pstTag);
521     if (it != m_pathFigList.end())
522     {
523         return getItem(it->second);
524     }
525
526     return NULL;
527 }
528
529 int ScilabView::search_path(char* _pstPath)
530 {
531     //copy string to protect it against strtok
532     char* pstPath = strdup(_pstPath);
533     std::list<int> ignoredList;
534     PathItem* path = NULL;
535     char* pstSubPath = strtok(pstPath, "/");
536     bool bDeep = false;
537     while (pstSubPath != NULL)
538     {
539         if (pstSubPath[0] == 0)
540         {
541             //"" ?
542             break;
543         }
544
545         if (pstSubPath[0] != '*')
546         {
547             //search in direct children
548             if (path == NULL)
549             {
550                 path = ScilabView::getFigureItem(pstSubPath);
551                 if (path == NULL)
552                 {
553                     path = ScilabView::getItem(pstSubPath, ignoredList);
554                     if (path == NULL)
555                     {
556                         break;
557                     }
558                 }
559
560                 //if figure is in ignore list, reeturn not found
561                 if (std::find(ignoredList.begin(), ignoredList.end(), path->uid) != ignoredList.end())
562                 {
563                     return 0;
564                 }
565             }
566             else
567             {
568                 PathItem* newPath = search_children(path, pstSubPath, bDeep, ignoredList);
569                 if (newPath == NULL)
570                 {
571                     //flag handle to ignore and restart parsing
572                     ignoredList.push_back(path->uid);
573                     pstPath = strdup(_pstPath);
574                     pstSubPath = strtok(pstPath, "/");
575                     path = NULL;
576                     continue;
577                 }
578                 else
579                 {
580                     path = newPath;
581                 }
582
583                 bDeep = false;
584             }
585         }
586         else
587         {
588             //search in all path children
589             bDeep = true;
590         }
591
592         pstSubPath = strtok(NULL, "/");
593     }
594
595     if (path == NULL)
596     {
597         return 0;
598     }
599
600     return path->uid;
601 }
602
603 PathItem* ScilabView::search_children(PathItem* _path, std::string _subPath, bool _bDeep, std::list<int>& _ignoredList)
604 {
605     PathItem::__child_iterator it = _path->children.begin();
606     for (; it != _path->children.end() ; it++)
607     {
608         PathItem* child = ScilabView::getItem(*it);
609         if (child->tag == _subPath)
610         {
611             bool ignored = false;
612             //check if this handle is not in ignoredList
613             if (std::find(_ignoredList.begin(), _ignoredList.end(), child->uid) == _ignoredList.end())
614             {
615                 return child;
616             }
617         }
618         else if (_bDeep)
619         {
620             PathItem *item = search_children(child, _subPath, _bDeep, _ignoredList);
621             if (item)
622             {
623                 return item;
624             }
625         }
626     }
627
628     return NULL;
629 }
630
631 std::string ScilabView::get_path(int uid)
632 {
633     PathItem* item = getItem(uid);
634     if (item->tag == "")
635     {
636         //impossible to create a useful path from object without tag
637         return "";
638     }
639
640     std::string path = item->tag;
641
642     while (item->parent != 0)
643     {
644         item = getItem(item->parent);
645         if (item->tag == "")
646         {
647             if (path[0] == '*')
648             {
649                 //we have already */ just continue
650                 continue;
651             }
652             else
653             {
654                 //add */ instead of /
655                 path = "*/" + path;
656             }
657         }
658         else
659         {
660             path = item->tag + "/" + path;
661         }
662     }
663
664     if (path[0] == '*')
665     {
666         //path must start by mane
667         return "";
668     }
669
670     return path;
671 }
672
673 void ScilabView::setUserdata(int _id, int* _data, int _datasize)
674 {
675     m_userdata[_id] = std::vector<int>(_data, _data + _datasize);
676 }
677
678 int ScilabView::getUserdataSize(int _id)
679 {
680     return (int)m_userdata[_id].size();
681 }
682
683 int* ScilabView::getUserdata(int _id)
684 {
685     std::vector<int> &vect = m_userdata[_id];
686     int size = (int)vect.size();
687
688     if (size != 0)
689     {
690         return &(vect[0]);
691     }
692
693     //empty userdata must be == NULL
694     return NULL;
695 }
696
697 /*
698 ** Allocate static class variable.
699 */
700 ScilabView::__figureList ScilabView::m_figureList = *new __figureList();
701 ScilabView::__handleList ScilabView::m_handleList = *new __handleList();
702 ScilabView::__uidList ScilabView::m_uidList = *new __uidList();
703 long ScilabView::m_topHandleValue = 0;
704 int ScilabView::m_currentFigure;
705 int ScilabView::m_currentObject;
706 int ScilabView::m_currentSubWin;
707 int ScilabView::m_figureModel;
708 int ScilabView::m_axesModel;
709 ScilabView::__pathList ScilabView::m_pathList = *new __pathList();
710 ScilabView::__pathFigList ScilabView::m_pathFigList = *new __pathFigList();
711 ScilabView::__userdata ScilabView::m_userdata = *new __userdata();