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