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