1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2017 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "nel/gui/group_tree.h"
24 #include "nel/gui/interface_element.h"
25 #include "nel/gui/view_bitmap.h"
26 #include "nel/gui/view_text.h"
27 #include "nel/gui/group_container_base.h"
28 #include "nel/gui/action_handler.h"
29 #include "nel/gui/lua_ihm.h"
30 #include "nel/misc/i_xml.h"
31 #include "nel/misc/i18n.h"
32 #include "nel/misc/xml_auto_ptr.h"
33 #include "nel/gui/widget_manager.h"
34 #include "nel/gui/view_renderer.h"
35 #include "nel/gui/view_pointer_base.h"
38 using namespace NLMISC
;
47 // ----------------------------------------------------------------------------
49 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
53 CGroupTree::SNode::SNode()
62 NodeAddedCallback
= NULL
;
65 LastVisibleSon
= NULL
;
67 //nlinfo("SNode(): %8x, c%d", this, SNodeCount++);
70 // ----------------------------------------------------------------------------
71 void CGroupTree::SNode::updateLastVisibleSon()
73 LastVisibleSon
= NULL
;
74 if (!Show
|| !Opened
) return;
75 for (sint sonIndex
= (sint
)Children
.size() - 1; sonIndex
>= 0; -- sonIndex
)
77 if (Children
[sonIndex
]->Show
)
79 LastVisibleSon
= Children
[sonIndex
];
83 for(uint k
= 0; k
< Children
.size(); ++k
)
85 Children
[k
]->updateLastVisibleSon();
89 // ----------------------------------------------------------------------------
90 CGroupTree::SNode::~SNode()
93 // IMPORTANT : must delete in reverse order because "makeOrphan" is called when deleting sons, thus changing vector size...
94 for (sint i
= (sint
)Children
.size() - 1; i
>= 0; --i
)
98 //nlinfo("~SNode(): %8x, c%d", this, --SNodeCount);
101 void CGroupTree::SNode::setParentTree(CGroupTree
*parent
)
104 for (uint k
= 0; k
< Children
.size(); ++k
)
106 Children
[k
]->setParentTree(parent
);
110 void CGroupTree::SNode::setFather(SNode
*father
)
113 setParentTree(father
? father
->ParentTree
: NULL
);
117 CGroupTree::SNode
*CGroupTree::SNode::getNodeFromId(const std::string
&id
)
119 if (Id
== id
) return this;
121 for (uint k
= 0; k
< Children
.size(); ++k
)
123 if (Children
[k
]->Id
== id
)
128 for (uint k
= 0; k
< Children
.size(); ++k
)
130 SNode
*found
= Children
[k
]->getNodeFromId(id
);
131 if (found
) return found
;
137 void CGroupTree::SNode::makeOrphan()
141 ParentTree
->forceRebuild();
145 if (Template
!= NULL
)
147 if (Template
->getParent())
149 // don't delete because may want to keep it. NB: deleted by smartptr at dtor
150 Template
->getParent()->delGroup(Template
, true);
156 Father
->detachChild(this);
161 // ----------------------------------------------------------------------------
164 bool operator()(const CGroupTree::SNode
*lhs
, const CGroupTree::SNode
*rhs
) const
166 return lhs
->Text
< rhs
->Text
;
170 // ----------------------------------------------------------------------------
171 void CGroupTree::SNode::sort()
173 std::sort(Children
.begin(), Children
.end(), CNodeSorter());
174 for(uint k
= 0; k
< Children
.size(); ++k
)
181 // ----------------------------------------------------------------------------
182 struct CNodeSorterByBitmap
184 bool operator()(const CGroupTree::SNode
*lhs
, const CGroupTree::SNode
*rhs
) const
186 if (lhs
->Bitmap
!= rhs
->Bitmap
) return lhs
->Bitmap
< rhs
->Bitmap
;
187 return lhs
->Text
< rhs
->Text
;
191 // ----------------------------------------------------------------------------
192 void CGroupTree::SNode::sortByBitmap()
194 std::sort(Children
.begin(), Children
.end(), CNodeSorterByBitmap());
195 for(uint k
= 0; k
< Children
.size(); ++k
)
197 Children
[k
]->sortByBitmap();
201 // ----------------------------------------------------------------------------
202 void CGroupTree::SNode::addChild (SNode
*pNode
)
206 Children
.push_back(pNode
);
207 pNode
->setFather(this);
210 // ----------------------------------------------------------------------------
211 void CGroupTree::SNode::addChildSorted(SNode
*pNode
)
215 std::vector
<SNode
*>::iterator it
= std::lower_bound(Children
.begin(), Children
.end(), pNode
, CNodeSorter());
216 Children
.insert(it
, pNode
);
217 pNode
->setFather(this);
220 // ----------------------------------------------------------------------------
221 void CGroupTree::SNode::addChildSortedByBitmap(SNode
*pNode
)
225 std::vector
<SNode
*>::iterator it
= std::lower_bound(Children
.begin(), Children
.end(), pNode
, CNodeSorterByBitmap());
226 Children
.insert(it
, pNode
);
227 pNode
->setFather(this);
230 // ----------------------------------------------------------------------------
231 bool CGroupTree::SNode::isChild(SNode
*pNode
) const
233 return std::find(Children
.begin(), Children
.end(), pNode
) != Children
.end();
236 // ----------------------------------------------------------------------------
237 void CGroupTree::SNode::detachChild(SNode
*pNode
)
240 nlassert(isChild(pNode
));
241 Children
.erase(std::remove(Children
.begin(), Children
.end(), pNode
), Children
.end());
242 pNode
->setFather(NULL
);
245 // ----------------------------------------------------------------------------
246 void CGroupTree::SNode::deleteChild(SNode
*pNode
)
251 // ----------------------------------------------------------------------------
252 void CGroupTree::SNode::addChildFront (SNode
*pNode
)
256 Children
.insert(Children
.begin(), pNode
);
257 pNode
->setFather(this);
260 // ----------------------------------------------------------------------------
261 void CGroupTree::SNode::addChildAtIndex(SNode
*pNode
, sint index
)
264 if (index
< 0 || index
> (sint
) Children
.size())
266 nlwarning("<CGroupTree::SNode::addChildAtIndex> bad index %d (%d elements in the vector)", index
, Children
.size());
272 pNode
->Father
->detachChild(pNode
);
274 Children
.insert(Children
.begin() + index
, pNode
);
275 pNode
->setFather(this);
278 // ----------------------------------------------------------------------------
279 void CGroupTree::SNode::openAll()
282 for (uint i
= 0; i
< Children
.size(); ++i
)
283 Children
[i
]->openAll();
286 // ----------------------------------------------------------------------------
287 void CGroupTree::SNode::closeAll()
290 for (uint i
= 0; i
< Children
.size(); ++i
)
291 Children
[i
]->closeAll();
294 // ----------------------------------------------------------------------------
295 bool CGroupTree::SNode::parse (xmlNodePtr cur
, CGroupTree
* parentGroup
)
297 if (stricmp((char*)cur
->name
, "node") == 0)
299 CXMLAutoPtr
id((const char*) xmlGetProp (cur
, (xmlChar
*)"id"));
301 Id
= (const char*)id
;
303 Id
= toString(parentGroup
->getIdNumber());
305 CXMLAutoPtr
name((const char*) xmlGetProp (cur
, (xmlChar
*)"name"));
309 const char *ptrName
= (const char*)name
;
310 if (NLMISC::startsWith(ptrName
, "ui"))
311 Text
= CI18N::get(ptrName
);
316 CXMLAutoPtr
color((const char*) xmlGetProp (cur
, (xmlChar
*)"color"));
319 Color
= convertColor(color
);
322 CXMLAutoPtr
open((const char*) xmlGetProp (cur
, (xmlChar
*)"opened"));
323 if (open
) Opened
= convertBool(open
);
325 CXMLAutoPtr
show((const char*) xmlGetProp (cur
, (xmlChar
*)"show"));
326 if (open
) Show
= convertBool(show
);
328 CXMLAutoPtr
ah((const char*) xmlGetProp (cur
, (xmlChar
*)"handler"));
329 if (ah
) AHName
= (const char*)ah
;
330 CXMLAutoPtr
cond((const char*) xmlGetProp (cur
, (xmlChar
*)"cond"));
331 if (cond
) AHCond
= (const char*)cond
;
332 CXMLAutoPtr
params((const char*) xmlGetProp (cur
, (xmlChar
*)"params"));
333 if (params
) AHParams
= (const char*)params
;
335 CXMLAutoPtr
ahRight((const char*) xmlGetProp (cur
, (xmlChar
*)"handler_right"));
336 if (ahRight
) AHNameRight
= (const char*)ahRight
;
337 CXMLAutoPtr
paramsRight((const char*) xmlGetProp (cur
, (xmlChar
*)"params_right"));
338 if (paramsRight
) AHParamsRight
= (const char*)paramsRight
;
340 CXMLAutoPtr
bitmap((const char*) xmlGetProp (cur
, (xmlChar
*)"bitmap"));
341 if (bitmap
) Bitmap
= (const char*)bitmap
;
343 FontSize
= parentGroup
->getFontSize();
344 CXMLAutoPtr
fs((const char*) xmlGetProp (cur
, (xmlChar
*)"fontsize"));
345 if (fs
) fromString((const char*)fs
, FontSize
);
347 YDecal
= parentGroup
->getYDecal();
348 CXMLAutoPtr
yDecalPtr((const char*) xmlGetProp (cur
, (xmlChar
*)"y_decal"));
349 if (yDecalPtr
) fromString((const char*)yDecalPtr
, YDecal
);
352 xmlNodePtr child
= cur
->children
;
354 while (child
!= NULL
)
356 SNode
*pNode
= new SNode
;
357 pNode
->parse (child
, parentGroup
);
366 // ----------------------------------------------------------------------------
368 // ----------------------------------------------------------------------------
370 NLMISC_REGISTER_OBJECT(CViewBase
, CGroupTree
, std::string
, "tree");
372 // ----------------------------------------------------------------------------
373 CGroupTree::CGroupTree(const TCtorParam
¶m
)
374 :CInterfaceGroup(param
)
383 _OverColor
= CRGBA(255, 255, 255, 128);
384 _OverColorBack
= CRGBA(64, 64, 64, 255);
385 _SelectedNode
= NULL
;
387 _SelectedColor
= CRGBA(255, 128, 128, 128);
390 _SelectAncestorOnClose
= false;
391 _NavigateOneBranch
= false;
393 _ArboOpenFirst
= "arbo_open_first.tga";
394 _ArboCloseJustOne
= "arbo_close_just_one.tga";
395 _ArboSonWithoutSon
= "arbo_son_without_son.tga";
396 _ArboSonLast
= "arbo_son_last.tga";
397 _ArboSon
= "arbo_son.tga";
398 _ArboLevel
= "arbo_level.tga";
400 _RectangleOutlineMode
= false;
405 _RectangleDeltaRL
= 0;
407 _AvoidSelectNodeByIdIR
= false;
410 // ----------------------------------------------------------------------------
411 CGroupTree::~CGroupTree()
414 if (_RootNode
!= NULL
) delete _RootNode
;
417 std::string
CGroupTree::getProperty( const std::string
&name
) const
419 if( name
== "col_over" )
421 return toString( _OverColor
);
424 if( name
== "col_select" )
426 return toString( _SelectedColor
);
429 if( name
== "col_over_back" )
431 return toString( _OverColorBack
);
434 if( name
== "fontsize" )
436 return toString( _FontSize
);
439 if( name
== "select_ancestor_on_close" )
441 return toString( _SelectAncestorOnClose
);
444 if( name
== "navigate_one_branch" )
446 return toString( _NavigateOneBranch
);
449 if( name
== "arbo_open_first" )
451 return _ArboOpenFirst
;
454 if( name
== "arbo_close_just_one" )
456 return _ArboCloseJustOne
;
459 if( name
== "arbo_son_without_son" )
461 return _ArboSonWithoutSon
;
464 if( name
== "arbo_son_last" )
469 if( name
== "arbo_son" )
474 if( name
== "arbo_x_extend" )
479 if( name
== "arbo_level" )
483 if( name
== "rectangle_outline" )
485 return toString( _RectangleOutlineMode
);
488 if( name
== "rectangle_x" )
490 return toString( _RectangleX
);
493 if( name
== "rectangle_y" )
495 return toString( _RectangleY
);
498 if( name
== "rectangle_w" )
500 return toString( _RectangleW
);
503 if( name
== "rectangle_h" )
505 return toString( _RectangleH
);
508 if( name
== "rectangle_drl" )
510 return toString( _RectangleDeltaRL
);
513 return CInterfaceGroup::getProperty( name
);
516 void CGroupTree::setProperty( const std::string
&name
, const std::string
&value
)
518 if( name
== "col_over" )
521 if( fromString( value
, c
) )
526 if( name
== "col_select" )
529 if( fromString( value
, c
) )
534 if( name
== "col_over_back" )
537 if( fromString( value
, c
) )
542 if( name
== "fontsize" )
545 if( fromString( value
, i
) )
550 if( name
== "select_ancestor_on_close" )
553 if( fromString( value
, b
) )
554 _SelectAncestorOnClose
= b
;
558 if( name
== "navigate_one_branch" )
561 if( fromString( value
, b
) )
562 _NavigateOneBranch
= b
;
566 if( name
== "arbo_open_first" )
568 _ArboOpenFirst
= value
;
573 if( name
== "arbo_close_just_one" )
575 _ArboCloseJustOne
= value
;
579 if( name
== "arbo_son_without_son" )
581 _ArboSonWithoutSon
= value
;
585 if( name
== "arbo_son_last" )
587 _ArboSonLast
= value
;
591 if( name
== "arbo_son" )
597 if( name
== "arbo_x_extend" )
599 _ArboXExtend
= value
;
604 if( name
== "arbo_level" )
609 if( name
== "rectangle_outline" )
612 if( fromString( value
, b
) )
613 _RectangleOutlineMode
= b
;
617 if( name
== "rectangle_x" )
620 if( fromString( value
, i
) )
625 if( name
== "rectangle_y" )
628 if( fromString( value
, i
) )
633 if( name
== "rectangle_w" )
636 if( fromString( value
, i
) )
641 if( name
== "rectangle_h" )
644 if( fromString( value
, i
) )
649 if( name
== "rectangle_drl" )
652 if( fromString( value
, i
) )
653 _RectangleDeltaRL
= i
;
657 CInterfaceGroup::setProperty( name
, value
);
660 xmlNodePtr
CGroupTree::serialize( xmlNodePtr parentNode
, const char *type
) const
662 xmlNodePtr node
= CInterfaceGroup::serialize( parentNode
, type
);
666 xmlSetProp( node
, BAD_CAST
"type", BAD_CAST
"tree" );
667 xmlSetProp( node
, BAD_CAST
"col_over", BAD_CAST
toString( _OverColor
).c_str() );
668 xmlSetProp( node
, BAD_CAST
"col_select", BAD_CAST
toString( _SelectedColor
).c_str() );
669 xmlSetProp( node
, BAD_CAST
"col_over_back", BAD_CAST
toString( _OverColorBack
).c_str() );
670 xmlSetProp( node
, BAD_CAST
"fontsize", BAD_CAST
toString( _FontSize
).c_str() );
671 xmlSetProp( node
, BAD_CAST
"select_ancestor_on_close", BAD_CAST
toString( _SelectAncestorOnClose
).c_str() );
672 xmlSetProp( node
, BAD_CAST
"navigate_one_branch", BAD_CAST
toString( _NavigateOneBranch
).c_str() );
673 xmlSetProp( node
, BAD_CAST
"arbo_open_first", BAD_CAST _ArboOpenFirst
.c_str() );
674 xmlSetProp( node
, BAD_CAST
"arbo_close_just_one", BAD_CAST _ArboCloseJustOne
.c_str() );
675 xmlSetProp( node
, BAD_CAST
"arbo_son_without_son", BAD_CAST _ArboSonWithoutSon
.c_str() );
676 xmlSetProp( node
, BAD_CAST
"arbo_son_last", BAD_CAST _ArboSonLast
.c_str() );
677 xmlSetProp( node
, BAD_CAST
"arbo_son", BAD_CAST _ArboSon
.c_str() );
678 xmlSetProp( node
, BAD_CAST
"arbo_x_extend", BAD_CAST _ArboXExtend
.c_str() );
679 xmlSetProp( node
, BAD_CAST
"arbo_level", BAD_CAST _ArboLevel
.c_str() );
680 xmlSetProp( node
, BAD_CAST
"rectangle_outline", BAD_CAST
toString( _RectangleOutlineMode
).c_str() );
681 xmlSetProp( node
, BAD_CAST
"rectangle_x", BAD_CAST
toString( _RectangleX
).c_str() );
682 xmlSetProp( node
, BAD_CAST
"rectangle_y", BAD_CAST
toString( _RectangleY
).c_str() );
683 xmlSetProp( node
, BAD_CAST
"rectangle_w", BAD_CAST
toString( _RectangleW
).c_str() );
684 xmlSetProp( node
, BAD_CAST
"rectangle_h", BAD_CAST
toString( _RectangleH
).c_str() );
685 xmlSetProp( node
, BAD_CAST
"rectangle_drl", BAD_CAST
toString( _RectangleDeltaRL
).c_str() );
690 // ----------------------------------------------------------------------------
691 bool CGroupTree::parse (xmlNodePtr cur
, CInterfaceGroup
* parentGroup
)
693 if (!CInterfaceGroup::parse(cur
, parentGroup
))
698 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"col_over");
699 if (ptr
) _OverColor
= convertColor(ptr
);
700 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"col_select");
701 if (ptr
) _SelectedColor
= convertColor(ptr
);
702 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"col_over_back");
703 if (ptr
) _OverColorBack
= convertColor(ptr
);
705 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"fontsize");
706 if (ptr
) fromString((const char*)ptr
, _FontSize
);
707 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"select_ancestor_on_close");
708 if (ptr
) _SelectAncestorOnClose
= convertBool(ptr
);
709 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"navigate_one_branch");
710 if (ptr
) _NavigateOneBranch
= convertBool(ptr
);
712 // read optional arbo bmps
713 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"arbo_open_first");
714 if (ptr
) _ArboOpenFirst
= (const char*)ptr
;
715 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"arbo_close_just_one");
716 if (ptr
) _ArboCloseJustOne
= (const char*)ptr
;
717 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"arbo_son_without_son");
718 if (ptr
) _ArboSonWithoutSon
= (const char*)ptr
;
719 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"arbo_son_last");
720 if (ptr
) _ArboSonLast
= (const char*)ptr
;
721 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"arbo_son");
722 if (ptr
) _ArboSon
= (const char*)ptr
;
723 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"arbo_level");
724 if (ptr
) _ArboLevel
= (const char*)ptr
;
725 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"arbo_x_extend");
726 if (ptr
) _ArboXExtend
= (const char*)ptr
;
728 // Rectangle selection style
729 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"rectangle_outline");
730 if (ptr
) _RectangleOutlineMode
= convertBool(ptr
);
731 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"rectangle_x");
732 if (ptr
) fromString((const char*)ptr
, _RectangleX
);
733 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"rectangle_y");
734 if (ptr
) fromString((const char*)ptr
, _RectangleY
);
735 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"rectangle_w");
736 if (ptr
) fromString((const char*)ptr
, _RectangleW
);
737 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"rectangle_h");
738 if (ptr
) fromString((const char*)ptr
, _RectangleH
);
739 ptr
= (char*) xmlGetProp (cur
, (xmlChar
*)"rectangle_drl");
740 if (ptr
) fromString((const char*)ptr
, _RectangleDeltaRL
);
744 _RootNode
= new SNode
;
749 // Check that this is a camera node
750 if ( stricmp((char*)cur
->name
, "node") == 0 )
752 SNode
*pNode
= new SNode
;
753 if (!pNode
->parse(cur
, this))
756 nlwarning("cannot parse node");
760 _RootNode
->addChild(pNode
);
765 _RootNode
->Opened
= true;
766 _ResizeFromChildW
= _ResizeFromChildH
= true;
773 void CGroupTree::setupArbo()
775 CViewRenderer
&rVR
= *CViewRenderer::getInstance();
776 sint32 id
= rVR
.getTextureIdFromName(_ArboOpenFirst
);
778 rVR
.getTextureSizeFromId(id
, _BmpW
, _BmpH
);
780 id
= rVR
.getTextureIdFromName(_ArboXExtend
);
782 rVR
.getTextureSizeFromId(id
, _XExtend
, dummy
);
784 // if not found, reset, to avoid errors
785 _ArboXExtend
.clear();
788 // ----------------------------------------------------------------------------
789 sint32
CGroupTree::getHrcIconXStart(sint32 depth
)
791 return depth
*(_BmpW
+_XExtend
);
794 // ----------------------------------------------------------------------------
795 sint32
CGroupTree::getHrcIconXEnd(sint32 depth
)
797 return depth
*(_BmpW
+_XExtend
) + _BmpW
;
800 // ----------------------------------------------------------------------------
801 void CGroupTree::checkCoords()
803 CInterfaceGroup::checkCoords();
806 // ----------------------------------------------------------------------------
807 void CGroupTree::updateCoords()
811 CInterfaceGroup::updateCoords();
814 // ----------------------------------------------------------------------------
815 void CGroupTree::drawSelection(sint x
, sint y
, sint w
, CRGBA col
)
817 CViewRenderer
&rVR
= *CViewRenderer::getInstance();
819 if(!_RectangleOutlineMode
)
821 rVR
.drawRotFlipBitmap (_RenderLayer
, _XReal
+_OffsetX
+x
, _YReal
+_OffsetY
+y
,
822 w
, _BmpH
, 0, false, rVR
.getBlankTextureId(),
828 x
+= _XReal
+_OffsetX
+_RectangleX
;
829 y
+= _YReal
+_OffsetY
+_RectangleY
;
831 sint32 h
= _RectangleH
;
832 sint32 rl
= _RenderLayer
+ _RectangleDeltaRL
;
834 rVR
.drawRotFlipBitmap (rl
, x
, y
, 1, h
, 0, false, rVR
.getBlankTextureId(), col
);
835 rVR
.drawRotFlipBitmap (rl
, x
+w
-1, y
, 1, h
, 0, false, rVR
.getBlankTextureId(), col
);
836 rVR
.drawRotFlipBitmap (rl
, x
, y
, w
, 1, 0, false, rVR
.getBlankTextureId(), col
);
837 rVR
.drawRotFlipBitmap (rl
, x
, y
+h
-1, w
, 1, 0, false, rVR
.getBlankTextureId(), col
);
841 // ----------------------------------------------------------------------------
842 CGroupTree::SNode
*CGroupTree::getNodeUnderMouse() const
844 if (_OverLine
== -1) return NULL
;
845 return _Lines
[_OverLine
].Node
;
848 // ----------------------------------------------------------------------------
849 void CGroupTree::draw()
852 sint32 clipx
, clipy
, clipw
, cliph
;
853 getClip(clipx
, clipy
, clipw
, cliph
);
856 bool bDisplayOver
= true;
858 if (!CWidgetManager::getInstance()->isMouseHandlingEnabled())
860 bDisplayOver
= false;
863 if (CWidgetManager::getInstance()->getModalWindow() == NULL
)
865 sint32 x
= CWidgetManager::getInstance()->getPointer()->getX();
866 sint32 y
= CWidgetManager::getInstance()->getPointer()->getY();
868 CInterfaceGroup
*pIG
= CWidgetManager::getInstance()->getWindowUnder(x
, y
);
869 CInterfaceGroup
*pParent
= this;
871 while (pParent
!= NULL
)
878 pParent
= pParent
->getParent();
881 // if the mouse is not in the clipped area
883 (x
> (clipx
+ clipw
)) ||
885 (y
> (clipy
+ cliph
)) || !bFound
)
893 for (sint32 i
= 0; i
< (sint32
)_Lines
.size(); ++i
)
895 if ((y
>= (_YReal
+(sint32
)(_Lines
.size()-i
-1)*_BmpH
)) &&
896 (y
< (_YReal
+(sint32
)(_Lines
.size()-i
)*_BmpH
)))
903 if (x
< _XReal
+ getHrcIconXEnd(_Lines
[_OverLine
].Depth
))
904 bDisplayOver
= false;
909 // some over to display?
910 if ((_OverLine
!= -1) && bDisplayOver
)
912 // Find the first container
913 CInterfaceGroup
*pIG
= _Parent
;
914 CGroupContainerBase
*pGC
= dynamic_cast<CGroupContainerBase
*>(pIG
);
917 pIG
= pIG
->getParent();
918 if (pIG
== NULL
) break;
919 if (dynamic_cast<CGroupContainerBase
*>(pIG
) != NULL
)
920 pGC
= dynamic_cast<CGroupContainerBase
*>(pIG
);
923 // avoid if window grayed
927 bDisplayOver
= false;
930 // Has to display the over?
933 // !NULL if the text over must displayed across all windows
934 CViewText
*viewTextExtend
= NULL
;
936 // If the line is a simple Text line (not template)
937 if(_Lines
[_OverLine
].Node
&& _Lines
[_OverLine
].Node
->DisplayText
)
940 viewTextExtend
= safe_cast
<CViewText
*>(_Lines
[_OverLine
].TextOrTemplate
);
941 // If this viewText is not too big, no need
942 if(viewTextExtend
->getXReal() + viewTextExtend
->getWReal() <= (clipx
+clipw
) )
943 viewTextExtend
= NULL
;
949 CRGBA col
= _OverColor
;
950 if(getModulateGlobalColor())
952 col
.modulateFromColor (_OverColor
, CWidgetManager::getInstance()->getGlobalColorForContent());
957 col
.A
= (uint8
)(((sint32
)col
.A
*((sint32
)CWidgetManager::getInstance()->getGlobalColorForContent().A
+1))>>8);
960 drawSelection( getHrcIconXEnd(_Lines
[_OverLine
].Depth
+ _Lines
[_OverLine
].getNumAdditionnalBitmap()), ((sint
)_Lines
.size()-_OverLine
-1)*_BmpH
,
961 _WReal
-getHrcIconXEnd(_Lines
[_OverLine
].Depth
+ _Lines
[_OverLine
].getNumAdditionnalBitmap()), col
);
963 // Draw extended over
966 CRGBA col
= _OverColorBack
;
967 // must add the selection color
968 if(_SelectedLine
== _OverLine
)
970 // simulate alpha blend of the selection bitmap
971 CRGBA sel
= _SelectedColor
;
972 sel
.A
= (uint8
)((sel
.A
*((sint32
)CWidgetManager::getInstance()->getGlobalColorForContent().A
+1))>>8);
973 col
.blendFromuiRGBOnly(col
, sel
, sel
.A
);
976 // will be drawn over all the interface
977 CWidgetManager::getInstance()->setOverExtendViewText(viewTextExtend
, col
);
982 // some selection to display
983 if (_SelectedLine
!= -1)
985 CRGBA col
= _SelectedColor
;
986 if(getModulateGlobalColor())
988 col
.modulateFromColor (_SelectedColor
, CWidgetManager::getInstance()->getGlobalColorForContent());
993 col
.A
= (uint8
)(((sint32
)col
.A
*((sint32
)CWidgetManager::getInstance()->getGlobalColorForContent().A
+1))>>8);
996 drawSelection( getHrcIconXEnd(_Lines
[_SelectedLine
].Depth
+ _Lines
[_SelectedLine
].getNumAdditionnalBitmap()), ((sint
)_Lines
.size()-_SelectedLine
-1)*_BmpH
,
997 _WReal
-getHrcIconXEnd(_Lines
[_SelectedLine
].Depth
+ _Lines
[_SelectedLine
].getNumAdditionnalBitmap()), col
);
1000 CInterfaceGroup::draw();
1003 // ----------------------------------------------------------------------------
1004 void CGroupTree::selectLine(uint line
, bool runAH
/*= true*/)
1006 if(line
>=_Lines
.size())
1009 if (!_Lines
[line
].Node
)
1011 // just deleted : must wait next draw to know the new line under mouse
1014 if (!_Lines
[line
].Node
->AHName
.empty() && runAH
)
1016 _CancelNextSelectLine
= false;
1018 CAHManager::getInstance()->runActionHandler ( _Lines[line].Node->AHName,
1020 _Lines[line].Node->AHParams );
1022 if (!_CancelNextSelectLine
)
1024 _SelectedLine
= line
;
1025 _SelectedNode
= _Lines
[line
].Node
;
1027 CAHManager::getInstance()->runActionHandler ( _Lines
[line
].Node
->AHName
,
1029 _Lines
[line
].Node
->AHParams
);
1030 _CancelNextSelectLine
= false;
1034 // ----------------------------------------------------------------------------
1035 bool CGroupTree::rightButton(uint line
)
1037 if(line
>=_Lines
.size())
1040 if (!_Lines
[_OverLine
].Node
|| _Lines
[_OverLine
].Node
->AHNameRight
.empty())
1043 if (line
!= (uint
) _SelectedLine
) selectLine(line
, false);
1045 CAHManager::getInstance()->runActionHandler ( _Lines
[line
].Node
->AHNameRight
,
1047 _Lines
[line
].Node
->AHParamsRight
);
1053 // ----------------------------------------------------------------------------
1054 const std::string
&CGroupTree::getSelectedNodeId() const
1056 if(_SelectedLine
>=0 && _SelectedLine
<(sint
)_Lines
.size() && _Lines
[_SelectedLine
].Node
)
1058 return _Lines
[_SelectedLine
].Node
->Id
;
1062 static string empty
;
1067 // ----------------------------------------------------------------------------
1068 bool CGroupTree::handleEvent (const NLGUI::CEventDescriptor
& event
)
1070 if (!_Active
) return false;
1071 if (CInterfaceGroup::handleEvent(event
)) return true;
1072 // The line must be over (pre-selected)
1073 if (event
.getType() == NLGUI::CEventDescriptor::mouse
&& _OverLine
>=0)
1075 const NLGUI::CEventDescriptorMouse
&eventDesc
= (const NLGUI::CEventDescriptorMouse
&)event
;
1077 if (!isIn(eventDesc
.getX(), eventDesc
.getY()))
1080 sint32 x
= eventDesc
.getX() - _OffsetX
;
1081 // sint32 y = eventDesc.getY() - _OffsetY;
1083 if (x
>= (_XReal
+getHrcIconXEnd(_Lines
[_OverLine
].Depth
+ _Lines
[_OverLine
].getNumAdditionnalBitmap())))
1086 if ((x
> (_XReal
+getHrcIconXStart(_Lines
[_OverLine
].Depth
)-_XExtend
)) &&
1087 (x
< (_XReal
+getHrcIconXEnd(_Lines
[_OverLine
].Depth
+ _Lines
[_OverLine
].getNumAdditionnalBitmap()))))
1090 if (eventDesc
.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightdown
)
1094 return rightButton(_OverLine
!= -1 ? _OverLine
: _SelectedLine
);
1098 bool toggleOne
= (eventDesc
.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftdown
);
1099 bool toggleAll
= (eventDesc
.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightdown
);
1100 if (toggleOne
|| toggleAll
)
1105 selectLine(_OverLine
);
1110 SNode
*changedNode
= _Lines
[_OverLine
].Node
;
1114 // if "SelectAncestorOnClose" feature wanted, if it was opened before, and if some node selected
1115 if(_SelectAncestorOnClose
&& changedNode
->Opened
&& _SelectedNode
)
1117 // check that the selected node is a son of the closing node
1118 SNode
*parent
= _SelectedNode
->Father
;
1121 if(parent
==changedNode
)
1123 // Then change selection to this parent first
1124 selectLine(_OverLine
);
1127 parent
= parent
->Father
;
1132 if(!_NavigateOneBranch
)
1134 // open/close the node
1135 changedNode
->Opened
= !changedNode
->Opened
;
1138 if (changedNode
->Opened
)
1139 changedNode
->openAll();
1141 changedNode
->closeAll();
1144 // else must close all necessary nodes.
1147 if(changedNode
->Opened
)
1148 changedNode
->closeAll();
1151 // must closeAll all his brothers first.
1152 if(changedNode
->Father
)
1154 changedNode
->Father
->closeAll();
1155 changedNode
->Father
->Opened
= true;
1157 changedNode
->Opened
= true;
1161 CAHManager::getInstance()->runActionHandler(changedNode
->AHNameClose
, this, changedNode
->AHParamsClose
);
1172 // ----------------------------------------------------------------------------
1173 void CGroupTree::unselect()
1176 _SelectedNode
= NULL
;
1179 // ----------------------------------------------------------------------------
1180 void CGroupTree::reset()
1185 _RootNode
->closeAll();
1186 _RootNode
->Opened
= true;
1191 // ----------------------------------------------------------------------------
1192 void CGroupTree::forceRebuild()
1194 _MustRebuild
= true;
1198 // ----------------------------------------------------------------------------
1199 void CGroupTree::rebuild()
1205 _RootNode
->Opened
= true;
1207 // Rebuild all depending on the logic
1209 addTextLine (0, _RootNode
);
1212 sint32 sizeH
= (sint32
)_Lines
.size()*_BmpH
;
1213 for (uint i
= 0; i
< _Lines
.size(); ++i
)
1214 _Lines
[i
].TextOrTemplate
->setY (_Lines
[i
].Node
->YDecal
+ sizeH
- ((1+_Lines
[i
].TextOrTemplate
->getY())*_BmpH
));
1215 // Add the hierarchy bitmaps
1216 addHierarchyBitmaps();
1217 // Find if we can display selection
1218 if (_SelectedNode
!= NULL
)
1221 for (uint i
= 0; i
< _Lines
.size(); ++i
)
1222 if (_Lines
[i
].Node
== _SelectedNode
)
1229 // Ok no more need to rebuild all this
1230 _MustRebuild
= false;
1233 // ----------------------------------------------------------------------------
1234 void CGroupTree::setRootNode (SNode
*pNewRoot
)
1238 _SelectedNode
= NULL
;
1240 CRefPtr
<SNode
> refPtrNewRoot
= pNewRoot
;
1244 // If the node was deleted
1245 if (pNewRoot
&& !refPtrNewRoot
)
1247 // NB nico : if anyone need that a day, please feel free to modify ...
1248 nlwarning("Trying to set a node that is part of the tree as root node (not supported yet ...)");
1251 // set new (may be NULL)
1252 _RootNode
= pNewRoot
;
1254 pNewRoot
->setParentTree(this);
1258 // ----------------------------------------------------------------------------
1259 void CGroupTree::removeAll()
1261 // Remove (but not delete) the groups template if any
1262 for(uint i
=0;i
<_Lines
.size();i
++)
1266 if(_Lines
[i
].Node
->Template
)
1268 delGroup(_Lines
[i
].Node
->Template
, true);
1273 // Clear all lines, but don't delete templates
1276 // Delete all BmpViews and/or all text views
1282 // ----------------------------------------------------------------------------
1283 void CGroupTree::addTextLine (uint8 nDepth
, CGroupTree::SNode
*pNode
)
1285 pNode
->setParentTree(this);
1289 line
.Depth
= nDepth
-1;
1291 if (pNode
->DisplayText
)
1293 CViewText
*pVT
= new CViewText(TCtorParam());
1294 line
.TextOrTemplate
= pVT
;
1295 pVT
->setId("t"+toString(_Lines
.size()));
1296 pVT
->setText(pNode
->Text
);
1297 pVT
->setColor(pNode
->Color
);
1298 if(pNode
->FontSize
==-1)
1299 pVT
->setFontSize(_FontSize
);
1301 pVT
->setFontSize(pNode
->FontSize
);
1305 line
.TextOrTemplate
= pNode
->Template
;
1307 line
.TextOrTemplate
->setPosRef (Hotspot_BL
);
1308 line
.TextOrTemplate
->setParentPosRef (Hotspot_BL
);
1309 line
.TextOrTemplate
->setParent (this);
1310 line
.TextOrTemplate
->setParentPos (NULL
);
1311 line
.TextOrTemplate
->setX (getHrcIconXEnd(nDepth
-1 + line
.getNumAdditionnalBitmap()));
1312 line
.TextOrTemplate
->setY ((sint32
)_Lines
.size());
1313 line
.TextOrTemplate
->setModulateGlobalColor(this->getModulateGlobalColor());
1314 if (pNode
->DisplayText
)
1315 addView (line
.TextOrTemplate
);
1317 addGroup ((CInterfaceGroup
*)line
.TextOrTemplate
);
1318 if (pNode
->NodeAddedCallback
)
1320 pNode
->NodeAddedCallback
->nodeAdded(pNode
, line
.TextOrTemplate
);
1322 _Lines
.push_back(line
);
1328 // **** standard hierarchy display, or if root
1329 if(!_NavigateOneBranch
|| nDepth
==0)
1331 for (uint i
= 0; i
< pNode
->Children
.size(); ++i
)
1333 // add the branch only if want to show it
1334 if(pNode
->Children
[i
]->Show
)
1335 addTextLine (nDepth
+1, pNode
->Children
[i
]);
1338 // **** display only the branch navigated
1341 // find the first child opened
1343 for (uint i
= 0; i
< pNode
->Children
.size(); ++i
)
1345 // don't take hid ones
1346 if(pNode
->Children
[i
]->Show
&& pNode
->Children
[i
]->Opened
)
1353 // If some chidl opened, add just this line
1356 addTextLine (nDepth
+1, pNode
->Children
[childOpen
]);
1358 // else add all closed, but showable lines
1361 for (uint i
= 0; i
< pNode
->Children
.size(); ++i
)
1363 if(pNode
->Children
[i
]->Show
)
1364 addTextLine (nDepth
+1, pNode
->Children
[i
]);
1371 // ----------------------------------------------------------------------------
1372 CViewBitmap
*CGroupTree::createViewBitmap(uint line
, const std::string
&idPrefix
, const std::string
&texture
)
1374 CViewBitmap
*pVB
= new CViewBitmap(TCtorParam());
1375 pVB
->setId(idPrefix
+toString(_Lines
.size())+"_"+toString(_Lines
[line
].Bmps
.size()));
1376 pVB
->setParent (this);
1377 pVB
->setParentPos (NULL
);
1378 pVB
->setModulateGlobalColor(this->getModulateGlobalColor());
1379 pVB
->setTexture(texture
);
1383 // ----------------------------------------------------------------------------
1384 void CGroupTree::addHierarchyBitmaps ()
1386 if (_RootNode
) _RootNode
->updateLastVisibleSon();
1387 for (uint nLayer
= 0; nLayer
< 256; nLayer
++)
1389 sint32 nCurRootLine
= -1;
1390 bool bCurRootLineLast
= false;
1391 bool bCurRootLineLastChild
= false;
1392 for (uint nLine
= 0; nLine
< _Lines
.size(); nLine
++)
1393 if (nLayer
<= _Lines
[nLine
].Depth
)
1395 // A Bitmap must be created
1396 CViewBitmap
*pVB
= createViewBitmap(nLine
, "t", "blank.tga");
1397 pVB
->setX (getHrcIconXStart(nLayer
));
1398 pVB
->setY ((sint32
)_Lines
.size()*_BmpH
- ((1+nLine
)*_BmpH
));
1400 bool bAddBitmap
= true;
1401 bool bAddXExtendBitmap
= false;
1403 // Are we on the last depth in the line ?
1404 if (_Lines
[nLine
].Depth
== nLayer
)
1406 nCurRootLine
= nLine
;
1407 if (_Lines
[nLine
].Node
== _Lines
[nCurRootLine
].Node
->Father
->LastVisibleSon
)
1408 bCurRootLineLast
= true;
1410 bCurRootLineLast
= false;
1411 bCurRootLineLastChild
= false;
1413 // do i have some child shown?
1414 bool haveSomeVisibleChild
= false;
1415 for(uint k
=0;k
<_Lines
[nLine
].Node
->Children
.size();k
++)
1417 if(_Lines
[nLine
].Node
->Children
[k
]->Show
)
1419 haveSomeVisibleChild
= true;
1425 if (haveSomeVisibleChild
)
1427 // Yes am I opened ?
1428 if (_Lines
[nLine
].Node
->Opened
)
1430 pVB
->setTexture(_ArboOpenFirst
);
1435 pVB
->setTexture(_ArboCloseJustOne
);
1442 // If there's a bitmap on this line , left an empty bitmap
1443 if (!_Lines[nLine].Node->Bitmap.empty())
1445 pVB->setTexture("blank.tga"); // create a transparent bitmap to have correct "child_resize_w"
1446 pVB->setColor(CRGBA(0, 0, 0, 0));
1450 pVB->setTexture(_ArboSonWithoutSon);
1453 pVB
->setTexture(_ArboSonWithoutSon
);
1456 // if not the root line, must add Extend Bitmap
1458 bAddXExtendBitmap
= true;
1462 // No we are before the last depth, Do we have any current root ?
1463 if (nCurRootLine
!= -1)
1465 // Yes, do the current line is child of current root line ?
1466 bool bFound
= false;
1467 for (uint i
= 0; i
< _Lines
[nCurRootLine
].Node
->Children
.size(); ++i
)
1468 if (_Lines
[nLine
].Node
== _Lines
[nCurRootLine
].Node
->Children
[i
])
1475 // is it the last child ?
1476 bool lastSonDisplay
= _Lines
[nLine
].Node
== _Lines
[nCurRootLine
].Node
->LastVisibleSon
;
1479 // Special for _NavigateOneBranch mode
1480 if(_NavigateOneBranch
)
1482 // if node opened, then his brother are hid! => he behaves like a "last son"
1483 if(_Lines
[nLine
].Node
->Opened
)
1484 lastSonDisplay
= true;
1487 // if must display like last child
1490 // Yes this is the last child
1491 pVB
->setTexture(_ArboSonLast
);
1492 bCurRootLineLastChild
= true;
1496 // No so we have brothers
1497 pVB
->setTexture(_ArboSon
);
1502 // Not found, display a line
1503 pVB
->setTexture(_ArboLevel
);
1505 // We have to not display a line if we have passed the last child of this root
1506 // We never have to display a line also if we are in _NavigateOneBranch mode
1507 if (bCurRootLineLastChild
|| _NavigateOneBranch
)
1517 _Lines
[nLine
].Bmps
.push_back(pVB
);
1519 // if must add the special extend bitmap, and if exist
1520 if(bAddXExtendBitmap
&& !_ArboXExtend
.empty())
1522 CViewBitmap
*pVB
= createViewBitmap(nLine
, "ext_t", _ArboXExtend
);
1523 pVB
->setX (getHrcIconXStart(nLayer
) - _XExtend
);
1524 pVB
->setY ((sint32
)_Lines
.size()*_BmpH
- ((1+nLine
)*_BmpH
));
1526 _Lines
[nLine
].Bmps
.push_back(pVB
);
1535 // add additionnal bitmap for each line
1536 for (uint nLine
= 0; nLine
< _Lines
.size(); nLine
++)
1538 if (!_Lines
[nLine
].Node
->Bitmap
.empty())
1540 CViewBitmap
*pVB
= createViewBitmap(nLine
, "custom_bm", _Lines
[nLine
].Node
->Bitmap
);
1541 pVB
->setX (getHrcIconXStart(_Lines
[nLine
].Depth
+ 1));
1542 pVB
->setY ((sint32
)_Lines
.size()*_BmpH
- ((1+nLine
)*_BmpH
));
1543 _Lines
[nLine
].Bmps
.push_back(pVB
);
1549 // ***************************************************************************
1550 CGroupTree::SNode
*CGroupTree::selectNodeByIdRecurse(SNode
*pNode
, const std::string
&nodeId
)
1552 // select this node?
1553 if(pNode
!=_RootNode
)
1555 if(pNode
->Id
== nodeId
)
1560 for(uint i
=0;i
<pNode
->Children
.size();i
++)
1562 SNode
*ret
= selectNodeByIdRecurse(pNode
->Children
[i
], nodeId
);
1567 // not found => NULL
1571 // ***************************************************************************
1572 bool CGroupTree::selectNodeById(const std::string
&nodeId
, bool triggerAH
)
1574 SNode
*selNode
= NULL
;
1576 // Avoid infinite recurs
1577 if(_AvoidSelectNodeByIdIR
)
1580 // first find in the hierarchy
1581 selNode
= selectNodeByIdRecurse(_RootNode
, nodeId
);
1586 // Opens the hierarchy
1587 SNode
*pFather
= selNode
->Father
;
1588 while(pFather
!= NULL
)
1590 pFather
->Opened
= true;
1591 pFather
= pFather
->Father
;
1596 // runAH may infinite recurs (HTML browse...)
1597 _AvoidSelectNodeByIdIR
= true;
1599 // launch the action handler
1600 CAHManager::getInstance()->runActionHandler ( selNode
->AHName
,
1602 selNode
->AHParams
);
1605 // runAH may infinite recurs (HTML browse...)
1606 _AvoidSelectNodeByIdIR
= false;
1609 _SelectedNode
= selNode
;
1621 // ***************************************************************************
1622 class CHandlerTreeReset
: public IActionHandler
1625 void execute (CCtrlBase
* /* pCaller */, const std::string
&sParams
)
1627 CGroupTree
*pTree
= dynamic_cast<CGroupTree
*>(CWidgetManager::getInstance()->getElementFromId(sParams
));
1633 REGISTER_ACTION_HANDLER( CHandlerTreeReset
, "tree_reset");
1635 // ***************************************************************************
1636 void CGroupTree::changeNavigateOneBranch(bool newState
)
1638 if(newState
!=_NavigateOneBranch
)
1640 _NavigateOneBranch
= newState
;
1641 // if new is true, then must reset both open state and selection
1642 if(_NavigateOneBranch
)
1645 // reselect the first line
1648 // else just rebuild
1656 // ***************************************************************************
1657 void CGroupTree::cancelNextSelectLine()
1659 _CancelNextSelectLine
= true;
1662 // ***************************************************************************
1663 int CGroupTree::luaGetRootNode(CLuaState
&ls
)
1665 CLuaIHM::checkArgCount(ls
, "getRootNode", 0);
1666 CLuaIHM::pushReflectableOnStack(ls
, getRootNode());
1670 // ***************************************************************************
1671 int CGroupTree::luaSetRootNode(CLuaState
&ls
)
1673 CLuaIHM::checkArgCount(ls
, "setRootNode", 1);
1679 setRootNode(SNode::luaGetNodeOnStack(ls
, "CGroupTree::setRootNode"));
1684 // ***************************************************************************
1685 int CGroupTree::luaForceRebuild(CLuaState
&ls
)
1687 CLuaIHM::checkArgCount(ls
, "forceRebuild", 0);
1692 // ***************************************************************************
1693 CGroupTree::SNode
*CGroupTree::SNode::luaGetNodeOnStack(CLuaState
&ls
, const char * /* funcName */)
1695 SNode
*node
= dynamic_cast<CGroupTree::SNode
*>(CLuaIHM::getReflectableOnStack(ls
, 1));
1696 CLuaIHM::check(ls
, node
!= NULL
, "SNode expected");
1700 // ***************************************************************************
1701 int CGroupTree::SNode::luaDetachChild(CLuaState
&ls
)
1703 const char *funcName
= "CGroupTree::SNode::luaDetachChild";
1704 CLuaIHM::checkArgCount(ls
, funcName
, 1);
1705 detachChild(luaGetNodeOnStack(ls
, funcName
));
1709 // ***************************************************************************
1710 int CGroupTree::SNode::luaSort(CLuaState
&ls
)
1712 const char *funcName
= "CGroupTree::SNode::luaSort";
1713 CLuaIHM::checkArgCount(ls
, funcName
, 0);
1718 // ***************************************************************************
1719 int CGroupTree::SNode::luaSortByBitmap(CLuaState
&ls
)
1721 const char *funcName
= "CGroupTree::SNode::luaSort";
1722 CLuaIHM::checkArgCount(ls
, funcName
, 0);
1727 // ***************************************************************************
1728 int CGroupTree::SNode::luaDeleteChild(CLuaState
&ls
)
1730 const char *funcName
= "CGroupTree::SNode::luaDeleteChild";
1731 CLuaIHM::checkArgCount(ls
, funcName
, 1);
1732 deleteChild(luaGetNodeOnStack(ls
, funcName
));
1736 // ***************************************************************************
1737 int CGroupTree::SNode::luaAddChild(CLuaState
&ls
)
1739 const char *funcName
= "CGroupTree::SNode::luaAddChild";
1740 CLuaIHM::checkArgCount(ls
, funcName
, 1);
1741 addChild(luaGetNodeOnStack(ls
, funcName
));
1745 // ***************************************************************************
1746 int CGroupTree::SNode::luaAddChildSorted(CLuaState
&ls
)
1748 const char *funcName
= "CGroupTree::SNode::luaAddChildSorted";
1749 CLuaIHM::checkArgCount(ls
, funcName
, 1);
1750 addChildSorted(luaGetNodeOnStack(ls
, funcName
));
1754 // ***************************************************************************
1755 int CGroupTree::SNode::luaAddChildSortedByBitmap(CLuaState
&ls
)
1757 const char *funcName
= "CGroupTree::SNode::luaAddChildSortedByBitmap";
1758 CLuaIHM::checkArgCount(ls
, funcName
, 1);
1759 addChildSorted(luaGetNodeOnStack(ls
, funcName
));
1763 // ***************************************************************************
1764 int CGroupTree::SNode::luaGetNodeFromId(CLuaState
&ls
)
1766 const char *funcName
= "CGroupTree::SNode::luaGetNodeFromId";
1767 CLuaIHM::checkArgCount(ls
, funcName
, 1);
1768 CLuaIHM::checkArgType(ls
, funcName
, 1, LUA_TSTRING
);
1769 SNode
*result
= getNodeFromId(ls
.toString(1));
1772 CLuaIHM::pushReflectableOnStack(ls
, result
);
1781 // ***************************************************************************
1782 int CGroupTree::SNode::luaGetParentTree(CLuaState
&ls
)
1784 CLuaIHM::checkArgCount(ls
, "getParentTree", 0);
1787 CLuaIHM::pushUIOnStack(ls
, ParentTree
);
1796 // ***************************************************************************
1797 int CGroupTree::luaGetNodeUnderMouse(CLuaState
&ls
)
1799 CLuaIHM::checkArgCount(ls
, "getNodeUnderMouse", 0);
1800 SNode
*node
= getNodeUnderMouse();
1803 CLuaIHM::pushReflectableOnStack(ls
, node
);
1812 // ***************************************************************************
1813 int CGroupTree::luaCancelNextSelectLine(CLuaState
&ls
)
1815 CLuaIHM::checkArgCount(ls
, "cancelNextSelectLine", 0);
1816 cancelNextSelectLine();
1820 // ***************************************************************************
1821 int CGroupTree::SNode::luaAddChildFront(CLuaState
&ls
)
1823 const char *funcName
= "CGroupTree::SNode::luaAddChildFront";
1824 CLuaIHM::checkArgCount(ls
, funcName
, 1);
1825 addChild(luaGetNodeOnStack(ls
, funcName
));
1829 // ***************************************************************************
1830 int CGroupTree::SNode::luaIsChild(CLuaState
&ls
)
1832 const char *funcName
= "CGroupTree::SNode::luaIsChild";
1833 CLuaIHM::checkArgCount(ls
, funcName
, 1);
1834 ls
.push(isChild(luaGetNodeOnStack(ls
, funcName
)));
1838 // ***************************************************************************
1839 int CGroupTree::SNode::luaAddChildAtIndex(CLuaState
&ls
)
1841 const char *funcName
= "CGroupTree::SNode::luaAddChildAtIndex";
1842 CLuaIHM::checkArgCount(ls
, funcName
, 2);
1843 CLuaIHM::checkArgType(ls
, funcName
, 2, LUA_TNUMBER
);
1844 addChildAtIndex(luaGetNodeOnStack(ls
, funcName
), (sint
) ls
.toInteger(2));
1848 // ***************************************************************************
1849 int CGroupTree::SNode::luaGetFather(CLuaState
&ls
)
1851 const char *funcName
= "CGroupTree::SNode::luaGetFather";
1852 CLuaIHM::checkArgCount(ls
, funcName
, 0);
1854 CLuaIHM::pushReflectableOnStack(ls
, Father
);
1860 // ***************************************************************************
1861 int CGroupTree::SNode::luaGetNumChildren(CLuaState
&ls
)
1863 const char *funcName
= "CGroupTree::SNode::luaGetNumChildren";
1864 CLuaIHM::checkArgCount(ls
, funcName
, 0);
1865 ls
.push((uint
)Children
.size());
1869 // ***************************************************************************
1870 int CGroupTree::SNode::luaGetChild(CLuaState
&ls
)
1872 const char *funcName
= "CGroupTree::SNode::luaGetChild";
1873 CLuaIHM::checkArgCount(ls
, funcName
, 1);
1874 CLuaIHM::checkArgType(ls
, funcName
, 1, LUA_TNUMBER
);
1876 sint index
= (sint
) ls
.toInteger(1);
1877 if (index
< 0 || index
>= (sint
) Children
.size())
1879 std::string range
= Children
.empty() ? "<empty>" : toString("[0, %d]", Children
.size() - 1);
1880 CLuaIHM::fails(ls
, "Bad index of tree node child : %d, range is %s", (int) index
, range
.c_str());
1882 CLuaIHM::pushReflectableOnStack(ls
, Children
[index
]);
1886 // ***************************************************************************
1887 int CGroupTree::SNode::luaCloseAll(CLuaState
&ls
)
1889 const char *funcName
= "CGroupTree::SNode::luaGetFather";
1890 CLuaIHM::checkArgCount(ls
, funcName
, 0);
1895 // ***************************************************************************
1896 int CGroupTree::luaSelectNodeById(CLuaState
&ls
)
1898 const char *funcName
= "selectNodeById";
1899 CLuaIHM::checkArgCount(ls
, funcName
, 2);
1900 CLuaIHM::checkArgType(ls
, funcName
, 1, LUA_TSTRING
);
1901 CLuaIHM::checkArgType(ls
, funcName
, 2, LUA_TBOOLEAN
);
1902 selectNodeById(ls
.toString(1), ls
.toBoolean(2));
1906 // ***************************************************************************
1907 int CGroupTree::luaGetSelectedNodeId(CLuaState
&ls
)
1909 CLuaIHM::checkArgCount(ls
, "getSelectedNodeId", 0);
1910 ls
.push(getSelectedNodeId());
1914 // ***************************************************************************
1915 int CGroupTree::luaSelectLine(CLuaState
&ls
)
1917 CLuaIHM::checkArgType(ls
, "CGroupTree::selectLine", 1, LUA_TNUMBER
);
1918 CLuaIHM::checkArgType(ls
, "CGroupTree::selectLine", 2, LUA_TBOOLEAN
);
1919 selectLine((uint
) ls
.toInteger(1), ls
.toBoolean(2));
1923 // ***************************************************************************
1924 int CGroupTree::luaUnselect(CLuaState
&ls
)
1926 CLuaIHM::checkArgCount(ls
, "unselect", 0);
1932 // ***************************************************************************
1933 uint
CGroupTree::SLine::getNumAdditionnalBitmap() const
1935 if (!Node
) return 0;
1936 return Node
->getNumBitmap();