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