88dfcb0f9fb51dad86ba9254e1b1a0816520a62f
[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     __pathList_iterator it = m_pathList.begin();
498     for (; it != m_pathList.end(); it++)
499     {
500         PathItem * item = it->second;
501         if (item->tag == _pstTag)
502         {
503             if (std::find(_ignoredList.begin(), _ignoredList.end(), item->uid) == _ignoredList.end())
504             {
505                 return item;
506             }
507         }
508     }
509     return NULL;
510 }
511
512 PathItem* ScilabView::getFigureItem(std::string _pstTag)
513 {
514
515     __pathFigList_iterator it = m_pathFigList.find(_pstTag);
516     if (it != m_pathFigList.end())
517     {
518         return getItem(it->second);
519     }
520
521     return NULL;
522 }
523
524 int ScilabView::search_path(char* _pstPath)
525 {
526     //copy string to protect it against strtok
527     char* pstPath = strdup(_pstPath);
528     std::list<int> ignoredList;
529     PathItem* path = NULL;
530     char* pstSubPath = strtok(pstPath, "/");
531     bool bDeep = false;
532     while (pstSubPath != NULL)
533     {
534         if (pstSubPath[0] == 0)
535         {
536             //"" ?
537             break;
538         }
539
540         if (pstSubPath[0] != '*')
541         {
542             //search in direct children
543             if (path == NULL)
544             {
545                 path = ScilabView::getFigureItem(pstSubPath);
546                 if (path == NULL)
547                 {
548                     path = ScilabView::getItem(pstSubPath, ignoredList);
549                     if (path == NULL)
550                     {
551                         break;
552                     }
553                 }
554
555                 //if figure is in ignore list, reeturn not found
556                 if (std::find(ignoredList.begin(), ignoredList.end(), path->uid) != ignoredList.end())
557                 {
558                     return 0;
559                 }
560             }
561             else
562             {
563                 PathItem* newPath = search_children(path, pstSubPath, bDeep, ignoredList);
564                 if (newPath == NULL)
565                 {
566                     //flag handle to ignore and restart parsing
567                     ignoredList.push_back(path->uid);
568                     pstPath = strdup(_pstPath);
569                     pstSubPath = strtok(pstPath, "/");
570                     path = NULL;
571                     continue;
572                 }
573                 else
574                 {
575                     path = newPath;
576                 }
577
578                 bDeep = false;
579             }
580         }
581         else
582         {
583             //search in all path children
584             bDeep = true;
585         }
586
587         pstSubPath = strtok(NULL, "/");
588     }
589
590     if (path == NULL)
591     {
592         return 0;
593     }
594
595     return path->uid;
596 }
597
598 PathItem* ScilabView::search_children(PathItem* _path, std::string _subPath, bool _bDeep, std::list<int>& _ignoredList)
599 {
600     PathItem::__child_iterator it = _path->children.begin();
601     for (; it != _path->children.end() ; it++)
602     {
603         PathItem* child = ScilabView::getItem(*it);
604         if (child->tag == _subPath)
605         {
606             bool ignored = false;
607             //check if this handle is not in ignoredList
608             if (std::find(_ignoredList.begin(), _ignoredList.end(), child->uid) == _ignoredList.end())
609             {
610                 return child;
611             }
612         }
613         else if (_bDeep)
614         {
615             PathItem *item = search_children(child, _subPath, _bDeep, _ignoredList);
616             if (item)
617             {
618                 return item;
619             }
620         }
621     }
622
623     return NULL;
624 }
625
626 std::string ScilabView::get_path(int uid)
627 {
628     PathItem* item = getItem(uid);
629     if (item->tag == "")
630     {
631         //impossible to create a useful path from object without tag
632         return "";
633     }
634
635     std::string path = item->tag;
636
637     while (item->parent != 0)
638     {
639         item = getItem(item->parent);
640         if (item->tag == "")
641         {
642             if (path[0] == '*')
643             {
644                 //we have already */ just continue
645                 continue;
646             }
647             else
648             {
649                 //add */ instead of /
650                 path = "*/" + path;
651             }
652         }
653         else
654         {
655             path = item->tag + "/" + path;
656         }
657     }
658
659     if (path[0] == '*')
660     {
661         //path must start by mane
662         return "";
663     }
664
665     return path;
666 }
667
668 /*
669 ** Allocate static class variable.
670 */
671 ScilabView::__figureList ScilabView::m_figureList = *new __figureList();
672 ScilabView::__handleList ScilabView::m_handleList = *new __handleList();
673 ScilabView::__uidList ScilabView::m_uidList = *new __uidList();
674 long ScilabView::m_topHandleValue = 0;
675 int ScilabView::m_currentFigure;
676 int ScilabView::m_currentObject;
677 int ScilabView::m_currentSubWin;
678 int ScilabView::m_figureModel;
679 int ScilabView::m_axesModel;
680 ScilabView::__pathList ScilabView::m_pathList = *new __pathList();
681 ScilabView::__pathFigList ScilabView::m_pathFigList = *new __pathFigList();