Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / src / gui / interface_group.cpp
blob87504cf2410a0b914d9600aaca5f96fbf4f14f86
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2019 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013-2014 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2013-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 //
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/>.
22 #include "stdpch.h"
23 #include "libxml/globals.h"
24 #include "nel/misc/debug.h"
25 #include "nel/misc/xml_auto_ptr.h"
26 #include "nel/misc/stream.h"
27 #include "nel/gui/lua_manager.h"
28 #include "nel/gui/lua_ihm.h"
29 #include "nel/gui/view_renderer.h"
30 #include "nel/gui/interface_group.h"
31 #include "nel/gui/interface_link.h"
32 #include "nel/gui/widget_manager.h"
33 #include "nel/gui/ctrl_scroll_base.h"
34 #include "nel/gui/lua_ihm.h"
36 using namespace std;
37 using namespace NL3D;
39 #ifdef DEBUG_NEW
40 #define new DEBUG_NEW
41 #endif
43 #define IG_UNIQUE_ID(this) ((void*)&((this)->_GroupSizeRef)) // NB nico : use some pointer *inside* CInterfaceGroup as a unique id for lua registry (any field but
44 // the first), instead of using 'this'. 'this' is already used by
45 // CLuaIHM::pushReflectableOnStack as unique id to CInterfaceElement's ref pointers
47 namespace NLGUI
50 REGISTER_UI_CLASS(CInterfaceGroup)
52 // ------------------------------------------------------------------------------------------------
53 NLMISC_REGISTER_OBJECT(CViewBase, CInterfaceGroup, std::string, "interface_group");
55 CInterfaceGroup::CInterfaceGroup(const TCtorParam &param) : CCtrlBase(param)
57 _ParentSizeMax = NULL;
58 _MaxW = _MaxH = std::numeric_limits<sint32>::max();
59 _OffsetX = _OffsetY = 0;
60 _Overlappable= true;
61 _ResizeFromChildW= false;
62 _ResizeFromChildH= false;
63 _ResizeFromChildWMargin= 0;
64 _ResizeFromChildHMargin= 0;
65 _MaxWReal = _MaxHReal = std::numeric_limits<sint32>::max();
66 _GroupSizeRef = 0;
67 _Escapable= false;
68 _Priority= WIN_PRIORITY_NORMAL;
69 _UseCursor = true;
70 _IsGroupContainer = false;
71 _IsGroupScrollText = false;
72 _IsGroupInScene = false;
73 _IsGroupList = false;
74 _AHOnActive = NULL;
75 _AHOnDeactive = NULL;
76 _AHOnLeftClick = NULL;
77 _AHOnRightClick = NULL;
78 _AHOnEnter = NULL;
79 _AHOnEscape = NULL;
80 _NeedFrameUpdatePos= false;
81 _LUAEnvTableCreated= false;
82 _DepthForZSort= 0.f;
84 #ifdef AJM_DEBUG_TRACK_INTERFACE_GROUPS
85 CInterfaceManager::getInstance()->DebugTrackGroupsCreated( this );
86 #endif
90 // ------------------------------------------------------------------------------------------------
91 void CInterfaceGroup::setIdRecurse(const std::string &id)
93 CCtrlBase::setIdRecurse(id);
94 for(std::vector<CInterfaceGroup*>::iterator it = _ChildrenGroups.begin(); it != _ChildrenGroups.end(); ++it)
96 (*it)->setIdRecurse((*it)->getShortId());
98 for(std::vector<CCtrlBase*>::iterator it = _Controls.begin(); it != _Controls.end(); ++it)
100 (*it)->setIdRecurse((*it)->getShortId());
102 for(std::vector<CViewBase*>::iterator it = _Views.begin(); it != _Views.end(); ++it)
104 (*it)->setIdRecurse((*it)->getShortId());
109 // ------------------------------------------------------------------------------------------------
110 void CInterfaceGroup::notifyActiveCalled(const NLGUI::CEventDescriptorActiveCalledOnParent &desc)
112 // notify children that the 'active' state of this group has changed
113 for(std::vector<CInterfaceGroup*>::iterator it = _ChildrenGroups.begin(); it != _ChildrenGroups.end(); ++it)
115 (*it)->handleEvent(desc);
117 for(std::vector<CCtrlBase*>::iterator ctrlIt = _Controls.begin(); ctrlIt != _Controls.end(); ++ctrlIt)
119 (*ctrlIt)->handleEvent(desc);
123 // ------------------------------------------------------------------------------------------------
124 void CInterfaceGroup::setActive(bool state)
126 if(state != getActive())
128 CCtrlBase::setActive(state);
129 if (_AHOnActive != NULL && state)
131 CAHManager::getInstance()->runActionHandler (_AHOnActive, this, _AHOnActiveParams);
133 if (_AHOnDeactive != NULL && !state)
135 CAHManager::getInstance()->runActionHandler (_AHOnDeactive, this, _AHOnDeactiveParams);
138 notifyActiveCalled(NLGUI::CEventDescriptorActiveCalledOnParent(state));
142 // ------------------------------------------------------------------------------------------------
143 CInterfaceGroup::~CInterfaceGroup()
145 // delete any LUA group environnement
146 deleteLUAEnvTable();
147 // delete any LUA interface link "ondbchange"
148 removeAllLUAOnDbChange();
150 // NLMISC::TTime initStart;
151 // initStart = ryzomGetLocalTime ();
152 clearGroups();
153 // nlinfo ("%d seconds for clearGroups '%s'", (uint32)(ryzomGetLocalTime ()-initStart)/1000, _Id.c_str());
154 // initStart = ryzomGetLocalTime ();
155 clearControls();
156 // nlinfo ("%d seconds for clearControls '%s'", (uint32)(ryzomGetLocalTime ()-initStart)/1000, _Id.c_str());
157 // initStart = ryzomGetLocalTime ();
158 clearViews();
159 // nlinfo ("%d seconds for clearViews '%s'", (uint32)(ryzomGetLocalTime ()-initStart)/1000, _Id.c_str());
160 CWidgetManager::getInstance()->removeRefOnGroup (this);
162 #ifdef AJM_DEBUG_TRACK_INTERFACE_GROUPS
163 // AJM DEBUG
164 CInterfaceManager::getInstance()->DebugTrackGroupsDestroyed( this );
165 #endif
168 // ------------------------------------------------------------------------------------------------
169 void CInterfaceGroup::clearViews()
171 // Yoyo: important to not Leave NULL in the array, because of ~CGroupHTML and LibWWW callback
172 // that may call CInterfaceManager::getElementFromId() (and this method hates having NULL in the arrays ^^)
173 while(!_Views.empty())
175 CViewBase *pVB = _Views.back();
176 delEltOrder (pVB);
177 delete pVB;
178 // slower than a _Views.clear() out of loop, but we have to keep a clean array.
179 _Views.pop_back();
183 // ------------------------------------------------------------------------------------------------
184 void CInterfaceGroup::clearControls()
186 // Yoyo: important to not Leave NULL in the array, because of ~CGroupHTML() and LibWWW callback
187 // that may call CInterfaceManager::getElementFromId() (and this method hates having NULL in the arrays ^^)
188 while(!_Controls.empty())
190 CCtrlBase *pCB = _Controls.back();
191 delEltOrder (pCB);
192 delete pCB;
193 // slower than a _Controls.clear() out of loop, but we have to keep a clean array.
194 _Controls.pop_back();
198 // ------------------------------------------------------------------------------------------------
199 void CInterfaceGroup::clearGroups()
201 // Yoyo: important to not Leave NULL in the array, because of ~CGroupHTML() and LibWWW callback
202 // that may call CInterfaceManager::getElementFromId() (and this method hates having NULL in the arrays ^^)
203 while(!_ChildrenGroups.empty())
205 CInterfaceGroup *pIG = _ChildrenGroups.back();
206 delEltOrder (pIG);
207 delete pIG;
208 // slower than a _ChildrenGroups.clear() out of loop, but we have to keep a clean array.
209 _ChildrenGroups.pop_back();
213 // ------------------------------------------------------------------------------------------------
214 bool CInterfaceGroup::moveSBTrackY (CInterfaceGroup *target, sint32 dy)
216 // Look if there is a vertical scrollbar with this target attached ...
217 vector<CCtrlBase*>::iterator itc;
218 for (itc = _Controls.begin(); itc != _Controls.end(); itc++)
220 CCtrlBase *pCB = *itc;
221 CCtrlScrollBase *pSB = dynamic_cast<CCtrlScrollBase*>(pCB);
222 if (pSB != NULL)
224 if (pSB->getTarget() == target)
226 pSB->moveTrackY(dy);
227 return true;
231 return false;
234 // ------------------------------------------------------------------------------------------------
235 bool CInterfaceGroup::moveSBTargetY(CInterfaceGroup *target,sint32 dy)
237 // Look if there is a vertical scrollbar with this target attached ...
238 vector<CCtrlBase*>::iterator itc;
239 for (itc = _Controls.begin(); itc != _Controls.end(); itc++)
241 CCtrlBase *pCB = *itc;
242 CCtrlScrollBase *pSB = dynamic_cast<CCtrlScrollBase*>(pCB);
243 if (pSB != NULL)
245 if (pSB->getTarget() == target)
247 pSB->moveTargetY(dy);
248 return true;
252 return false;
255 // ------------------------------------------------------------------------------------------------
256 void CInterfaceGroup::setPriority(uint8 nprio)
258 if (nprio != _Priority)
260 CWidgetManager::getInstance()->setWindowPriority(this, nprio);
264 // ------------------------------------------------------------------------------------------------
265 bool CInterfaceGroup::parse (xmlNodePtr cur, CInterfaceGroup * parentGroup)
267 if ( !CCtrlBase::parse(cur,parentGroup) )
269 nlinfo ("cannot parse InterfaceElementLocalisable part");
270 return false;
273 //determine if the group is a window. If the property is not specified, set it to false.
274 CXMLAutoPtr ptr((const char*) xmlGetProp( cur, (xmlChar*)"win" ));
276 ptr = (char*) xmlGetProp( cur, (xmlChar*)"overlappable" );
277 if(ptr)
279 _Overlappable= convertBool(ptr);
282 ptr = (char*) xmlGetProp( cur, (xmlChar*)"escapable" );
283 if(ptr) _Escapable= convertBool(ptr);
285 // determine if the group must be sized according to his sons.
286 ptr = (char*) xmlGetProp( cur, (xmlChar*)"child_resize_w" );
287 if(ptr)
289 _ResizeFromChildW= convertBool(ptr);
291 ptr = (char*) xmlGetProp( cur, (xmlChar*)"child_resize_h" );
292 if(ptr)
294 _ResizeFromChildH= convertBool(ptr);
296 ptr = (char*) xmlGetProp( cur, (xmlChar*)"child_resize_wmargin" );
297 if(ptr)
299 NLMISC::fromString((const char*)ptr, _ResizeFromChildWMargin);
301 ptr = (char*) xmlGetProp( cur, (xmlChar*)"child_resize_hmargin" );
302 if(ptr)
304 NLMISC::fromString((const char*)ptr, _ResizeFromChildHMargin);
306 CAHManager::getInstance()->parseAH(cur, "on_active", "on_active_params", _AHOnActive, _AHOnActiveParams);
307 CAHManager::getInstance()->parseAH(cur, "on_deactive", "on_deactive_params", _AHOnDeactive, _AHOnDeactiveParams);
309 // Read user max size
310 ptr = (char*) xmlGetProp( cur, (xmlChar*)"max_w" );
311 if (ptr) NLMISC::fromString((const char*)ptr, _MaxW);
312 ptr = (char*) xmlGetProp( cur, (xmlChar*)"max_h" );
313 if (ptr) NLMISC::fromString((const char*)ptr, _MaxH);
314 ptr = (char*) xmlGetProp( cur, (xmlChar*)"max_sizeref" );
315 if (ptr)
317 parseMaxSizeRef(ptr);
320 ptr = (char*) xmlGetProp( cur, (xmlChar*)"max_sizeparent" );
321 if (ptr)
323 string idparent = NLMISC::toLowerAscii(ptr.str());
324 if (idparent != "parent")
326 if (parentGroup)
327 idparent = parentGroup->getId() +":" + string((const char*)ptr);
328 else
329 idparent = "ui:" + string((const char*)ptr);
331 else
333 if (parentGroup)
334 idparent = parentGroup->getId();
336 CWidgetManager::getInstance()->getParser()->addParentSizeMaxAssociation (this, idparent);
339 // left & right clicks
340 CAHManager::getInstance()->parseAH(cur, "group_onclick_r", "group_params_r", _AHOnRightClick, _AHOnRightClickParams);
341 CAHManager::getInstance()->parseAH(cur, "group_onclick_l", "group_params_l", _AHOnLeftClick, _AHOnLeftClickParams);
343 // Each window (modal and groupContainer) can be validated by Enter. if "" => no op.
344 CAHManager::getInstance()->parseAH(cur, "on_enter", "on_enter_params", _AHOnEnter, _AHOnEnterParams);
346 ptr = (char*) xmlGetProp( cur, (xmlChar*)"win_priority" );
347 if(ptr) NLMISC::fromString((const char*)ptr, _Priority);
349 ptr = (char*) xmlGetProp( cur, (xmlChar*)"use_cursor" );
350 if(ptr) _UseCursor= convertBool(ptr);
352 // Each window (modal and groupContainer) can be escaped if "escapable" set
353 // they can add an action handler before the hide
354 CAHManager::getInstance()->parseAH(cur, "on_escape", "on_escape_params", _AHOnEscape, _AHOnEscapeParams);
356 if( editorMode )
358 ptr = (char*) xmlGetProp( cur, BAD_CAST "on_active" );
359 if( ptr )
360 mapAHString( "on_active", std::string( (const char*)ptr ) );
362 ptr = (char*) xmlGetProp( cur, BAD_CAST "on_deactive" );
363 if( ptr )
364 mapAHString( "on_deactive", std::string( (const char*)ptr ) );
366 ptr = (char*) xmlGetProp( cur, BAD_CAST "group_onclick_r" );
367 if( ptr )
368 mapAHString( "group_onclick_r", std::string( (const char*)ptr ) );
370 ptr = (char*) xmlGetProp( cur, BAD_CAST "group_onclick_l" );
371 if( ptr )
372 mapAHString( "group_onclick_l", std::string( (const char*)ptr ) );
374 ptr = (char*) xmlGetProp( cur, BAD_CAST "on_enter" );
375 if( ptr )
376 mapAHString( "on_enter", std::string( (const char*)ptr ) );
378 ptr = (char*) xmlGetProp( cur, BAD_CAST "on_escape" );
379 if( ptr )
380 mapAHString( "on_escape", std::string( (const char*)ptr ) );
384 // LuaClass script
385 ptr = xmlGetProp (cur, (xmlChar*)"lua_class");
386 if( ptr )
387 CWidgetManager::getInstance()->getParser()->addLuaClassAssociation( this, (const char*)ptr );
389 return true;
392 std::string CInterfaceGroup::getProperty( const std::string &name ) const
394 if( name == "overlappable" )
396 return NLMISC::toString( _Overlappable );
398 else
399 if( name == "escapable" )
401 return NLMISC::toString( _Escapable );
403 else
404 if( name == "child_resize_w" )
406 return NLMISC::toString( _ResizeFromChildW );
408 else
409 if( name == "child_resize_h" )
411 return NLMISC::toString( _ResizeFromChildH );
413 else
414 if( name == "child_resize_wmargin" )
416 return NLMISC::toString( _ResizeFromChildWMargin );
418 else
419 if( name == "child_resize_hmargin" )
421 return NLMISC::toString( _ResizeFromChildHMargin );
423 else
424 if( name == "on_active" )
426 return getAHString( name );
428 else
429 if( name == "on_active_params" )
431 return getOnActiveParams();
433 else
434 if( name == "on_deactive" )
436 return getAHString( name );
438 else
439 if( name == "on_deactive_params" )
441 return getOnDeactiveParams();
443 else
444 if( name == "max_w" )
446 return NLMISC::toString( _MaxW );
448 else
449 if( name == "max_h" )
451 return NLMISC::toString( _MaxH );
453 else
454 if( name == "max_sizeref" )
456 return getSizeRefAsString( _GroupSizeRef, _SizeDivW, _SizeDivH );
458 else
459 if( name == "max_sizeparent" )
461 return CWidgetManager::getInstance()->getParser()->getParentSizeMaxAssociation( (CInterfaceElement*)this );
463 else
464 if( name == "group_onclick_r" )
466 return getAHString( name );
468 else
469 if( name == "group_params_r" )
471 return getRightClickHandlerParams();
473 else
474 if( name == "group_onclick_l" )
476 return getAHString( name );
478 else
479 if( name == "group_params_l" )
481 return getLeftClickHandlerParams();
483 else
484 if( name == "on_enter" )
486 return getAHString( name );
488 else
489 if( name == "on_enter_params" )
491 return getAHOnEnterParams();
493 else
494 if( name == "win_priority" )
496 return NLMISC::toString( _Priority );
498 else
499 if( name == "use_cursor" )
501 return NLMISC::toString( _UseCursor );
503 else
504 if( name == "on_escape" )
506 return getAHString( name );
508 else
509 if( name == "on_escape_params" )
511 return getAHOnEscapeParams();
513 else
514 if( name == "lua_class" )
516 return CWidgetManager::getInstance()->getParser()->getLuaClassAssociation( (CInterfaceGroup*)this );
518 else
519 return CCtrlBase::getProperty( name );
522 void CInterfaceGroup::setProperty( const std::string &name, const std::string &value )
524 if( name == "overlappable" )
526 bool b;
527 if( NLMISC::fromString( value, b ) )
528 _Overlappable = b;
529 return;
531 else
532 if( name == "escapable" )
534 bool b;
535 if( NLMISC::fromString( value, b ) )
536 _Escapable = b;
537 return;
539 else
540 if( name == "child_resize_w" )
542 bool b;
543 if( NLMISC::fromString( value, b ) )
544 _ResizeFromChildW = b;
545 return;
547 else
548 if( name == "child_resize_h" )
550 bool b;
551 if( NLMISC::fromString( value, b ) )
552 _ResizeFromChildH = b;
553 return;
555 else
556 if( name == "child_resize_wmargin" )
558 bool b;
559 if( NLMISC::fromString( value, b ) )
560 _ResizeFromChildWMargin = b;
561 return;
563 else
564 if( name == "child_resize_hmargin" )
566 bool b;
567 if( NLMISC::fromString( value, b ) )
568 _ResizeFromChildHMargin = b;
569 return;
571 else
572 if( name == "on_active" )
574 std::string dummy;
575 _AHOnActive = CAHManager::getInstance()->getAH( value, dummy );
576 mapAHString( name, value );
577 return;
579 else
580 if( name == "on_active_params" )
582 _AHOnActiveParams = value;
583 return;
585 else
586 if( name == "on_deactive" )
588 std::string dummy;
589 _AHOnDeactive = CAHManager::getInstance()->getAH( value, dummy );
590 mapAHString( name, value );
591 return;
593 else
594 if( name == "on_deactive_params" )
596 _AHOnDeactiveParams = value;
598 else
599 if( name == "max_w" )
601 sint32 i;
602 if( NLMISC::fromString( value, i ) )
603 _MaxW = i;
604 return;
606 else
607 if( name == "max_h" )
609 sint32 i;
610 if( NLMISC::fromString( value, i ) )
611 _MaxH = i;
612 return;
614 else
615 if( name == "max_sizeref" )
617 parseMaxSizeRef( value.c_str() );
618 return;
620 else
621 if( name == "max_sizeparent" )
623 std::string parentId;
625 if (value != "parent")
627 if (_Parent != NULL)
629 parentId = _Parent->getId() + ":" + value;
631 else
633 parentId = "ui:" + value;
636 else
638 if (_Parent)
640 parentId = _Parent->getId();
642 else
644 parentId = value;
648 CWidgetManager::getInstance()->getParser()->addParentSizeMaxAssociation(this, parentId);
649 return;
651 else
652 if( name == "group_onclick_r" )
654 std::string dummy;
655 _AHOnRightClick = CAHManager::getInstance()->getAH( value, dummy );
656 mapAHString( name, value );
657 return;
659 else
660 if( name == "group_params_r" )
662 _AHOnRightClickParams = value;
663 return;
665 else
666 if( name == "group_onclick_l" )
668 std::string dummy;
669 _AHOnLeftClick = CAHManager::getInstance()->getAH( value, dummy );
670 mapAHString( name, value );
671 return;
673 else
674 if( name == "group_params_l" )
676 _AHOnLeftClickParams = value;
677 return;
679 else
680 if( name == "on_enter" )
682 std::string dummy;
683 _AHOnEnter = CAHManager::getInstance()->getAH( value, dummy );
684 mapAHString( name, value );
685 return;
687 else
688 if( name == "on_enter_params" )
690 _AHOnEnterParams = value;
691 return;
693 else
694 if( name == "win_priority" )
696 sint8 i;
697 if( NLMISC::fromString( value, i ) )
698 _Priority = i;
699 return;
701 else
702 if( name == "use_cursor" )
704 bool b;
705 if( NLMISC::fromString( value, b ) )
706 _UseCursor = b;
707 return;
709 else
710 if( name == "on_escape" )
712 std::string dummy;
713 _AHOnEscape = CAHManager::getInstance()->getAH( value, dummy );
714 mapAHString( name, value );
715 return;
717 else
718 if( name == "on_escape_params" )
720 _AHOnEscapeParams = value;
721 return;
723 else
724 if( name == "lua_class" )
726 CWidgetManager::getInstance()->getParser()->addLuaClassAssociation( this, value );
727 return;
729 else
730 CCtrlBase::setProperty( name, value );
733 xmlNodePtr CInterfaceGroup::serialize( xmlNodePtr parentNode, const char *type ) const
735 xmlNodePtr node = serializeGroup( parentNode, type );
736 if( node == NULL )
737 return NULL;
739 serializeSubGroups( node );
740 serializeControls( node );
741 serializeViews( node );
742 serializeLinks( node );
744 return node;
747 xmlNodePtr CInterfaceGroup::serializeGroup( xmlNodePtr parentNode, const char *type ) const
749 xmlNodePtr node = CCtrlBase::serialize( parentNode, type );
750 if( node == NULL )
751 return NULL;
753 xmlNewProp( node, BAD_CAST "overlappable", BAD_CAST NLMISC::toString( _Overlappable ).c_str() );
754 xmlNewProp( node, BAD_CAST "escapable", BAD_CAST NLMISC::toString( _Escapable ).c_str() );
755 xmlNewProp( node, BAD_CAST "child_resize_w", BAD_CAST NLMISC::toString( _ResizeFromChildW ).c_str() );
756 xmlNewProp( node, BAD_CAST "child_resize_h", BAD_CAST NLMISC::toString( _ResizeFromChildH ).c_str() );
757 xmlNewProp( node, BAD_CAST "child_resize_wmargin", BAD_CAST NLMISC::toString( _ResizeFromChildWMargin ).c_str() );
758 xmlNewProp( node, BAD_CAST "child_resize_hmargin", BAD_CAST NLMISC::toString( _ResizeFromChildHMargin ).c_str() );
760 xmlNewProp( node, BAD_CAST "on_active", BAD_CAST getAHString( "on_active" ).c_str() );
761 xmlNewProp( node, BAD_CAST "on_active_params", BAD_CAST getOnActiveParams().c_str() );
762 xmlNewProp( node, BAD_CAST "on_deactive", BAD_CAST getAHString( "on_deactive" ).c_str() );
763 xmlNewProp( node, BAD_CAST "on_deactive_params", BAD_CAST getOnDeactiveParams().c_str() );
765 xmlNewProp( node, BAD_CAST "max_w", BAD_CAST NLMISC::toString( _MaxW ).c_str() );
766 xmlNewProp( node, BAD_CAST "max_h", BAD_CAST NLMISC::toString( _MaxH ).c_str() );
767 xmlNewProp( node, BAD_CAST "max_sizeref",
768 BAD_CAST getSizeRefAsString( _GroupSizeRef, _SizeDivW, _SizeDivH ).c_str() );
769 xmlNewProp( node, BAD_CAST "max_sizeparent",
770 BAD_CAST CWidgetManager::getInstance()->getParser()->getParentSizeMaxAssociation( (CInterfaceElement*)this ).c_str() );
771 xmlNewProp( node, BAD_CAST "group_onclick_r", BAD_CAST getAHString( "group_onclick_r" ).c_str() );
772 xmlNewProp( node, BAD_CAST "group_params_r", BAD_CAST getRightClickHandlerParams().c_str() );
773 xmlNewProp( node, BAD_CAST "group_onclick_l", BAD_CAST getAHString( "group_onclick_l" ).c_str() );
774 xmlNewProp( node, BAD_CAST "group_params_l", BAD_CAST getLeftClickHandlerParams().c_str() );
775 xmlNewProp( node, BAD_CAST "on_enter", BAD_CAST getAHString( "on_enter" ).c_str() );
776 xmlNewProp( node, BAD_CAST "on_enter_params", BAD_CAST getAHOnEnterParams().c_str() );
777 xmlNewProp( node, BAD_CAST "win_priority", BAD_CAST NLMISC::toString( _Priority ).c_str() );
778 xmlNewProp( node, BAD_CAST "use_cursor", BAD_CAST NLMISC::toString( _UseCursor ).c_str() );
779 xmlNewProp( node, BAD_CAST "on_escape", BAD_CAST getAHString( "on_escape" ).c_str() );
780 xmlNewProp( node, BAD_CAST "on_escape_params", BAD_CAST getAHOnEscapeParams().c_str() );
781 xmlNewProp( node, BAD_CAST "lua_class",
782 BAD_CAST CWidgetManager::getInstance()->getParser()->getLuaClassAssociation( (CInterfaceGroup*)this ).c_str() );
784 return node;
787 xmlNodePtr CInterfaceGroup::serializeSubGroups( xmlNodePtr parentNode ) const
789 std::vector< CInterfaceGroup* >::const_iterator itr;
790 for( itr = _ChildrenGroups.begin(); itr != _ChildrenGroups.end(); ++itr )
792 if( !(*itr)->IsSerializable() )
793 continue;
795 (*itr)->serialize( parentNode, "group" );
798 return parentNode;
801 xmlNodePtr CInterfaceGroup::serializeControls( xmlNodePtr parentNode ) const
803 std::vector< CCtrlBase* >::const_iterator itr;
804 for( itr = _Controls.begin(); itr != _Controls.end(); ++itr )
806 if( !(*itr)->IsSerializable() )
807 continue;
809 (*itr)->serialize( parentNode, "ctrl" );
812 return parentNode;
815 xmlNodePtr CInterfaceGroup::serializeViews( xmlNodePtr parentNode ) const
817 std::vector< CViewBase* >::const_iterator itr;
818 for( itr = _Views.begin(); itr != _Views.end(); ++itr )
820 if( !(*itr)->IsSerializable() )
821 continue;
823 (*itr)->serialize( parentNode, "view" );
826 return parentNode;
829 xmlNodePtr CInterfaceGroup::serializeTreeData( xmlNodePtr parentNode ) const
831 if( parentNode == NULL )
832 return NULL;
834 xmlNodePtr node = xmlNewNode( NULL, BAD_CAST "tree" );
835 if( node == NULL )
836 return NULL;
838 xmlAddChild( parentNode, node );
840 xmlSetProp( node, BAD_CAST "node", BAD_CAST CInterfaceElement::stripId( getId() ).c_str() );
842 return node;
846 bool CInterfaceGroup::serializeLinks( xmlNodePtr parentNode ) const
848 if( parentNode == NULL )
849 return false;
851 const std::map< uint32, SLinkData > &linkMap =
852 CWidgetManager::getInstance()->getParser()->getLinkMap();
854 xmlNodePtr node = NULL;
856 std::map< uint32, SLinkData >::const_iterator itr;
857 for( itr = linkMap.begin(); itr != linkMap.end(); ++itr )
859 if( itr->second.parent != getId() )
860 continue;
862 const SLinkData &data = itr->second;
864 node = xmlNewNode( NULL, BAD_CAST "link" );
865 if( node == NULL )
866 return false;
868 xmlAddChild( parentNode, node );
870 xmlSetProp( node, BAD_CAST "expr", BAD_CAST data.expr.c_str() );
872 if( !data.target.empty() )
873 xmlSetProp( node, BAD_CAST "target", BAD_CAST data.target.c_str() );
875 if( !data.action.empty() )
877 xmlSetProp( node, BAD_CAST "action", BAD_CAST data.action.c_str() );
879 if( !data.params.empty() )
880 xmlSetProp( node, BAD_CAST "params", BAD_CAST data.params.c_str() );
882 if( !data.cond.empty() )
883 xmlSetProp( node, BAD_CAST "cond", BAD_CAST data.cond.c_str() );
889 return true;
892 // ------------------------------------------------------------------------------------------------
893 void CInterfaceGroup::parseMaxSizeRef(const char *ptr)
895 parseSizeRef(ptr, _GroupSizeRef, _SizeDivW, _SizeDivH);
898 // ------------------------------------------------------------------------------------------------
899 uint32 CInterfaceGroup::getMemory ()
901 uint32 Mem = sizeof(*this);
902 /*vector<CInterfaceGroup*>::const_iterator itg;
903 for (itg = _ChildrenGroups.begin() ; itg != _ChildrenGroups.end(); itg++)
905 CInterfaceGroup *pIG = *itg;
906 Mem += pIG->getMemory();
909 for (vector<CViewBase*>::const_iterator itv = _Views.begin() ; itv != _Views.end(); itv++)
911 CViewBase *pVB = *itv;
912 Mem += pVB->getMemory();
915 for (vector<CCtrlBase*>::const_iterator itc = _Controls.begin() ; itc != _Controls.end(); itc++)
917 CCtrlBase* ctrl = *itc;
918 Mem += ctrl->getMemory();
920 return Mem;
923 // ------------------------------------------------------------------------------------------------
924 void CInterfaceGroup::addToEltOrder(CViewBase *view, sint order)
926 if (!view) return;
927 if (order == -1)
929 _EltOrder.push_back(view);
931 else
933 if (order > (sint) _EltOrder.size()) return;
934 _EltOrder.insert(_EltOrder.begin() + order, view);
938 // ------------------------------------------------------------------------------------------------
939 void CInterfaceGroup::addElement (CInterfaceElement *child, sint eltOrder /*= -1*/)
941 if (!child)
943 nlwarning("<CInterfaceGroup::addView> : tried to add a NULL view");
944 return;
947 if( child->isGroup() )
949 addGroup( static_cast< CInterfaceGroup* >( child ), eltOrder );
951 else
952 if( child->isCtrl() )
954 addCtrl( static_cast< CCtrlBase* >( child ), eltOrder );
956 else
957 if( child->isView() )
959 addView( static_cast< CViewBase* >( child ), eltOrder );
963 // ------------------------------------------------------------------------------------------------
964 void CInterfaceGroup::addView (CViewBase *child, sint eltOrder /*= -1*/)
966 if (!child)
968 nlwarning("<CInterfaceGroup::addView> : tried to add a NULL view");
969 return;
971 _Views.push_back(child);
972 addToEltOrder(child, eltOrder);
974 // elt callBack.
975 child->onAddToGroup();
978 // ------------------------------------------------------------------------------------------------
979 void CInterfaceGroup::addCtrl (CCtrlBase *child, sint eltOrder /*= -1*/)
981 if (!child)
983 nlwarning("<CInterfaceGroup::addCtrl> : tried to add a NULL ctrl");
984 return;
986 _Controls.push_back(child);
987 addToEltOrder(child, eltOrder);
989 // elt callBack.
990 child->onAddToGroup();
993 // ------------------------------------------------------------------------------------------------
994 void CInterfaceGroup::addGroup (CInterfaceGroup *child, sint eltOrder /*= -1*/)
996 if (!child)
998 nlwarning("<CInterfaceGroup::addGroup> : tried to add a NULL group");
999 return;
1001 _ChildrenGroups.push_back(child);
1002 addToEltOrder(child, eltOrder);
1004 // elt callBack.
1005 child->onAddToGroup();
1008 // ------------------------------------------------------------------------------------------------
1009 int CInterfaceGroup::luaAddGroup (CLuaState &ls)
1011 CLuaIHM::checkArgCount(ls, "CInterfaceGroup::addTab", 1);
1012 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup *>(CLuaIHM::getUIOnStack(ls, 1));
1013 if(group)
1015 group->setParent(this);
1016 group->setParentPos(this);
1017 addGroup(group);
1019 return 0;
1021 // ------------------------------------------------------------------------------------------------
1022 // id = incomplete path (text:list:a) lid complete one (ui:interface:content:text:list:a)
1023 static bool reverseCheckPath(const string &id, const string &lid)
1025 string idTmp = id, lidTmp = lid;
1026 // bool isFound = true;
1027 while (!idTmp.empty())
1029 string tokid, toklid;
1031 string::size_type posid = idTmp.rfind (":");
1032 if (posid == string::npos)
1034 posid = 0;
1035 tokid = idTmp;
1037 else
1039 tokid = idTmp.substr (posid+1);
1042 string::size_type poslid = lidTmp.rfind (":");
1043 if (poslid == string::npos)
1045 poslid = 0;
1046 toklid = lidTmp;
1048 else
1050 toklid = lidTmp.substr (poslid+1);
1053 if (tokid != toklid)
1054 return false;
1056 if (posid > 0)
1057 idTmp = idTmp.substr (0, posid);
1058 else
1059 idTmp.clear();
1061 if (poslid > 0)
1062 lidTmp = lidTmp.substr (0, poslid);
1063 else
1064 lidTmp.clear();
1066 return true;
1069 // ------------------------------------------------------------------------------------------------
1070 CViewBase* CInterfaceGroup::getView (const std::string &id)
1072 vector<CViewBase*>::const_iterator itv;
1073 for (itv = _Views.begin(); itv != _Views.end(); ++itv)
1075 CViewBase *pVB = (*itv);
1076 if (reverseCheckPath(id, pVB->getId()))
1077 return *itv;
1079 // search in sons
1080 std::vector<CInterfaceGroup*>::const_iterator itg;
1081 for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); ++itg)
1083 CViewBase* view = (*itg)->getView(id);
1084 if (view)
1085 return view;
1087 return NULL;
1090 // ------------------------------------------------------------------------------------------------
1091 CCtrlBase* CInterfaceGroup::getCtrl (const std::string &id)
1093 vector<CCtrlBase*>::const_iterator itv;
1094 for (itv = _Controls.begin(); itv != _Controls.end(); ++itv)
1096 CCtrlBase *pCB = (*itv);
1097 if (reverseCheckPath(id, pCB->getId()))
1098 return *itv;
1100 // search in sons
1101 std::vector<CInterfaceGroup*>::const_iterator itg;
1102 for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); ++itg)
1104 CCtrlBase*pCtrl = (*itg)->getCtrl (id);
1105 if (pCtrl)
1106 return pCtrl;
1108 return NULL;
1111 // ------------------------------------------------------------------------------------------------
1112 CInterfaceGroup*CInterfaceGroup::getGroup (const std::string &id) const
1114 std::vector<CInterfaceGroup*>::const_iterator itg;
1115 for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end();itg++)
1117 CInterfaceGroup *pIG = (*itg);
1118 if (reverseCheckPath(id, pIG->getId()))
1119 return *itg;
1121 // search in sons
1122 for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); ++itg)
1124 CInterfaceGroup *pCtrl = (*itg)->getGroup (id);
1125 if (pCtrl)
1126 return pCtrl;
1128 return NULL;
1131 // ------------------------------------------------------------------------------------------------
1132 bool CInterfaceGroup::delView (CViewBase *child, bool dontDelete /* = false*/)
1134 for (sint32 i = 0; i < (sint32)_Views.size(); ++i)
1136 if (_Views[i] == child)
1138 CViewBase *v = _Views[i];
1139 _Views.erase(_Views.begin()+i);
1140 delEltOrder (child);
1141 child->onRemoved();
1142 if (!dontDelete) delete v;
1143 return true;
1146 return false;
1149 // ------------------------------------------------------------------------------------------------
1150 bool CInterfaceGroup::delCtrl (CCtrlBase *child, bool dontDelete /* = false*/)
1152 for (sint32 i = 0; i < (sint32)_Controls.size(); ++i)
1154 if (_Controls[i] == child)
1156 CCtrlBase *c = _Controls[i];
1157 _Controls.erase(_Controls.begin()+i);
1158 delEltOrder (child);
1159 child->onRemoved();
1160 if (!dontDelete) delete c;
1161 return true;
1164 return false;
1167 // ------------------------------------------------------------------------------------------------
1168 bool CInterfaceGroup::delGroup (CInterfaceGroup *child, bool dontDelete /* = false*/)
1170 for (sint32 i = 0; i < (sint32)_ChildrenGroups.size(); ++i)
1172 if (_ChildrenGroups[i] == child)
1174 CInterfaceGroup *g = _ChildrenGroups[i];
1175 _ChildrenGroups.erase(_ChildrenGroups.begin()+i);
1176 delEltOrder (child);
1177 child->onRemoved();
1178 if (!dontDelete) delete g;
1179 return true;
1182 return false;
1185 // ------------------------------------------------------------------------------------------------
1186 int CInterfaceGroup::luaDelGroup (CLuaState &ls)
1188 CLuaIHM::checkArgCount(ls, "CInterfaceGroup::delTab", 1);
1189 CInterfaceGroup * group = dynamic_cast<CInterfaceGroup *>(CLuaIHM::getUIOnStack(ls, 1));
1190 if(group)
1192 delGroup(group);
1194 return 0;
1197 // ------------------------------------------------------------------------------------------------
1198 int CInterfaceGroup::luaGetNumGroups(CLuaState &ls)
1200 CLuaIHM::checkArgCount(ls, "CInterfaceGroup::getNumGroups", 0);
1201 ls.push((uint)_ChildrenGroups.size());
1202 return 1;
1205 // ------------------------------------------------------------------------------------------------
1206 int CInterfaceGroup::luaGetGroup(CLuaState &ls)
1208 const char *funcName = "CInterfaceGroup::getGroup";
1209 CLuaIHM::checkArgCount(ls, "CInterfaceGroup::getGroup", 1);
1210 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1211 uint index = (uint) ls.toInteger(1);
1212 if (index >= _ChildrenGroups.size())
1214 CLuaIHM::fails(ls, "getGroup : try to index group %s, but there are only %d son groups", ls.toString(1), (int) _ChildrenGroups.size());
1216 CLuaIHM::pushUIOnStack(ls, _ChildrenGroups[index]);
1217 return 1;
1220 // ------------------------------------------------------------------------------------------------
1221 void CInterfaceGroup::delEltOrder (CViewBase *pElt)
1223 for (sint32 i = 0; i < (sint32)_EltOrder.size(); ++i)
1225 if (_EltOrder[i] == pElt)
1227 _EltOrder.erase (_EltOrder.begin()+i);
1228 return;
1233 // ------------------------------------------------------------------------------------------------
1234 bool CInterfaceGroup::delView (const std::string &id, bool dontDelete /* = false*/)
1236 return delView(getView(id), dontDelete);
1239 // ------------------------------------------------------------------------------------------------
1240 bool CInterfaceGroup::delCtrl (const std::string &id, bool dontDelete /* = false*/)
1242 return delCtrl(getCtrl(id), dontDelete);
1245 // ------------------------------------------------------------------------------------------------
1246 bool CInterfaceGroup::delGroup (const std::string &id, bool dontDelete /* = false*/)
1248 return delGroup(getGroup(id), dontDelete);
1251 // ------------------------------------------------------------------------------------------------
1252 bool CInterfaceGroup::isChildGroup(const CInterfaceGroup *group) const
1254 return std::find(_ChildrenGroups.begin(), _ChildrenGroups.end(), group) != _ChildrenGroups.end();
1257 // ------------------------------------------------------------------------------------------------
1258 bool CInterfaceGroup::handleEvent (const NLGUI::CEventDescriptor &event)
1260 if (CCtrlBase::handleEvent(event)) return true;
1261 if (!_Active)
1262 return false;
1264 if (event.getType() == NLGUI::CEventDescriptor::system)
1266 NLGUI::CEventDescriptorSystem &eds = (NLGUI::CEventDescriptorSystem&)event;
1267 if (eds.getEventTypeExtended() == NLGUI::CEventDescriptorSystem::activecalledonparent)
1269 // notify all childrens
1270 notifyActiveCalled((NLGUI::CEventDescriptorActiveCalledOnParent &) eds);
1274 if (event.getType() == NLGUI::CEventDescriptor::mouse)
1276 const NLGUI::CEventDescriptorMouse &eventDesc = (const NLGUI::CEventDescriptorMouse &)event;
1278 if (!isIn(eventDesc.getX(), eventDesc.getY()))
1279 return false;
1281 bool taken = false;
1283 // For each control in the group...
1284 vector<CCtrlBase*>::const_iterator itc;
1285 for (itc = _Controls.begin(); itc != _Controls.end(); itc++)
1287 CCtrlBase *pCB = *itc;
1288 if (pCB->getActive())
1289 taken = taken || pCB->handleEvent(eventDesc);
1291 if (taken)
1292 return true;
1294 // For each child group
1295 for (sint i = (sint)_ChildrenGroups.size()-1; i >= 0; --i)
1297 CInterfaceGroup *pIG = _ChildrenGroups[i];
1298 if (pIG->getActive())
1299 if (pIG->handleEvent(eventDesc))
1300 return true;
1304 if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftdown)
1306 if (_AHOnLeftClick != NULL)
1308 CAHManager::getInstance()->runActionHandler(_AHOnLeftClick, this, _AHOnLeftClickParams);
1309 return true;
1313 if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightup)
1315 if (_AHOnRightClick != NULL)
1317 CAHManager::getInstance()->runActionHandler(_AHOnRightClick, this, _AHOnRightClickParams);
1318 return true;
1321 if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousewheel)
1323 // handle the Mouse Wheel only if interesting
1324 if (_H>_MaxH)
1326 CInterfaceGroup *currParent = _Parent;
1327 while (currParent)
1329 if (currParent->moveSBTargetY (this, -(eventDesc.getWheel()*12)))
1330 return true;
1331 currParent = currParent->getParent();
1336 return false;
1339 // ------------------------------------------------------------------------------------------------
1340 void CInterfaceGroup::executeControl (const std::string &/* sControlName */)
1342 // bool taken = false;
1343 // CCtrlBase *pIC = getCtrl (sControlName);
1344 // if (pIC != NULL)
1345 // pIC->callback(taken);
1349 // ------------------------------------------------------------------------------------------------
1350 void CInterfaceGroup::draw ()
1352 sint32 oldSciX, oldSciY, oldSciW, oldSciH;
1353 makeNewClip (oldSciX, oldSciY, oldSciW, oldSciH);
1355 // Display sons only if not total clipped
1356 CViewRenderer &rVR = *CViewRenderer::getInstance();
1357 if( !rVR.isClipWindowEmpty() )
1359 // Draw all decorative elements
1360 vector<CViewBase*>::const_iterator ite;
1361 for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++)
1363 CViewBase *pVB = *ite;
1364 if( pVB->getName() == "=MARKED=" )
1366 nlinfo( "=MARKED=" );
1369 if (pVB->getActive())
1370 pVB->draw();
1374 restoreClip (oldSciX, oldSciY, oldSciW, oldSciH);
1377 // ------------------------------------------------------------------------------------------------
1378 void CInterfaceGroup::drawNoClip()
1380 // Display sons only if not total clipped
1381 CViewRenderer &rVR = *CViewRenderer::getInstance();
1382 if( !rVR.isClipWindowEmpty() )
1384 // Draw all decorative elements
1385 vector<CViewBase*>::const_iterator ite;
1386 for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++)
1388 CViewBase *pVB = *ite;
1389 if (pVB->getActive())
1390 pVB->draw();
1395 // ------------------------------------------------------------------------------------------------
1396 void CInterfaceGroup::renderWiredQuads(CInterfaceElement::TRenderWired type, const std::string &uiFilter)
1398 if (!_Active) return;
1399 CInterfaceElement::renderWiredQuads(type, uiFilter);
1400 sint32 oldSciX, oldSciY, oldSciW, oldSciH;
1401 makeNewClip (oldSciX, oldSciY, oldSciW, oldSciH);
1402 for(std::vector<CViewBase*>::iterator it = _EltOrder.begin(); it != _EltOrder.end(); ++it)
1404 if (*it) (*it)->renderWiredQuads(type, uiFilter);
1406 restoreClip (oldSciX, oldSciY, oldSciW, oldSciH);
1409 // ------------------------------------------------------------------------------------------------
1410 void CInterfaceGroup::drawElement (CViewBase *el)
1412 sint32 oldSciX, oldSciY, oldSciW, oldSciH;
1413 makeNewClip (oldSciX, oldSciY, oldSciW, oldSciH);
1415 if(el)
1416 el->draw();
1418 restoreClip (oldSciX, oldSciY, oldSciW, oldSciH);
1421 // ------------------------------------------------------------------------------------------------
1422 sint32 CInterfaceGroup::getInnerWidth() const
1424 sint width = CInterfaceElement::getInnerWidth();
1425 return std::min(width, _MaxWReal - _MarginLeft);
1428 // ------------------------------------------------------------------------------------------------
1429 void CInterfaceGroup::checkCoords()
1431 // Make XReal same as in updateCoords() as some elements (CViewText) depends on it
1432 _XReal += _MarginLeft;
1434 //update all children elements
1435 vector<CViewBase*>::const_iterator ite;
1436 for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++)
1438 CViewBase *pIE = *ite;
1439 if(pIE->getActive())
1440 pIE->checkCoords();
1443 _XReal -= _MarginLeft;
1444 executeLuaScriptOnDraw();
1447 // ------------------------------------------------------------------------------------------------
1448 void CInterfaceGroup::executeLuaScriptOnDraw()
1450 // If some LUA script attached to me, execute it
1451 if(!_LUAOnDraw.empty())
1452 CAHManager::getInstance()->runActionHandler("lua", this, _LUAOnDraw);
1456 // ------------------------------------------------------------------------------------------------
1457 void CInterfaceGroup::doUpdateCoords()
1459 _MaxWReal = _MaxW;
1460 _MaxHReal = _MaxH;
1462 CInterfaceElement *el = NULL;
1464 if (_ParentSizeMax != NULL)
1466 el = _ParentSizeMax;
1468 else
1470 if (_ParentSize != NULL)
1472 el = _ParentSize;
1474 else
1476 if (_ParentPos != NULL)
1477 el = _ParentPos;
1478 else
1479 el = _Parent;
1483 if (el != NULL)
1485 if (_GroupSizeRef&1)
1486 _MaxWReal += _SizeDivW * el->getWReal() / 10;
1488 if (_GroupSizeRef&2)
1489 _MaxHReal += _SizeDivH * el->getHReal() / 10;
1492 CViewBase::updateCoords();
1493 _XReal += _OffsetX + _MarginLeft;
1494 _YReal += _OffsetY;
1496 //update all children elements
1497 vector<CViewBase*>::const_iterator ite;
1498 for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++)
1500 CViewBase *pIE = *ite;
1501 pIE->updateCoords();
1504 _XReal -= (_OffsetX + _MarginLeft);
1505 _YReal -= _OffsetY;
1508 // ------------------------------------------------------------------------------------------------
1509 void CInterfaceGroup::updateCoords()
1511 // update basis and sons one time.
1512 doUpdateCoords();
1514 // if the group must resize from children
1515 if(_ResizeFromChildH || _ResizeFromChildW)
1517 // compute BBox of all childrens
1518 sint width, height;
1519 evalChildrenBBox(_ResizeFromChildW, _ResizeFromChildH, width, height);
1520 // set forced size.
1521 if(_ResizeFromChildW)
1523 _W= _ResizeFromChildWMargin + width;
1525 if(_ResizeFromChildH)
1527 _H= _ResizeFromChildHMargin + height;
1531 CInterfaceElement::updateCoords();
1534 // ------------------------------------------------------------------------------------------------
1535 void CInterfaceGroup::evalChildrenBBox(bool resizeFromChildW, bool resizeFromChildH, sint &width, sint &height) const
1537 sint yMin=INT_MAX, yMax=INT_MIN;
1538 sint xMin=INT_MAX, xMax=INT_MIN;
1539 vector<CViewBase*>::const_iterator ite;
1540 for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++)
1542 CViewBase *pIE = *ite;
1543 nlassert(pIE);
1544 if (pIE->getActive())
1546 const CInterfaceElement *el = pIE->getParentPos() ? pIE->getParentPos() : pIE->getParent();
1547 if (el == this)
1549 // to compute the bbox, don't use direct sons that have a sizeref on the resizing coordinate
1550 if ((resizeFromChildW && (pIE->getSizeRef() & 1))
1551 || (resizeFromChildH && (pIE->getSizeRef() & 2))
1554 continue;
1557 // avoid also some interface elements
1558 if(pIE->avoidResizeParent())
1559 continue;
1560 // get the real coords bounds.
1561 sint32 x0,y0,x1,y1;
1562 // If it is a group, minimize with MaxHReal / MaxWReal
1563 const CInterfaceGroup *sonGroup= dynamic_cast<const CInterfaceGroup*>(pIE);
1564 // \todo yoyo: do not know why but don't work if this==scroll_text
1565 if(sonGroup && !isGroupScrollText())
1567 sint32 w, h;
1568 sonGroup->computeClipContribution(x0, y0, w, h);
1569 x1= x0 + w;
1570 y1= y0 + h;
1572 else
1574 x0= pIE->getXReal();
1575 y0= pIE->getYReal();
1576 x1= x0 + pIE->getWReal();
1577 y1= y0 + pIE->getHReal();
1579 // enlarge
1580 if(x0<xMin)
1581 xMin= x0;
1582 if(y0<yMin)
1583 yMin= y0;
1584 if(x1>xMax)
1585 xMax= x1;
1586 if(y1>yMax)
1587 yMax= y1;
1590 width = xMax - xMin;
1591 height = yMax - yMin;
1594 // ------------------------------------------------------------------------------------------------
1595 CInterfaceElement* CInterfaceGroup::getElement (const std::string &id)
1597 if (_Id == id)
1598 return this;
1600 if (id.compare(0, _Id.size(), _Id) != 0)
1601 return NULL;
1603 vector<CViewBase*>::const_iterator itv;
1604 for (itv = _Views.begin(); itv != _Views.end(); itv++)
1606 CViewBase *pVB = *itv;
1607 #if !FINAL_VERSION // For SpeedUp in final version
1608 nlassert(pVB); // The element must not be NULL
1609 #endif
1610 if (pVB->getId() == id)
1611 return pVB;
1614 vector<CCtrlBase*>::const_iterator itc;
1615 for (itc = _Controls.begin(); itc != _Controls.end(); itc++)
1617 CCtrlBase* ctrl = *itc;
1618 #if !FINAL_VERSION // For SpeedUp in final version
1619 nlassert(ctrl); // The element must not be NULL
1620 #endif
1621 if (ctrl->getId() == id)
1622 return ctrl;
1625 vector<CInterfaceGroup*>::const_iterator itg;
1626 for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
1628 CInterfaceGroup *pIG = *itg;
1629 #if !FINAL_VERSION // For SpeedUp in final version
1630 nlassert(pIG); // The element must not be NULL
1631 #endif
1632 CInterfaceElement *pIEL = pIG->getElement(id);
1633 if (pIEL != NULL)
1634 return pIEL;
1636 return NULL;
1639 // ------------------------------------------------------------------------------------------------
1640 bool CInterfaceGroup::delElement (const std::string &id, bool noWarning)
1642 if (id.substr(0, _Id.size()) != _Id)
1643 return false;
1645 vector<CViewBase*>::const_iterator itv;
1646 for (itv = _Views.begin(); itv != _Views.end(); itv++)
1648 CViewBase *pVB = *itv;
1649 if (pVB->getId() == id)
1651 delView (pVB, false);
1652 return true;
1656 vector<CCtrlBase*>::const_iterator itc;
1657 for (itc = _Controls.begin(); itc != _Controls.end(); itc++)
1659 CCtrlBase* ctrl = *itc;
1660 if (ctrl->getId() == id)
1662 delCtrl (ctrl, false);
1663 return true;
1667 vector<CInterfaceGroup*>::const_iterator itg;
1668 for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
1670 CInterfaceGroup *pIG = *itg;
1671 if (pIG->getId() == id)
1673 // If this is a root window
1674 if (pIG->getRootWindow () == pIG)
1675 CWidgetManager::getInstance()->unMakeWindow(pIG, noWarning);
1676 delGroup (pIG, false);
1677 return true;
1680 return false;
1683 // ------------------------------------------------------------------------------------------------
1684 bool CInterfaceGroup::delElement (CInterfaceElement *pIE, bool noWarning)
1686 // delete correct type of element
1687 if(pIE->isGroup())
1689 CInterfaceGroup *pIG= static_cast<CInterfaceGroup*>(pIE);
1690 // unmake window if it is
1691 if (pIG->getRootWindow () == pIG)
1692 CWidgetManager::getInstance()->unMakeWindow(pIG, noWarning);
1693 return delGroup(pIG);
1695 else if(pIE->isCtrl())
1697 return delCtrl(static_cast<CCtrlBase*>(pIE));
1700 nlassert(pIE->isView());
1701 return delView(static_cast<CViewBase*>(pIE));
1704 // ------------------------------------------------------------------------------------------------
1705 CInterfaceElement* CInterfaceGroup::takeElement( CInterfaceElement *e )
1707 bool ok = false;
1709 if( e->isGroup() )
1711 ok = delGroup( static_cast< CInterfaceGroup* >( e ), true );
1713 else
1714 if( e->isCtrl() )
1716 ok = delCtrl( static_cast< CCtrlBase* >( e ), true );
1718 else
1719 if( e->isView() )
1721 ok = delView( static_cast< CViewBase* >( e ), true );
1724 if( ok )
1725 return e;
1726 else
1727 return NULL;
1730 // ------------------------------------------------------------------------------------------------
1731 bool CInterfaceGroup::isWindowUnder (sint32 x, sint32 y)
1733 return ((x >= _XReal) &&
1734 (x < (_XReal + _WReal))&&
1735 (y > _YReal) &&
1736 (y <= (_YReal + _HReal)));
1739 // ------------------------------------------------------------------------------------------------
1740 CInterfaceGroup* CInterfaceGroup::getGroupUnder (sint32 x, sint32 y)
1742 // Begins by the children
1743 std::vector<CInterfaceGroup*>::const_iterator itg;
1744 for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
1746 CInterfaceGroup *pChild = *itg;
1747 CInterfaceGroup *pChildUnder = pChild->getGroupUnder (x-_XReal, y-_YReal);
1748 if (pChildUnder != NULL)
1750 if ( (x >= _XReal) &&
1751 (x < (_XReal + _WReal))&&
1752 (y > _YReal) &&
1753 (y <= (_YReal+ _HReal)))
1754 return pChildUnder;
1758 // If not found in childs then try in the parent one
1759 if ( (x >= _XReal) &&
1760 (x < (_XReal + _WReal))&&
1761 (y > _YReal) &&
1762 (y <= (_YReal+ _HReal)))
1763 return this;
1764 return NULL;
1767 // ------------------------------------------------------------------------------------------------
1768 bool CInterfaceGroup::getViewsUnder (sint32 x, sint32 y, sint32 clipX, sint32 clipY, sint32 clipW, sint32 clipH, std::vector<CViewBase*> &vVB)
1770 if (!((x >= _XReal) &&
1771 (x < (_XReal + _WReal))&&
1772 (y > _YReal) &&
1773 (y <= (_YReal+ _HReal))))
1774 return false;
1775 // test against current clip
1776 computeCurrentClipContribution(clipX, clipY, clipW, clipH,
1777 clipX, clipY, clipW, clipH);
1779 if (!((x > clipX) &&
1780 (x < (clipX + clipW))&&
1781 (y > clipY) &&
1782 (y < (clipY + clipH))))
1783 return false;
1787 // same as draw order: start with parent
1788 std::vector<CViewBase*>::const_iterator itc;
1789 for (itc = _EltOrder.begin(); itc != _EltOrder.end(); itc++)
1791 if (!(*itc)->isCtrl() && !(*itc)->isGroup()) // must be a view
1793 CViewBase *pVB = *itc;
1794 if (pVB != NULL)
1795 if (pVB->getActive())
1796 if ( ((x) > pVB->getXReal()) &&
1797 ((x) < (pVB->getXReal() + pVB->getWReal()))&&
1798 ((y) > pVB->getYReal()) &&
1799 ((y) < (pVB->getYReal() + pVB->getHReal())))
1801 vVB.push_back (pVB);
1806 // same as draw order: continue with children
1807 std::vector<CInterfaceGroup*>::const_iterator itg;
1808 for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
1810 CInterfaceGroup *pChild = *itg;
1811 if (pChild->getActive())
1813 // bool bUnder =
1814 pChild->getViewsUnder (x, y, clipX, clipY, clipW, clipH, vVB);
1815 // if (bUnder && !vICL.empty())
1816 // return true;
1819 return true;
1822 // ------------------------------------------------------------------------------------------------
1823 bool CInterfaceGroup::getCtrlsUnder (sint32 x, sint32 y, sint32 clipX, sint32 clipY, sint32 clipW, sint32 clipH, std::vector<CCtrlBase*> &vICL)
1825 if (!((x >= _XReal) &&
1826 (x < (_XReal + _WReal))&&
1827 (y > _YReal) &&
1828 (y <= (_YReal+ _HReal))))
1829 return false;
1830 // test against current clip
1831 computeCurrentClipContribution(clipX, clipY, clipW, clipH,
1832 clipX, clipY, clipW, clipH);
1834 if (!((x >= clipX) &&
1835 (x < (clipX + clipW))&&
1836 (y > clipY) &&
1837 (y <= (clipY + clipH))))
1838 return false;
1842 // same as draw order: start with parent
1843 std::vector<CViewBase*>::const_iterator itc;
1844 for (itc = _EltOrder.begin(); itc != _EltOrder.end(); itc++)
1846 if ((*itc)->isCtrl() && !(*itc)->isGroup()) // must be a ctrl but not a group (parsed later)
1848 CCtrlBase *pICL = (CCtrlBase *) *itc;
1849 if (pICL != NULL)
1850 if (pICL->getActive())
1851 if ( ((x) >= pICL->getXReal()) &&
1852 ((x) < (pICL->getXReal() + pICL->getWReal()))&&
1853 ((y) > pICL->getYReal()) &&
1854 ((y) <= (pICL->getYReal() + pICL->getHReal())))
1856 vICL.push_back (pICL->getSubCtrl(x,y));
1861 // same as draw order: continue with children
1862 std::vector<CInterfaceGroup*>::const_iterator itg;
1863 for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
1865 CInterfaceGroup *pChild = *itg;
1866 if (pChild->getActive())
1868 // bool bUnder =
1869 pChild->getCtrlsUnder (x, y, clipX, clipY, clipW, clipH, vICL);
1870 // if (bUnder && !vICL.empty())
1871 // return true;
1874 return true;
1878 // ------------------------------------------------------------------------------------------------
1879 bool CInterfaceGroup::getGroupsUnder (sint32 x, sint32 y, sint32 clipX, sint32 clipY, sint32 clipW, sint32 clipH, std::vector<CInterfaceGroup *> &vIGL)
1881 if (!((x >= _XReal) &&
1882 (x < (_XReal + _WReal))&&
1883 (y > _YReal) &&
1884 (y <= (_YReal+ _HReal))))
1885 return false;
1886 // test against current clip
1887 computeCurrentClipContribution(clipX, clipY, clipW, clipH,
1888 clipX, clipY, clipW, clipH);
1890 if (!((x >= clipX) &&
1891 (x < (clipX + clipW))&&
1892 (y > clipY) &&
1893 (y <= (clipY + clipH))))
1894 return false;
1898 // same as draw order: start with parent
1899 std::vector<CViewBase*>::const_iterator itc;
1900 for (itc = _EltOrder.begin(); itc != _EltOrder.end(); itc++)
1902 if ((*itc)->isGroup()) // must be a group
1904 CInterfaceGroup *pIGL = (CInterfaceGroup *) *itc;
1905 if (pIGL != NULL)
1906 if (pIGL->getActive())
1907 if ( ((x) >= pIGL->getXReal()) &&
1908 ((x) < (pIGL->getXReal() + pIGL->getWReal()))&&
1909 ((y) > pIGL->getYReal()) &&
1910 ((y) <= (pIGL->getYReal() + pIGL->getHReal())))
1912 vIGL.push_back (pIGL);
1917 // same as draw order: continue with children
1918 std::vector<CInterfaceGroup*>::const_iterator itg;
1919 for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
1921 CInterfaceGroup *pChild = *itg;
1922 if (pChild->getActive())
1924 // bool bUnder =
1925 pChild->getGroupsUnder (x, y, clipX, clipY, clipW, clipH, vIGL);
1926 // if (bUnder && !vICL.empty())
1927 // return true;
1930 return true;
1934 // ------------------------------------------------------------------------------------------------
1935 void CInterfaceGroup::absoluteToRelative (sint32 &x, sint32 &y)
1937 CInterfaceGroup *curGrp = _Parent;
1938 while (curGrp != NULL)
1940 x = x - curGrp->_XReal;
1941 y = y - curGrp->_YReal;
1942 curGrp = curGrp->_Parent;
1946 // ------------------------------------------------------------------------------------------------
1947 void CInterfaceGroup::computeClipContribution(sint32 &newSciXDest, sint32 &newSciYDest, sint32 &newSciWDest, sint32 &newSciHDest) const
1949 sint32 newSciX = _XReal;
1950 sint32 newSciY = _YReal;
1951 sint32 newSciW = _WReal;
1952 sint32 newSciH = _HReal;
1953 // If there is width size limiter
1954 if (_MaxWReal < _WReal)
1956 if ((_PosRef == Hotspot_TR) || (_PosRef == Hotspot_MR) || (_PosRef == Hotspot_BR))
1957 newSciX = _XReal + _WReal - _MaxWReal;
1958 newSciW = _MaxWReal;
1960 // If there is height size limiter
1961 if (_MaxHReal < _HReal)
1963 if ((_PosRef == Hotspot_TL) || (_PosRef == Hotspot_TM) || (_PosRef == Hotspot_TR))
1964 newSciY = _YReal + _HReal - _MaxHReal;
1965 newSciH = _MaxHReal;
1967 // Don't apply margins because HTML list marker is drawn outside group paragraph inner content.
1968 // Should not be an issue because horizontal scolling not used.
1969 newSciXDest = newSciX/* + _MarginLeft*/;
1970 newSciYDest = newSciY;
1971 newSciWDest = newSciW/* - _MarginLeft*/;
1972 newSciHDest = newSciH;
1975 // ------------------------------------------------------------------------------------------------
1976 void CInterfaceGroup::computeCurrentClipContribution(sint32 oldSciX, sint32 oldSciY, sint32 oldSciW, sint32 oldSciH,
1977 sint32 &newSciXDest, sint32 &newSciYDest, sint32 &newSciWDest, sint32 &newSciHDest) const
1979 sint32 newSciX, newSciY, newSciW, newSciH;
1980 computeClipContribution(newSciX, newSciY, newSciW, newSciH);
1982 // Clip Left
1983 if (newSciX < oldSciX)
1985 newSciW = newSciW - (oldSciX - newSciX);
1986 newSciX = oldSciX;
1988 // Clip Right
1989 if ((newSciX+newSciW) > (oldSciX+oldSciW))
1991 newSciW = newSciW - ((newSciX+newSciW)-(oldSciX+oldSciW));
1993 // Clip Bottom
1994 if (newSciY < oldSciY)
1996 newSciH = newSciH - (oldSciY - newSciY);
1997 newSciY = oldSciY;
1999 // Clip Top
2000 if ((newSciY+newSciH) > (oldSciY+oldSciH))
2002 newSciH = newSciH - ((newSciY+newSciH)-(oldSciY+oldSciH));
2005 // Don't apply margins because HTML list marker is drawn outside group paragraph inner content.
2006 // Should not be an issue because horizontal scolling not used.
2007 newSciXDest = newSciX/* + _MarginLeft*/;
2008 newSciYDest = newSciY;
2009 newSciWDest = newSciW/* - _MarginLeft*/;
2010 newSciHDest = newSciH;
2014 // ------------------------------------------------------------------------------------------------
2015 void CInterfaceGroup::makeNewClip (sint32 &oldSciX, sint32 &oldSciY, sint32 &oldSciW, sint32 &oldSciH)
2017 CViewRenderer &rVR = *CViewRenderer::getInstance();
2018 rVR.getClipWindow (oldSciX, oldSciY, oldSciW, oldSciH);
2020 sint32 newSciX, newSciY, newSciW, newSciH;
2021 computeCurrentClipContribution(oldSciX, oldSciY, oldSciW, oldSciH, newSciX, newSciY, newSciW, newSciH);
2022 rVR.setClipWindow (newSciX, newSciY, newSciW, newSciH);
2025 // ------------------------------------------------------------------------------------------------
2026 void CInterfaceGroup::getClip(sint32 &x, sint32 &y, sint32 &w, sint32 &h) const
2028 CViewRenderer &rVR = *CViewRenderer::getInstance();
2029 uint32 sw, sh;
2030 rVR.getScreenSize(sw, sh);
2031 sint32 sciX = 0, sciY = 0, sciW = sw, sciH =sh;
2032 const CInterfaceGroup *currGroup = this;
2035 currGroup->computeCurrentClipContribution(sciX, sciY, sciW, sciH, sciX, sciY, sciW, sciH);
2036 currGroup = currGroup->_Parent;
2037 } while(currGroup);
2038 x = sciX;
2039 y = sciY;
2040 w = sciW;
2041 h = sciH;
2044 // ------------------------------------------------------------------------------------------------
2045 void CInterfaceGroup::restoreClip (sint32 oldSciX, sint32 oldSciY, sint32 oldSciW, sint32 oldSciH)
2047 CViewRenderer &rVR = *CViewRenderer::getInstance();
2048 rVR.setClipWindow (oldSciX, oldSciY, oldSciW, oldSciH);
2052 // ------------------------------------------------------------------------------------------------
2053 void CInterfaceGroup::launch ()
2055 // launch all elements
2056 vector<CViewBase*>::const_iterator ite;
2057 for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++)
2059 CViewBase *pIE = *ite;
2060 pIE->launch();
2064 // ------------------------------------------------------------------------------------------------
2065 CInterfaceGroup *CInterfaceGroup::getGroup(uint index) const
2067 if (index > _ChildrenGroups.size())
2069 nlwarning("<CInterfaceGroup::getGroup()> bad index;");
2070 return NULL;
2072 return _ChildrenGroups[index];
2075 // ------------------------------------------------------------------------------------------------
2076 void CInterfaceGroup::updateAllLinks()
2078 CCtrlBase::updateAllLinks();
2080 for(std::vector<CInterfaceGroup*>::iterator it = _ChildrenGroups.begin(); it != _ChildrenGroups.end(); ++it)
2082 (*it)->updateAllLinks();
2086 for(std::vector<CCtrlBase*>::iterator it = _Controls.begin(); it != _Controls.end(); ++it)
2088 (*it)->updateAllLinks();
2092 for(std::vector<CViewBase*>::iterator it = _Views.begin(); it != _Views.end(); ++it)
2094 (*it)->updateAllLinks();
2099 // ------------------------------------------------------------------------------------------------
2100 sint32 CInterfaceGroup::getAlpha() const
2102 vector<CViewBase*>::const_iterator itv;
2103 for (itv = _Views.begin(); itv != _Views.end(); itv++)
2105 CViewBase *pVB = *itv;
2106 sint32 a = pVB->getAlpha();
2107 if (a != -1)
2108 return a;
2111 vector<CCtrlBase*>::const_iterator itc;
2112 for (itc = _Controls.begin(); itc != _Controls.end(); itc++)
2114 CCtrlBase *pCB = *itc;
2115 sint32 a = pCB->getAlpha();
2116 if (a != -1)
2117 return a;
2120 vector<CInterfaceGroup*>::const_iterator itg;
2121 for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
2123 CInterfaceGroup *pIG = *itg;
2124 sint32 a = pIG->getAlpha();
2125 if (a != -1)
2126 return a;
2128 return -1;
2131 // ------------------------------------------------------------------------------------------------
2132 void CInterfaceGroup::setAlpha (sint32 a)
2134 vector<CViewBase*>::const_iterator itv;
2135 for (itv = _Views.begin(); itv != _Views.end(); itv++)
2137 CViewBase *pVB = *itv;
2138 pVB->setAlpha(a);
2141 vector<CCtrlBase*>::const_iterator itc;
2142 for (itc = _Controls.begin(); itc != _Controls.end(); itc++)
2144 CCtrlBase *pCB = *itc;
2145 pCB->setAlpha(a);
2148 vector<CInterfaceGroup*>::const_iterator itg;
2149 for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
2151 CInterfaceGroup *pIG = *itg;
2152 pIG->setAlpha(a);
2156 // ------------------------------------------------------------------------------------------------
2157 void CInterfaceGroup::setLeftClickHandler(const std::string &handler)
2159 _AHOnLeftClick = CAHManager::getInstance()->getAH(handler, _AHOnLeftClickParams);
2162 // ------------------------------------------------------------------------------------------------
2163 void CInterfaceGroup::setRightClickHandler(const std::string &handler)
2165 _AHOnRightClick = CAHManager::getInstance()->getAH(handler, _AHOnRightClickParams);
2168 // ------------------------------------------------------------------------------------------------
2169 CInterfaceGroup* CInterfaceGroup::getEnclosingContainer()
2171 CInterfaceGroup *ig = this;
2174 if( ig->isGroupContainer() )
2175 return ig;
2176 ig = ig->getParent();
2178 while( ig != NULL );
2180 return NULL;
2183 // ------------------------------------------------------------------------------------------------
2184 int CInterfaceGroup::luaDumpSize(CLuaState &ls)
2186 const char *funcName = "dumpSize";
2187 CLuaIHM::checkArgCount(ls, funcName, 0);
2188 dumpSize();
2189 return 0;
2192 // ------------------------------------------------------------------------------------------------
2193 int CInterfaceGroup::luaDumpEltsOrder(CLuaState &ls)
2195 const char *funcName = "dumpEltsOrder";
2196 CLuaIHM::checkArgCount(ls, funcName, 0);
2197 dumpEltsOrder();
2198 return 0;
2201 // ------------------------------------------------------------------------------------------------
2202 int CInterfaceGroup::luaDumpGroups(CLuaState &ls)
2204 const char *funcName = "dumpGroups";
2205 CLuaIHM::checkArgCount(ls, funcName, 0);
2206 dumpGroups();
2207 return 0;
2210 // ------------------------------------------------------------------------------------------------
2211 void CInterfaceGroup::dumpGroups() const
2213 nlinfo("Num groups = %d", (int) _ChildrenGroups.size());
2214 for(uint k = 0; k < _ChildrenGroups.size(); ++k)
2216 std::string typeName = "???";
2217 if (_ChildrenGroups[k])
2219 NLGUI::CInterfaceGroup *group = _ChildrenGroups[k];
2220 const type_info &ti = typeid(*group);
2221 typeName = ti.name();
2223 nlinfo("Group %d, name = %s, type=%s", k, _ChildrenGroups[k] ? _ChildrenGroups[k]->getId().c_str() : "???", typeName.c_str());
2227 // ------------------------------------------------------------------------------------------------
2228 void CInterfaceGroup::dumpEltsOrder() const
2230 nlinfo("Num elements = %d, num groups = %d", (int) _EltOrder.size(), _ChildrenGroups.size());
2231 for(uint k = 0; k < _EltOrder.size(); ++k)
2233 CInterfaceElement *el = _EltOrder[k];
2234 if (el)
2236 std::string typeName;
2237 NLGUI::CViewBase *view = _EltOrder[k];
2238 const type_info &ti = typeid(*view);
2239 typeName = ti.name();
2240 nlinfo("Element %d, name = %s, type=%s, x=%d, y=%d, parent_name=%s parentposname=%s xreal=%d, yreal=%d, wreal=%d, hreal=%d",
2241 k, el->getId().c_str(), typeName.c_str(), el->getX(), el->getY(), el->getParent() ? el->getParent()->getId().c_str() : "no parent",
2242 el->getParentPos() ? el->getParentPos()->getId().c_str() : "parent",
2243 (int) el->getXReal(),
2244 (int) el->getYReal(),
2245 (int) el->getWReal(),
2246 (int) el->getHReal()
2249 else
2251 nlinfo("Element %d = NULL", (int) k);
2256 // ------------------------------------------------------------------------------------------------
2257 sint CInterfaceGroup::getInsertionOrder(CViewBase *vb) const
2259 for(uint k = 0; k < _EltOrder.size(); ++k)
2261 if (_EltOrder[k] == vb) return (sint) k;
2263 return -1;
2266 // ------------------------------------------------------------------------------------------------
2267 sint32 CInterfaceGroup::getMaxUsedW() const
2269 sint maxWidth = 0;
2270 for (uint k = 0; k < _EltOrder.size(); ++k)
2272 // Get the child width
2273 sint32 width = _EltOrder[k]->getMaxUsedW()+_EltOrder[k]->getXReal() - getXReal();
2274 if (width > maxWidth)
2275 maxWidth = width;
2277 return maxWidth;
2280 // ------------------------------------------------------------------------------------------------
2281 sint32 CInterfaceGroup::getMinUsedW() const
2283 sint32 minWidth = 0;
2284 for (uint k = 0; k < _EltOrder.size(); ++k)
2286 // Get the child width
2287 sint32 width = _EltOrder[k]->getMinUsedW()+_EltOrder[k]->getXReal() - getXReal();
2288 if (width > minWidth)
2289 minWidth = width;
2291 return minWidth;
2294 // ------------------------------------------------------------------------------------------------
2295 void CInterfaceGroup::clearAllEditBox()
2297 for(uint k = 0; k < _ChildrenGroups.size(); ++k)
2299 if (_ChildrenGroups[k]) _ChildrenGroups[k]->clearAllEditBox();
2303 // ------------------------------------------------------------------------------------------------
2304 void CInterfaceGroup::restoreAllContainersBackupPosition()
2306 for(uint k = 0; k < _ChildrenGroups.size(); ++k)
2308 if (_ChildrenGroups[k]) _ChildrenGroups[k]->restoreAllContainersBackupPosition();
2312 // ------------------------------------------------------------------------------------------------
2313 void CInterfaceGroup::dumpSize(uint depth /*=0*/) const
2315 CViewBase::dumpSize(depth);
2316 for(uint k = 0; k < _ChildrenGroups.size(); ++k)
2318 _ChildrenGroups[k]->dumpSize(depth + 1);
2320 for(uint k = 0; k < _Controls.size(); ++k)
2322 _Controls[k]->dumpSize(depth + 1);
2324 for(uint k = 0; k < _Views.size(); ++k)
2326 _Views[k]->dumpSize(depth + 1);
2330 // ------------------------------------------------------------------------------------------------
2331 void CInterfaceGroup::visit(CInterfaceElementVisitor *visitor)
2333 nlassert(visitor);
2334 for(uint k = 0; k < _ChildrenGroups.size(); ++k)
2336 _ChildrenGroups[k]->visit(visitor);
2338 for(uint k = 0; k < _Controls.size(); ++k)
2340 _Controls[k]->visit(visitor);
2342 for(uint k = 0; k < _Views.size(); ++k)
2344 _Views[k]->visit(visitor);
2346 visitor->visitGroup(this);
2347 CInterfaceElement::visit(visitor);
2350 // ------------------------------------------------------------------------------------------------
2351 void CInterfaceGroup::visitGroupAndChildren( CInterfaceElementVisitor *visitor )
2353 nlassert( visitor != 0 );
2354 for( uint i = 0; i < _ChildrenGroups.size(); i++ )
2356 _ChildrenGroups[ i ]->visitGroupAndChildren( visitor );
2359 visitor->visitGroup( this );
2363 // ------------------------------------------------------------------------------------------------
2365 void CInterfaceGroup::setUseCursor(bool use)
2367 _UseCursor=use;
2370 // ------------------------------------------------------------------------------------------------
2371 void CInterfaceGroup::onFrameUpdateWindowPos(sint dx, sint dy)
2373 // Move me.
2374 _XReal+= dx;
2375 _YReal+= dy;
2377 // Move all my sons.
2378 vector<CViewBase*>::const_iterator ite;
2379 for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++)
2381 CViewBase *pIE = *ite;
2382 pIE->onFrameUpdateWindowPos(dx, dy);
2386 // ------------------------------------------------------------------------------------------------
2387 void CInterfaceGroup::pushLUAEnvTable()
2389 CLuaState *lua= CLuaManager::getInstance().getLuaState();
2390 nlassert(lua);
2392 if(!_LUAEnvTableCreated)
2394 CLuaStackChecker lsc(lua);
2396 // Create a table and assign it in the REGISTRY."__ui_envtable" table, with a userdata ptr
2397 lua->push(IHM_LUA_ENVTABLE);
2398 lua->getTable(LUA_REGISTRYINDEX); // Stack: __ui_envtable
2399 lua->pushLightUserData(IG_UNIQUE_ID(this));
2400 lua->newTable();
2401 lua->setTable(-3); // Stack: __ui_envtable (with .this={})
2402 lua->pop();
2404 // Created!
2405 _LUAEnvTableCreated= true;
2408 // Get the table from registry, and push it on stack
2409 CLuaStackChecker lsc(lua, 1);
2410 lua->push(IHM_LUA_ENVTABLE);
2411 lua->getTable(LUA_REGISTRYINDEX); // __ui_envtable
2412 lua->pushLightUserData(IG_UNIQUE_ID(this));
2413 lua->getTable(-2); // __ui_envtable envtable
2414 lua->remove(-2); // envtable
2415 nlassert(lua->isTable());
2418 // ------------------------------------------------------------------------------------------------
2419 void CInterfaceGroup::deleteLUAEnvTable(bool recurse)
2421 if(_LUAEnvTableCreated)
2423 CLuaState *lua= CLuaManager::getInstance().getLuaState();
2424 nlassert(lua);
2426 // replace simply the table with Nil, letting LUA Garbage collector do the realease stuff
2427 CLuaStackChecker lsc(lua);
2428 lua->push(IHM_LUA_ENVTABLE);
2429 lua->getTable(LUA_REGISTRYINDEX); // __ui_envtable
2430 lua->pushLightUserData(IG_UNIQUE_ID(this)); // NB nico : use some pointer *inside* that object as a unique id (any field but
2431 // the first), instead of using 'this'. 'this' is already used by
2432 // CLuaIHM::pushReflectableOnStack
2433 lua->pushNil();
2434 lua->setTable(-3); // __ui_envtable
2435 lua->pop();
2437 _LUAEnvTableCreated= false;
2439 if (recurse)
2441 for(uint k = 0; k < _ChildrenGroups.size(); ++k)
2443 _ChildrenGroups[k]->deleteLUAEnvTable(true);
2448 // ------------------------------------------------------------------------------------------------
2449 void CInterfaceGroup::setLuaScriptOnDraw(const std::string &script)
2451 _LUAOnDraw= script;
2454 // ------------------------------------------------------------------------------------------------
2455 void CInterfaceGroup::addLuaScriptOnDBChange(const std::string &dbList, const std::string &script)
2457 // remove any existing
2458 removeLuaScriptOnDBChange(dbList);
2460 // create and attach the link
2461 NLMISC::CSmartPtr<CInterfaceLink> newLink= new CInterfaceLink;
2462 _LUAOnDbChange[dbList]= newLink;
2463 // Init and attach to list of untargeted links
2464 std::vector<CInterfaceLink::CTargetInfo> noTargets;
2465 std::vector<CInterfaceLink::CCDBTargetInfo> noCdbTargets;
2466 newLink->init(noTargets, noCdbTargets, NLMISC::toString("depends(%s)", dbList.c_str()), "lua", script, "", this);
2469 // ------------------------------------------------------------------------------------------------
2470 void CInterfaceGroup::removeLuaScriptOnDBChange(const std::string &dbList)
2472 TLUAOnDbChange::iterator it= _LUAOnDbChange.find(dbList);
2473 if(it!=_LUAOnDbChange.end())
2475 nlassert(it->second!=NULL);
2476 // Remove from link of untargeted Links
2477 it->second->uninit();
2478 // erase from map (thus the ptr should be deleted)
2479 _LUAOnDbChange.erase(it);
2483 // ------------------------------------------------------------------------------------------------
2484 void CInterfaceGroup::removeAllLUAOnDbChange()
2486 TLUAOnDbChange::iterator it= _LUAOnDbChange.begin();
2487 for(;it!=_LUAOnDbChange.end();)
2489 // since deleted, must not do it++, but it= begin()
2490 removeLuaScriptOnDBChange(it->first);
2491 it= _LUAOnDbChange.begin();
2495 // ------------------------------------------------------------------------------------------------
2496 int CInterfaceGroup::luaFind(CLuaState &ls)
2498 CLuaIHM::checkArgCount(ls, "CInterfaceGroup::find", 1);
2499 CLuaIHM::checkArgType(ls, "CInterfaceGroup::find", 1, LUA_TSTRING);
2500 std::string id = ls.toString(1);
2501 CInterfaceElement* element = findFromShortId(id);
2502 if (!element)
2504 ls.pushNil();
2506 else
2508 CLuaIHM::pushUIOnStack(ls, element);
2510 return 1;
2513 // ------------------------------------------------------------------------------------------------
2514 CInterfaceElement* CInterfaceGroup::findFromShortId(const std::string &id)
2516 CInterfaceElement* element = NULL;
2517 element = getView(id);
2518 if (!element) element = getCtrl(id);
2519 if (!element) element = getGroup(id);
2520 return element;
2523 // ------------------------------------------------------------------------------------------------
2524 int CInterfaceGroup::luaGetEnclosingContainer(CLuaState &ls)
2526 CLuaIHM::checkArgCount(ls, "CInterfaceGroup::getEnclosingContainer", 0);
2527 CLuaIHM::pushUIOnStack(ls, getEnclosingContainer());
2528 return 1;
2531 // ------------------------------------------------------------------------------------------------
2532 int CInterfaceGroup::luaDeleteLUAEnvTable(CLuaState &ls)
2534 const char *funcName = "deleteLUAenvTable";
2535 CLuaIHM::checkArgCount(ls, funcName, 1);
2536 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TBOOLEAN); // is delete recursive
2537 deleteLUAEnvTable(ls.toBoolean(1));
2538 return 0;
2541 // ------------------------------------------------------------------------------------------------
2542 void CInterfaceGroup::serial(NLMISC::IStream &f)
2544 CCtrlBase::serial(f);
2545 f.serialContPolyPtr(_ChildrenGroups);
2546 f.serialContPolyPtr(_Controls);
2547 f.serialContPolyPtr(_Views);
2548 f.serialContPolyPtr(_EltOrder);
2549 f.serial(_MaxW, _MaxH);
2550 f.serial(_MaxWReal, _MaxHReal);
2551 f.serial(_OffsetX, _OffsetY);
2552 f.serial(_Priority);
2554 nlSerialBitBool(f, _Overlappable);
2555 nlSerialBitBool(f, _ResizeFromChildW);
2556 nlSerialBitBool(f, _ResizeFromChildH);
2557 nlSerialBitBool(f, _Escapable);
2558 nlSerialBitBool(f, _UseCursor);
2559 nlSerialBitBool(f, _IsGroupContainer);
2560 nlSerialBitBool(f, _NeedFrameUpdatePos);
2562 f.serial(_ResizeFromChildWMargin);
2563 f.serial(_ResizeFromChildHMargin);
2564 f.serial(_GroupSizeRef);
2566 serialAH(f, _AHOnActive);
2567 f.serial(_AHOnActiveParams);
2568 serialAH(f, _AHOnDeactive);
2569 f.serial(_AHOnDeactiveParams);
2571 // right & left clicks
2572 serialAH(f, _AHOnLeftClick);
2573 f.serial(_AHOnLeftClickParams);
2574 serialAH(f, _AHOnRightClick);
2575 f.serial(_AHOnRightClickParams);
2577 // enter params.
2578 serialAH(f, _AHOnEnter);
2579 f.serial(_AHOnEnterParams);
2581 // escape AH
2582 serialAH(f, _AHOnEscape);
2583 f.serial(_AHOnEscapeParams);
2586 // ------------------------------------------------------------------------------------------------
2587 CInterfaceElement *CInterfaceGroup::clone()
2589 CInterfaceElement *oldParentSizeMax = _ParentSizeMax;
2590 if (_ParentSizeMax == _Parent)
2592 _ParentSizeMax = NULL;
2594 CInterfaceElement *ret = CCtrlBase::clone();
2595 _ParentSizeMax = oldParentSizeMax;
2596 return ret;
2599 // ------------------------------------------------------------------------------------------------
2600 void CInterfaceGroup::setMaxSizeRef(const std::string &maxSizeRef)
2602 parseMaxSizeRef(maxSizeRef.c_str());
2605 // ------------------------------------------------------------------------------------------------
2606 std::string CInterfaceGroup::getMaxSizeRefAsString() const
2608 return "IMPLEMENT ME!";
2611 void CInterfaceGroup::onWidgetDeleted( CInterfaceElement *e )
2613 for( std::vector< CViewBase* >::iterator itr = _Views.begin(); itr != _Views.end(); ++itr )
2614 (*itr)->onWidgetDeleted( e );
2616 for( std::vector< CCtrlBase* >::iterator itr = _Controls.begin(); itr != _Controls.end(); ++itr )
2617 (*itr)->onWidgetDeleted( e );
2619 for( std::vector< CInterfaceGroup* >::iterator itr = _ChildrenGroups.begin(); itr != _ChildrenGroups.end(); ++itr )
2620 (*itr)->onWidgetDeleted( e );
2623 void CInterfaceGroup::moveBy(sint32 x, sint32 y)
2625 CInterfaceElement::moveBy(x, y);
2627 for(uint i = 0; i < _EltOrder.size(); ++i)
2629 CViewBase *v = _EltOrder[i];
2630 v->updateCoords();
2634 bool CInterfaceGroup::explode()
2636 CInterfaceGroup *p = getParent();
2637 if( p == NULL )
2638 return false;
2640 std::string oldId;
2642 // Reparent children
2643 for(uint i = 0; i < _EltOrder.size(); ++i)
2645 CInterfaceElement *e = _EltOrder[i];
2647 oldId = e->getId();
2649 e->setW(e->getWReal());
2650 e->setH(e->getHReal());
2651 e->setSizeRef("");
2653 e->setParent(p);
2655 e->setParentPos(p);
2656 e->setParentSize(p);
2657 e->alignTo(p);
2659 p->addElement(e);
2660 e->setIdRecurse(e->getShortId());
2662 CWidgetManager::getInstance()->onWidgetMoved(oldId, e->getId());
2665 _EltOrder.clear();
2666 _Views.clear();
2667 _Controls.clear();
2668 _ChildrenGroups.clear();
2670 return true;
2673 void CInterfaceGroup::spanElements()
2675 sint32 minx = std::numeric_limits< sint32 >::max();
2676 sint32 miny = std::numeric_limits< sint32 >::max();
2677 sint32 maxx = std::numeric_limits< sint32 >::min();
2678 sint32 maxy = std::numeric_limits< sint32 >::min();
2680 sint32 tlx, tly, brx, bry;
2682 // Find the min and max coordinates of the elements
2683 for(uint i = 0; i < _EltOrder.size(); ++i)
2685 CViewBase *v = _EltOrder[i];
2687 v->getHSCoords(Hotspot_TL, tlx, tly);
2688 v->getHSCoords(Hotspot_BR, brx, bry);
2690 if (tlx < minx)
2691 minx = tlx;
2692 if (brx > maxx)
2693 maxx = brx;
2694 if (bry < miny)
2695 miny = bry;
2696 if (tly > maxy)
2697 maxy = tly;
2700 // Set the position and the width and height based on these coords
2701 setW(maxx - minx);
2702 setH(maxy - miny);
2703 _WReal = getW();
2704 _HReal = getH();
2705 _XReal = minx;
2706 _YReal = miny;
2709 void CInterfaceGroup::alignElements()
2711 for(uint i = 0; i < _EltOrder.size(); ++i)
2713 CViewBase *v = _EltOrder[i];
2714 v->alignTo(this);