Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / gui / group_menu.cpp
blob116e114aca1b0df0183c028586b2900731cd44b9
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2020 Winch Gate Property Limited
3 //
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) 2014-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/>.
21 #include "stdpch.h"
22 #include "nel/gui/interface_options.h"
23 #include "nel/gui/interface_expr.h"
24 #include "nel/gui/group_menu.h"
25 #include "nel/misc/xml_auto_ptr.h"
26 #include "nel/gui/view_bitmap.h"
27 #include "nel/gui/action_handler.h" // Just for getAllParams
28 #include "nel/gui/lua_ihm.h"
29 #include "nel/misc/i18n.h"
30 #include "nel/gui/widget_manager.h"
31 #include "nel/gui/group_list.h"
32 #include "nel/gui/ctrl_scroll.h"
33 #include "nel/gui/view_pointer_base.h"
36 using namespace NLMISC;
37 using namespace std;
39 #ifdef DEBUG_NEW
40 #define new DEBUG_NEW
41 #endif
43 namespace
45 const std::string ID_MENU_CHECKBOX = "menu_cb";
46 const std::string ID_MENU_SEPARATOR = "menu_separator";
47 const std::string ID_MENU_SUBMENU = "menu_sb";
48 const uint MENU_WIDGET_X = 2;
49 const uint LEFT_MENU_WIDGET_X = 4;
52 namespace NLGUI
55 // ------------------------------------------------------------------------------------------------
56 // CGroupSubMenu
57 // ------------------------------------------------------------------------------------------------
59 // ------------------------------------------------------------------------------------------------
60 bool CViewTextMenu::getGrayed() const
62 return _Grayed;
65 // ------------------------------------------------------------------------------------------------
66 void CViewTextMenu::setGrayed (bool g)
68 _Grayed = g;
71 // ------------------------------------------------------------------------------------------------
72 void CViewTextMenu::setCheckable(bool c)
74 if (!c)
76 _Checkable = false;
77 _CheckBox = NULL;
79 else
81 _Checkable = true;
85 // ------------------------------------------------------------------------------------------------
86 void CViewTextMenu::setChecked(bool c)
88 if (_CheckBox)
90 CInterfaceOptions *pIO = CWidgetManager::getInstance()->getOptions("menu_checkbox");
91 if (!pIO) return;
92 _CheckBox->setTexture(pIO->getValStr(c ? "checked_bitmap" : "unchecked_bitmap"));
94 _Checked = c;
97 // ------------------------------------------------------------------------------------------------
98 sint32 CViewTextMenu::getAlpha() const
100 if (_Grayed)
102 return OldColorGrayed.A;
104 else
106 if (Over)
107 return OldColorOver.A;
108 else
109 return OldColor.A;
113 // ------------------------------------------------------------------------------------------------
114 void CViewTextMenu::setAlpha (sint32 a)
116 OldShadowColor.A = OldColor.A = (uint8)a;
117 OldShadowColorOver.A = OldColorOver.A = (uint8)a;
118 OldShadowColorGrayed.A = OldColorGrayed.A = (uint8)a;
121 // ------------------------------------------------------------------------------------------------
122 // CGroupSubMenu
123 // ------------------------------------------------------------------------------------------------
125 // ------------------------------------------------------------------------------------------------
126 CGroupSubMenu::CGroupSubMenu(const TCtorParam &param)
127 : CGroupSubMenuBase(param)
129 _SelectionView = NULL;
130 _GroupList = NULL;
131 _GroupMenu = NULL;
132 _Selected = -1;
133 _MaxVisibleLine = -1;
134 _ScrollBar = NULL;
137 // ------------------------------------------------------------------------------------------------
138 CGroupSubMenu::~CGroupSubMenu()
140 removeAllUserGroups();
143 // ------------------------------------------------------------------------------------------------
144 sint CGroupSubMenu::getLineFromId(const std::string &id)
146 for (uint k = 0; k < _Lines.size(); ++k)
148 if (_Lines[k].Id == id)
150 return (sint) k;
153 return -1;
156 // ------------------------------------------------------------------------------------------------
157 CGroupSubMenu *CGroupSubMenu::getSubMenu(uint index) const
159 if (index >= _SubMenus.size())
161 nlassert("bad index");
162 return NULL;
164 return _SubMenus[index];
167 // ------------------------------------------------------------------------------------------------
168 void CGroupSubMenu::setSubMenu(uint index, CGroupSubMenu *sub)
170 nlassert(sub != NULL);
171 nlassert(index < _SubMenus.size());
172 sub->setSerializable( false );
174 if (_SubMenus[index] != NULL)
176 // must delete from the group menu (if not found, just delete)
177 if( !_GroupMenu || !_GroupMenu->delGroup(_SubMenus[index]) )
178 delete _SubMenus[index];
179 _SubMenus[index] = NULL;
180 delView(_Lines[index].RightArrow);
183 if (_Lines[index].CheckBox)
184 _Lines[index].RightArrow = createRightArrow(_Lines[index].CheckBox, true);
185 else
186 _Lines[index].RightArrow = createRightArrow(_GroupList, false);
188 sub->_GroupMenu = _GroupMenu;
189 sub->initOptions(this);
190 _GroupMenu->addGroup (sub);
191 sub->_DispType = _GroupMenu->_DispType;
192 _SubMenus[index] = sub;
195 // ------------------------------------------------------------------------------------------------
196 void CGroupSubMenu::initOptions(CInterfaceGroup *parent)
198 // Initialization
199 // me
200 _Parent = _GroupMenu;
201 if (parent == NULL)
203 setParentPos (_GroupMenu);
204 setParentPosRef (Hotspot_TL);
205 setPosRef (Hotspot_TL);
207 else
209 setParentPos (parent);
210 setParentPosRef (Hotspot_BR);
211 setPosRef (Hotspot_BL);
213 _DisplayFrame = true;
214 _ResizeFromChildH = true;
215 _ResizeFromChildW = true;
216 _ResizeFromChildHMargin = 8;
217 _ResizeFromChildWMargin = 8;
218 _ModulateGlobalColor = _GroupMenu->_ModulateGlobalColor;
219 // the selection
220 if (_SelectionView == NULL)
222 _SelectionView = new CViewBitmap(CViewBase::TCtorParam());
223 // CInterfaceManager *pIM = CInterfaceManager::getInstance();
224 // CViewRenderer &rVR = *CViewRenderer::getInstance();
225 _SelectionView->setId( getId() + ":selection" );
226 _SelectionView->setParent (this);
227 _SelectionView->setActive (false);
228 _SelectionView->setTexture ("blank.tga");
229 _SelectionView->setScale (true);
230 _SelectionView->setX (4);
231 _SelectionView->setSizeRef(1); // sizeref on W
232 _SelectionView->setW (-8);
233 _SelectionView->setSerializable( false );
234 addView (_SelectionView, 0);
236 // the group list
237 if (_GroupList == NULL)
239 _GroupList = new CGroupList(CViewBase::TCtorParam());
240 _GroupList->setId( getId() + ":list" );
241 _GroupList->setParent (this);
242 _GroupList->setParentPos (this);
243 _GroupList->setX (4);
244 _GroupList->setY (4);
245 _GroupList->setSpace (_GroupMenu->_Space);
246 _GroupList->setSerializable( false );
247 _GroupList->setResizeFromChildW(true);
248 addGroup (_GroupList);
252 // ------------------------------------------------------------------------------------------------
253 bool CGroupSubMenu::parse (xmlNodePtr cur, CInterfaceGroup *parent)
255 initOptions(parent);
256 // the children
257 while (cur)
259 CViewTextMenu *pV = NULL;
261 CXMLAutoPtr id((const char*) xmlGetProp (cur, (xmlChar*)"id"));
263 if (stricmp((char*)cur->name, "separator") == 0)
265 if (id)
267 addSeparator((const char *) id);
269 else
271 addSeparator();
274 else
275 if (stricmp((char*)cur->name, "action") == 0)
277 string strId, strAh, strParams, strCond, strTexture;
278 string ucstrName;
280 if (id) strId = (const char*)id;
281 CXMLAutoPtr name((const char*) xmlGetProp (cur, (xmlChar*)"name"));
283 if (name)
285 const char *ptrName = (const char*)name;
286 if (NLMISC::startsWith(ptrName, "ui"))
287 ucstrName = CI18N::get(ptrName);
288 else
289 ucstrName = ptrName;
292 CXMLAutoPtr ah((const char*) xmlGetProp (cur, (xmlChar*)"handler"));
293 if (ah) strAh = (const char*)ah;
294 CXMLAutoPtr cond((const char*) xmlGetProp (cur, (xmlChar*)"cond"));
295 if (cond) strCond = (const char*)cond;
296 CXMLAutoPtr params((const char*) xmlGetProp (cur, (xmlChar*)"params"));
297 if (params) strParams = (const char*)params;
298 CXMLAutoPtr strCheckable((const char*) xmlGetProp (cur, (xmlChar*)"checkable"));
299 bool bCheckable = false;
300 if (strCheckable) bCheckable = convertBool (strCheckable);
301 CXMLAutoPtr strChecked((const char*) xmlGetProp (cur, (xmlChar*)"checked"));
302 bool bChecked = false;
303 if (strChecked) bChecked = convertBool (strChecked);
304 bool bFormatted = false;
305 CXMLAutoPtr strFormatted((const char*) xmlGetProp (cur, (xmlChar*)"formatted"));
306 if (strFormatted) bFormatted = convertBool (strFormatted);
308 pV = addLine (ucstrName, strAh, strParams, strId, strCond, strTexture, bCheckable, bChecked, bFormatted);
309 pV->setSerializable( false );
311 CXMLAutoPtr strSelectable((const char*) xmlGetProp (cur, (xmlChar*)"selectable"));
312 bool bSelectable = true;
313 if (strSelectable) bSelectable = convertBool (strSelectable);
314 _Lines.back().Selectable = bSelectable;
317 CXMLAutoPtr grayed((const char*) xmlGetProp (cur, (xmlChar*)"grayed"));
318 bool bGrayed = false;
319 if (grayed) bGrayed = convertBool (grayed);
320 pV->setGrayed(bGrayed);
322 // Is this line has a sub menu ?
323 xmlNodePtr child = cur->children;
324 if (child != NULL)
326 if (_Lines.back().CheckBox)
328 _Lines.back().RightArrow = createRightArrow(_Lines.back().CheckBox, true);
330 else
332 _Lines.back().RightArrow = createRightArrow(_GroupList, false);
334 // and create the sub menu
335 CGroupSubMenu *childMenu = new CGroupSubMenu(CViewText::TCtorParam());
336 childMenu->_GroupMenu = _GroupMenu;
337 childMenu->setSerializable( false );
338 childMenu->parse (child, this);
340 CXMLAutoPtr MVL((const char*) xmlGetProp(cur, (xmlChar*)"max_visible_line"));
341 if (MVL)
343 sint32 maxVisibleLine;
344 fromString((const char*)MVL, maxVisibleLine);
345 childMenu->setMaxVisibleLine(maxVisibleLine);
348 _SubMenus.back() = childMenu;
351 // Add user groups
352 // Left
353 CXMLAutoPtr usergroup((const char*) xmlGetProp (cur, (xmlChar*)"usergroup_l"));
354 if (usergroup)
356 vector< pair<string,string> > vparams;
357 CXMLAutoPtr ugparams((const char*) xmlGetProp (cur, (xmlChar*)"usergroup_params_l"));
358 if (ugparams)
360 IActionHandler::getAllParams((const char*)ugparams, vparams);
363 string completeId = _Parent->getId() + ":" + _Lines[_Lines.size()-1].Id;
364 CInterfaceGroup *pUGLeft = CWidgetManager::getInstance()->getParser()->createGroupInstance((const char*)usergroup, completeId, vparams);
365 if (pUGLeft)
366 setUserGroupLeft((uint)_Lines.size()-1, pUGLeft, true);
368 usergroup = (char*) xmlGetProp (cur, (xmlChar*)"usergroup_r");
369 if (usergroup)
371 vector< pair<string,string> > vparams;
372 CXMLAutoPtr ugparams((const char*) xmlGetProp (cur, (xmlChar*)"usergroup_params_r"));
373 if (ugparams)
375 IActionHandler::getAllParams((const char*)ugparams, vparams);
378 string completeId = _Parent->getId() + ":" + _Lines[_Lines.size()-1].Id;
379 CInterfaceGroup *pUG = CWidgetManager::getInstance()->getParser()->createGroupInstance((const char*)usergroup, completeId, vparams);
380 if (pUG)
381 setUserGroupRight((uint)_Lines.size()-1, pUG, true);
383 // usergroup from simple icon
384 CXMLAutoPtr icon((const char*) xmlGetProp (cur, (xmlChar*)"icon"));
385 if (icon)
387 typedef std::pair<std::string, std::string> TTmplParams;
388 std::vector<TTmplParams> vparams;
389 uint lineIndex = _Lines.size()-1;
390 vparams.push_back(TTmplParams("id", toString("icon%d", lineIndex)));
391 vparams.push_back(TTmplParams("sizeref", ""));
392 vparams.push_back(TTmplParams("icon_texture", (const char*)icon));
393 //vparams.push_back(TTmplParams("icon_color", options.ColorNormal.toString()));
394 string lineId = toString("%s:icon", pV->getId().c_str());
396 CInterfaceGroup *pUG = CWidgetManager::getInstance()->getParser()->createGroupInstance("menu_row_icon", lineId, vparams);
397 if (pUG)
398 setUserGroupLeft((uint)_Lines.size()-1, pUG, true);
401 cur = cur->next;
404 _GroupMenu->addGroup (this);
405 this->_DispType = _GroupMenu->_DispType;
407 return true;
410 // ------------------------------------------------------------------------------------------------
411 CViewBitmap *CGroupSubMenu::createIcon(CInterfaceElement *parentPos, const string &texture)
413 // Add an icon to the line
414 CViewBitmap *pVB = new CViewBitmap(CViewBase::TCtorParam());
415 pVB->setSerializable( false );
416 pVB->setParent (this);
417 pVB->setParentPos (parentPos);
418 pVB->setParentPosRef (Hotspot_ML);
419 pVB->setPosRef (Hotspot_MR);
420 pVB->setTexture(texture);
421 pVB->setModulateGlobalColor(false);
422 pVB->setX (-2);
423 addView (pVB);
424 return pVB;
427 // ------------------------------------------------------------------------------------------------
428 CViewBitmap *CGroupSubMenu::createCheckBox(bool checked)
430 // Put the left arrow to the line
431 CViewBitmap *pVB = new CViewBitmap(CViewBase::TCtorParam());
432 pVB->setSerializable( false );
433 pVB->setParent (this);
434 pVB->setParentPos (_GroupList);
435 pVB->setParentPosRef (Hotspot_BR);
436 pVB->setPosRef (Hotspot_BL);
437 CInterfaceOptions *pIO = CWidgetManager::getInstance()->getOptions("menu_checkbox");
438 if (pIO)
440 pVB->setTexture(pIO->getValStr(checked ? "checked_bitmap" : "unchecked_bitmap"));
442 pVB->setX (MENU_WIDGET_X);
443 pVB->setId (ID_MENU_CHECKBOX); // always rescale to parent in update coords
444 addView (pVB);
445 return pVB;
449 // ------------------------------------------------------------------------------------------------
450 CViewBitmap *CGroupSubMenu::createRightArrow(CInterfaceElement *parentPos, bool center)
452 // Put the left arrow to the line
453 CViewBitmap *pVB = new CViewBitmap(CViewBase::TCtorParam());
454 pVB->setSerializable( false );
455 pVB->setParent (this);
456 pVB->setParentPos (parentPos);
457 if (!center)
459 pVB->setParentPosRef (Hotspot_BR);
460 pVB->setPosRef (Hotspot_BL);
462 else
464 pVB->setParentPosRef (Hotspot_MR);
465 pVB->setPosRef (Hotspot_ML);
467 pVB->setTexture("w_arrow_right_3.tga");
468 pVB->setX (MENU_WIDGET_X);
469 pVB->setId (ID_MENU_SUBMENU); // rescale to parent in update coords if asked (not needed if there's already on the left a checkbox)
470 addView (pVB);
471 return pVB;
474 // ------------------------------------------------------------------------------------------------
475 #define GET_REF_ELM(__index__) \
476 CInterfaceElement *refElm; \
477 sint32 refElmYReal= 0; \
478 sint32 refElmHReal= 0; \
479 refElm = _Lines[__index__].ViewText; \
480 if(refElm) \
482 refElmYReal= refElm->getYReal() - _Lines[__index__].TextDY; \
483 refElmHReal= _Lines[__index__].HReal; \
486 void CGroupSubMenu::updateCoords ()
488 if (_ParentPos == _GroupMenu)
490 // Root Menu
491 setX(_GroupMenu->SpawnMouseX);
492 setY(_GroupMenu->SpawnMouseY);
493 CGroupFrame::updateCoords();
495 CViewRenderer &rVR = *CViewRenderer::getInstance();
496 uint32 screenW, screenH;
497 rVR.getScreenSize(screenW, screenH);
498 if ((_XReal+_WReal) > (sint32)screenW)
499 setX(screenW-_WReal);
500 if (_YReal < 0)
501 setY(_HReal);
503 else
504 // The sub menu may go outside the screen in Y. => clamp it as possible
506 /* X/Y coords have normally been updated before by "parent" sub menus
507 Why? because setSubMenu() is typically called in "parent first" order (or it is exactly what is done in ::parse())
508 => Parent CGroupSubMenu::updateCoords() are called before their sons in CGroupMenu::updateCoords() !!!
509 => No Need to call _SubMenus[RALineNb]->updateCoords() below ! (else would call too much time because of recursion!!)
512 // must udpate correct Real coords
513 CGroupFrame::updateCoords();
515 // get screen size
516 CViewRenderer &rVR = *CViewRenderer::getInstance();
517 uint32 screenW, screenH;
518 rVR.getScreenSize(screenW, screenH);
520 sint32 hReal= getHReal();
521 // If the H is too big, abort.. can't do anything
522 if(hReal<=(sint32)screenH)
524 sint32 yReal= getYReal();
526 // compute the shift to apply to the Y of the sub menu, to respect (as possible) the screen
527 sint32 dyClamp= 0;
528 if(yReal<0)
529 dyClamp= - yReal;
530 if(yReal+hReal>(sint32)screenH)
531 dyClamp= screenH - (yReal+hReal);
532 // change then the Y
533 if(dyClamp!=0)
535 setY(getY()+dyClamp);
536 CGroupFrame::updateCoords();
541 // not yet setuped?
542 if (!_GroupList) return;
544 // get text dy position
545 sint32 textDYPos= 0;
546 textDYPos= -(1+_GroupList->getSpace())/2;
548 // Set the arrows at the right positions (in _Views we have selection and the right arrows)
549 sint32 CBLineNb = 0; // check box
550 sint32 RALineNb = 0; // right arrow
551 uint32 i;
553 sint32 maxUserGroupWidth = 0;
554 // compute max width of user groups, & adapt max height for each line
555 uint k;
557 // update all left user groups to get their width
558 sint32 maxLeftUGWidth = 0;
559 for(k = 0; k < _Lines.size(); ++k)
561 if (_Lines[k].UserGroupLeft)
563 _Lines[k].UserGroupLeft->updateCoords();
564 maxLeftUGWidth = std::max(_Lines[k].UserGroupLeft->getWReal(), maxLeftUGWidth);
568 _GroupList->setX(LEFT_MENU_WIDGET_X + maxLeftUGWidth);
570 // active separators when needed
571 bool activeLineSeen = false;
572 for (i = 0; i < _Lines.size(); ++i)
574 if (_Lines[i].Separator != NULL)
576 if (i == _Lines.size() - 1)
578 _Lines[i].Separator->setActive(false);
579 break;
581 _Lines[i].Separator->setActive(activeLineSeen);
582 activeLineSeen = false;
584 else
586 if (_Lines[i].ViewText && _Lines[i].ViewText->getActive()) activeLineSeen = true;
590 CGroupFrame::updateCoords();
592 if (_MaxVisibleLine > 0 && sint32(_Lines.size())>_MaxVisibleLine)
594 for(k = 0; k < _Lines.size(); ++k)
595 if (_Lines[k].ViewText)
597 // compute max height of widgets on the left of text
598 sint32 widgetMaxH = 0;
599 if (_Lines[k].UserGroupRight) widgetMaxH = _Lines[k].UserGroupRight->getHReal();
600 if (_Lines[k].UserGroupLeft) widgetMaxH = std::max(widgetMaxH, _Lines[k].UserGroupLeft->getHReal());
601 if (_Lines[k].CheckBox) widgetMaxH = std::max(widgetMaxH, _Lines[k].CheckBox->getHReal());
602 if (_Lines[k].RightArrow) widgetMaxH = std::max(widgetMaxH, _Lines[k].RightArrow->getHReal());
603 widgetMaxH = std::max(widgetMaxH, _Lines[k].ViewText->getHReal());
604 _GroupList->setMaxH(widgetMaxH*_MaxVisibleLine+_GroupList->getSpace()*(_MaxVisibleLine-1));
605 if (_ScrollBar == NULL)
607 _ScrollBar = new CCtrlScroll(CViewBase::TCtorParam());
608 _ScrollBar->setParent (this);
609 _ScrollBar->setParentPos (_GroupList);
610 _ScrollBar->setPosRef (Hotspot_BL);
611 _ScrollBar->setParentPosRef (Hotspot_BR);
612 _ScrollBar->setX (4);
613 _ScrollBar->setY (0);
614 _ScrollBar->setW (8);
615 _ScrollBar->setTextureBottomOrLeft ("w_scroll_l123_b.tga");
616 _ScrollBar->setTextureMiddle ("w_scroll_l123_m.tga");
617 _ScrollBar->setTextureTopOrRight ("w_scroll_l123_t.tga");
618 _ScrollBar->setTarget(_GroupList);
619 _SelectionView->setW (-8-8-2);
620 _ScrollBar->setSerializable( false );
621 addCtrl(_ScrollBar);
623 break;
626 else
628 _SelectionView->setW(-8);
632 // *** Setup Text
633 for(k = 0; k < _Lines.size(); ++k)
635 CInterfaceGroup *ig = _Lines[k].UserGroupRight;
636 if (ig)
638 ig->updateCoords();
639 maxUserGroupWidth = std::max(maxUserGroupWidth, ig->getWReal());
641 if (_Lines[k].ViewText)
643 // compute max height of widgets on the left of text
644 sint32 widgetMaxH = 0;
645 if (_Lines[k].UserGroupRight) widgetMaxH = _Lines[k].UserGroupRight->getHReal();
646 if (_Lines[k].UserGroupLeft) widgetMaxH = std::max(widgetMaxH, _Lines[k].UserGroupLeft->getHReal());
647 if (_Lines[k].CheckBox) widgetMaxH = std::max(widgetMaxH, _Lines[k].CheckBox->getHReal());
648 if (_Lines[k].RightArrow) widgetMaxH = std::max(widgetMaxH, _Lines[k].RightArrow->getHReal());
650 sint32 textHReal= _Lines[k].ViewText->getHReal();
651 _Lines[k].HReal= max(widgetMaxH, textHReal);
652 _Lines[k].TextDY= textDYPos;
653 if(widgetMaxH>textHReal)
654 _Lines[k].TextDY+= (widgetMaxH-textHReal) / 2;
659 // *** Update Text Positions
660 // sint32 currX = 0;
661 for(k = 0; k < _Lines.size(); ++k)
663 if (_Lines[k].ViewText)
665 // Setup Y
666 _Lines[k].ViewText->setY(_Lines[k].TextDY);
670 CGroupFrame::updateCoords();
672 // *** Setup SubMenus and CheckBoxes Positions
673 sint32 maxViewW = 0;
674 for (i = 1; i < _Views.size(); ++i)
676 CViewBitmap *pVB = dynamic_cast<CViewBitmap *>(_Views[i]);
677 if (pVB == NULL) continue;
678 if (pVB->getId() == ID_MENU_SUBMENU)
680 // Look for the next line of the menu that contains a sub menu
681 for(;;)
683 nlassert (RALineNb < (sint32)_SubMenus.size());
684 if (_SubMenus[RALineNb] != NULL) // has a check box or an arrow to indicate submenu ?
686 break;
688 ++RALineNb;
691 // get refElm and refElmYReal
692 GET_REF_ELM(RALineNb)
694 // if there is a check box, y is 0
695 if (_Lines[RALineNb].CheckBox || _Lines[RALineNb].UserGroupRight)
697 pVB->setY(0);
698 pVB->setX(MENU_WIDGET_X);
700 else
702 sint32 limY = refElmYReal + refElmHReal/2 - _GroupList->getYReal();
703 // Setup the arrow at the right pos
704 if(_GroupList->getMaxH()>=limY && limY>=0)
706 pVB->setY(refElmYReal + (refElmHReal - pVB->getHReal()) / 2 - _GroupList->getYReal());
707 pVB->setColor(_Lines[RALineNb].ViewText->getColor());
708 pVB->setActive(_Lines[RALineNb].ViewText->getActive());
709 pVB->setX(maxUserGroupWidth + MENU_WIDGET_X);
711 else
713 pVB->setY(0);
714 pVB->setActive(false);
718 if (_GroupMenu->SpawnOnMousePos)
720 _SubMenus[RALineNb]->setParentPos (this);
722 // According to mouse position, set the sub menu on the left or right, begin at top or bottom
723 CViewRenderer &rVR = *CViewRenderer::getInstance();
724 uint32 screenW, screenH;
725 rVR.getScreenSize(screenW, screenH);
726 if ((_GroupMenu->SpawnMouseX <= ((sint32)screenW/2)) && (_GroupMenu->SpawnMouseY <= ((sint32)screenH/2)))
728 _SubMenus[RALineNb]->setParentPosRef(Hotspot_BR);
729 _SubMenus[RALineNb]->setPosRef(Hotspot_BL);
730 _SubMenus[RALineNb]->setY (refElmYReal - _GroupList->getYReal());
732 if ((_GroupMenu->SpawnMouseX <= ((sint32)screenW/2)) && (_GroupMenu->SpawnMouseY > ((sint32)screenH/2)))
734 _SubMenus[RALineNb]->setParentPosRef(Hotspot_TR);
735 _SubMenus[RALineNb]->setPosRef(Hotspot_TL);
736 _SubMenus[RALineNb]->setY (refElmHReal+(refElmYReal - _GroupList->getYReal()) - _GroupList->getHReal());
738 if ((_GroupMenu->SpawnMouseX > ((sint32)screenW/2)) && (_GroupMenu->SpawnMouseY <= ((sint32)screenH/2)))
740 _SubMenus[RALineNb]->setParentPosRef(Hotspot_BL);
741 _SubMenus[RALineNb]->setPosRef(Hotspot_BR);
742 _SubMenus[RALineNb]->setY (refElmYReal - _GroupList->getYReal());
744 if ((_GroupMenu->SpawnMouseX > ((sint32)screenW/2)) && (_GroupMenu->SpawnMouseY > ((sint32)screenH/2)))
746 _SubMenus[RALineNb]->setParentPosRef(Hotspot_TL);
747 _SubMenus[RALineNb]->setPosRef(Hotspot_TR);
748 _SubMenus[RALineNb]->setY (refElmHReal+(refElmYReal - _GroupList->getYReal()) - _GroupList->getHReal());
750 _SubMenus[RALineNb]->setX(0);
752 else
754 // Setup sub menu
755 _SubMenus[RALineNb]->setParentPos (this);
756 _SubMenus[RALineNb]->setParentPosRef (Hotspot_BR);
757 _SubMenus[RALineNb]->setPosRef (Hotspot_BL);
758 _SubMenus[RALineNb]->setY (16+refElmYReal - _GroupList->getYReal() - _SubMenus[RALineNb]->getHReal());
761 ++RALineNb;
763 else if (pVB->getId() == ID_MENU_CHECKBOX)
765 for(;;)
767 nlassert (CBLineNb < (sint32)_SubMenus.size());
768 if (_Lines[CBLineNb].CheckBox != NULL) // has a check box or an arrow to indicate submenu ?
770 break;
772 ++CBLineNb;
774 // Setup the arrow at the right pos
775 if (!_Lines[CBLineNb].UserGroupRight)
777 // get refElm and refElmYReal
778 GET_REF_ELM(CBLineNb)
780 pVB->setX(maxUserGroupWidth + 2 * MENU_WIDGET_X);
782 sint32 limY = refElmYReal + refElmHReal/2 - _GroupList->getYReal();
783 // Setup the arrow at the right pos
784 if(_GroupList->getMaxH()>=limY && limY>=0)
786 pVB->setY(refElmYReal + (refElmHReal - pVB->getHReal()) / 2 - _GroupList->getYReal());
787 pVB->setActive(_Lines[CBLineNb].ViewText->getActive());
789 else
791 pVB->setY(0);
792 pVB->setActive(false);
795 else
797 pVB->setY(0);
798 pVB->setX(MENU_WIDGET_X);
800 pVB->setColor (_Lines[CBLineNb].ViewText->getColor());
802 ++CBLineNb;
805 if (maxViewW<(pVB->getWReal()+pVB->getX())) maxViewW = pVB->getWReal()+pVB->getX();
808 // setup scrollbar position in function of views width
809 if(maxViewW>0 && _ScrollBar)
810 _ScrollBar->setX(4 + maxViewW);
812 // *** Setup user groups positions
813 for(k = 0; k < _Lines.size(); ++k)
815 CInterfaceGroup *igr = _Lines[k].UserGroupRight;
816 CInterfaceGroup *igl = _Lines[k].UserGroupLeft;
817 if (igr || igl)
819 // get refElm and refElmYReal
820 GET_REF_ELM(k)
822 if (refElm)
824 if (igr)
826 igr->setX(MENU_WIDGET_X + maxUserGroupWidth - igr->getWReal());
828 sint32 limY = refElmYReal + refElmHReal/2 - _GroupList->getYReal();
829 if(_GroupList->getMaxH()>=limY && limY>=0)
831 igr->setY(refElmYReal + (refElmHReal - igr->getHReal()) / 2 - _GroupList->getYReal());
832 igr->setActive (refElm->getActive());
834 else
836 igr->setY(0);
837 igr->setActive(false);
841 if (igl)
843 sint32 limY = refElmYReal + refElmHReal/2 - _GroupList->getYReal();
844 if(_GroupList->getMaxH()>=limY && limY>=0)
846 igl->setY(refElmYReal + (refElmHReal - igl->getHReal()) / 2 - this->getYReal());
847 igl->setActive(refElm->getActive());
849 else
851 igl->setY(0);
852 igl->setActive(false);
860 sint32 SepLineNb = 0;
861 // set separator at the right position
862 for (i = 0; i < _ChildrenGroups.size(); ++i)
864 CInterfaceGroup *pIG = dynamic_cast<CInterfaceGroup *>(_ChildrenGroups[i]);
865 if (pIG == NULL) continue;
866 if (pIG->getId() != ID_MENU_SEPARATOR) continue; // is it a separator ?
868 // set good width
869 /*sint32 sw = getW() - _LeftBorder - _RightBorder;
870 sw = std::max(sw, (sint32) 0);
871 pIG->setW(sw);*/
873 // Look for the next line of the menu that contains a separator
874 CInterfaceGroup *sep = NULL;
877 nlassert (SepLineNb < (sint32)_Lines.size());
878 sep = _Lines[SepLineNb].Separator;
879 ++SepLineNb;
881 while (sep == NULL);
883 // Setup the arrow at the right pos
884 pIG->setY (sep->getYReal() - getYReal());
885 pIG->setActive(sep->getActive());
887 CGroupFrame::updateCoords();
889 //_SelectionView->setW (this->getW());
890 _SelectionView->setH (8);
891 _SelectionView->setY (4);
894 if (_Selected != -1 && _Lines[_Selected].ViewText != NULL)
896 CRGBA col= _GroupMenu->_HighLightOver;
898 _SelectionView->setColor (col);
899 _SelectionView->setModulateGlobalColor(getModulateGlobalColor());
901 // get refElm and refElmYReal
902 GET_REF_ELM(_Selected)
904 _SelectionView->setH (refElmHReal);
905 _SelectionView->setY (refElmYReal - this->getYReal());
909 // ------------------------------------------------------------------------------------------------
910 void CGroupSubMenu::checkCoords()
912 if (!_Active) return;
913 if (_GroupMenu == NULL) return;
915 // if the mouse goes out the window, unselect all (because handleEvent may not be called)
916 sint xMouse= CWidgetManager::getInstance()->getPointer()->getX();
917 sint yMouse= CWidgetManager::getInstance()->getPointer()->getY();
918 if (!((xMouse >= _XReal) &&
919 (xMouse < (_XReal + _WReal))&&
920 (yMouse > _YReal) &&
921 (yMouse <= (_YReal+ _HReal))))
922 _Selected= -1;
924 // CViewRenderer &rVR = *CViewRenderer::getInstance();
926 // Highlight (background under the selection)
927 if (_Selected != -1)
929 // display hightlight
930 if(_GroupMenu->_HighLightOver.A > 0)
932 _SelectionView->setActive (true);
933 _SelectionView->invalidateCoords();
935 else
937 _SelectionView->setActive (false);
940 else // no selection
942 _SelectionView->setActive (false);
945 // Text color if grayed or not
946 for (sint32 i = 0; i < (sint32)_Lines.size(); ++i)
948 if (_Lines[i].ViewText)
950 if (_Lines[i].ViewText->getGrayed()) // Colors when the text is grayed
952 _Lines[i].ViewText->setColor (_Lines[i].ViewText->OldColorGrayed);
953 _Lines[i].ViewText->setShadowColor (_Lines[i].ViewText->OldShadowColorGrayed);
955 else
957 if (i == _Selected) // Colors when the text is selected
959 _Lines[i].ViewText->Over = true;
960 _Lines[i].ViewText->setColor (_Lines[i].ViewText->OldColorOver);
961 _Lines[i].ViewText->setShadowColor (_Lines[i].ViewText->OldShadowColorOver);
963 else // Or finally normal colors
965 _Lines[i].ViewText->Over = false;
966 _Lines[i].ViewText->setColor (_Lines[i].ViewText->OldColor);
967 _Lines[i].ViewText->setShadowColor (_Lines[i].ViewText->OldShadowColor);
974 // ------------------------------------------------------------------------------------------------
975 void CGroupSubMenu::draw()
977 if (!_Active) return;
978 if (_GroupMenu == NULL) return;
979 CGroupFrame::draw();
982 // ------------------------------------------------------------------------------------------------
983 bool CGroupSubMenu::handleEvent (const NLGUI::CEventDescriptor &event)
985 if (!_Active)
986 return false;
988 sint32 textDYPos= 0;
989 if(_GroupList)
990 textDYPos= -(1+_GroupList->getSpace())/2;
992 if (event.getType() == NLGUI::CEventDescriptor::mouse)
994 const NLGUI::CEventDescriptorMouse &eventDesc = (const NLGUI::CEventDescriptorMouse &)event;
995 _Selected = -1;
997 // TODO First check sub menus that can be not in the area of this menu
999 if (!((eventDesc.getX() >= _XReal) &&
1000 (eventDesc.getX() < (_XReal + _WReal))&&
1001 (eventDesc.getY() > _YReal) &&
1002 (eventDesc.getY() <= (_YReal+ _HReal))))
1003 return false;
1005 uint32 i = 0;
1006 for (i = 0; i < _Lines.size(); ++i)
1008 if (_Lines[i].Selectable)
1010 // get refElm and refElmYReal
1011 GET_REF_ELM(i)
1013 if (refElm)
1015 if (refElm->getActive() == true)
1016 if ((eventDesc.getY() > refElmYReal) &&
1017 (eventDesc.getY() <= (refElmYReal + refElmHReal + _GroupList->getSpace())))
1019 _Selected = i;
1020 break;
1026 if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftup)
1028 // If a line is selected and the line is not grayed
1029 if ((_Selected != -1) && (!_Lines[i].ViewText->getGrayed()))
1032 CAHManager::getInstance()->runActionHandler ( _Lines[_Selected].AHName,
1033 CWidgetManager::getInstance()->getCtrlLaunchingModal(),
1034 _Lines[_Selected].AHParams );
1036 if (_SubMenus[_Selected] != NULL)
1038 openSubMenu (_Selected);
1040 else
1042 // if the menu hasn't triggered a new modal window, disable it
1043 if (CWidgetManager::getInstance()->getModalWindow() == _GroupMenu)
1045 if(_GroupMenu && _GroupMenu->getCloseSubMenuUsingPopModal())
1046 CWidgetManager::getInstance()->popModalWindow();
1047 else
1048 CWidgetManager::getInstance()->disableModalWindow ();
1054 if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightup)
1056 // If a line is selected and the line is not grayed and has right click action handler
1057 if ((_Selected != -1) && (!_Lines[i].ViewText->getGrayed()) && !_Lines[_Selected].AHRightClick.empty())
1059 CAHManager::getInstance()->runActionHandler ( _Lines[_Selected].AHRightClick,
1060 CWidgetManager::getInstance()->getCtrlLaunchingModal(),
1061 _Lines[_Selected].AHRightClickParams );
1062 return true;
1066 if (event.getType() == NLGUI::CEventDescriptor::mouse)
1068 const NLGUI::CEventDescriptorMouse &eventDesc = (const NLGUI::CEventDescriptorMouse &)event;
1070 if (_GroupList && _ScrollBar)
1072 if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousewheel)
1074 if (isIn(eventDesc.getX(), eventDesc.getY()))
1076 sint32 h = 0;
1077 for (uint32 k = 0; k < _Lines.size(); ++k)
1078 if (_Lines[k].ViewText)
1080 // compute max height of widgets on the left of text
1081 sint32 widgetMaxH = 0;
1082 if (_Lines[k].UserGroupRight) widgetMaxH = _Lines[k].UserGroupRight->getHReal();
1083 if (_Lines[k].UserGroupLeft) widgetMaxH = std::max(widgetMaxH, _Lines[k].UserGroupLeft->getHReal());
1084 if (_Lines[k].CheckBox) widgetMaxH = std::max(widgetMaxH, _Lines[k].CheckBox->getHReal());
1085 if (_Lines[k].RightArrow) widgetMaxH = std::max(widgetMaxH, _Lines[k].RightArrow->getHReal());
1086 widgetMaxH = std::max(widgetMaxH, _Lines[k].ViewText->getHReal());
1087 h = widgetMaxH+_GroupList->getSpace();
1089 if (h == 0) h = 1;
1090 _ScrollBar->moveTargetY(- eventDesc.getWheel() * h);
1092 hideSubMenus();
1094 return true;
1100 return true;
1102 return false;
1105 // ------------------------------------------------------------------------------------------------
1106 CInterfaceElement* CGroupSubMenu::getElement (const std::string &id)
1108 string sTmp = id.substr(0, _GroupMenu->getId().size());
1109 if (sTmp != _GroupMenu->getId()) return NULL;
1111 string sRest = id.substr(_GroupMenu->getId().size()+1, id.size());
1113 // Iterate through the tree to see if sRest is present
1114 CGroupSubMenu *pCurGSM = this;
1115 while (!sRest.empty())
1117 // Get the first element of the sRest
1118 string::size_type posid = sRest.find (":");
1120 if (posid == string::npos) // Is there just one token to test ?
1122 for (uint32 i = 0; i < pCurGSM->_Lines.size(); ++i)
1123 if (sRest == pCurGSM->_Lines[i].Id)
1124 return pCurGSM->_Lines[i].ViewText;
1125 sRest.clear();
1127 else // no a lot of token left
1129 string sTok = sRest.substr (0, posid);
1130 uint32 i = 0;
1131 for (i = 0; i < pCurGSM->_Lines.size(); ++i)
1132 if (sTok == pCurGSM->_Lines[i].Id)
1133 break;
1134 if (i == pCurGSM->_Lines.size())
1135 return NULL;
1137 // No sub-menus
1138 if (pCurGSM->_SubMenus[i] == NULL)
1140 // Get next token
1141 sRest = sRest.substr (posid+1);
1142 posid = sRest.find (":");
1143 if (posid == string::npos)
1144 sTok = sRest;
1145 else
1146 sTok = sRest.substr (0, posid);
1147 // Do we want left or right user group ?
1148 if (pCurGSM->_Lines[i].UserGroupRight)
1150 string sUGid = pCurGSM->_Lines[i].UserGroupRight->getId();
1151 sUGid = sUGid.substr(sUGid.rfind(':')+1,sUGid.size());
1152 if (sUGid == sTok)
1154 CInterfaceElement *pIE = pCurGSM->_Lines[i].UserGroupRight->getElement(id);
1155 return pIE;
1158 if (pCurGSM->_Lines[i].UserGroupLeft)
1160 string sUGid = pCurGSM->_Lines[i].UserGroupLeft->getId();
1161 sUGid = sUGid.substr(sUGid.rfind(':')+1,sUGid.size());
1162 if (sUGid == sTok)
1164 CInterfaceElement *pIE = pCurGSM->_Lines[i].UserGroupLeft->getElement(id);
1165 return pIE;
1169 return NULL;
1171 else
1173 pCurGSM = pCurGSM->_SubMenus[i];
1176 sRest = sRest.substr (posid+1);
1179 return NULL;
1182 // ------------------------------------------------------------------------------------------------
1183 void CGroupSubMenu::addSeparator(const std::string &id)
1185 addSeparatorAtIndex((uint)_Lines.size(), id);
1188 // ------------------------------------------------------------------------------------------------
1189 void CGroupSubMenu::addSeparatorAtIndex(uint index, const std::string &id)
1191 if (index > _Lines.size())
1193 nlwarning("Bad index");
1194 return;
1197 // create the real separator. It may be larger than the group list, this is why we create a separate group
1198 CInterfaceGroup *separator = CWidgetManager::getInstance()->getParser()->createGroupInstance("menu_separator", "", NULL, 0);
1199 if (!separator) return;
1200 separator->setSerializable( false );
1201 separator->setId(ID_MENU_SEPARATOR);
1202 separator->setSerializable( false );
1203 addGroup(separator);
1204 separator->setParent(this);
1205 // create place holder group
1206 CInterfaceGroup *ph = CWidgetManager::getInstance()->getParser()->createGroupInstance("menu_separator_empty", "", NULL, 0);
1207 if (!ph)
1209 delGroup(separator);
1210 return;
1212 _GroupList->addChildAtIndex(ph, index);
1213 SSubMenuEntry tmp;
1214 tmp.Id = id;
1215 tmp.Separator = ph;
1216 tmp.ViewText = NULL;
1217 tmp.CheckBox = NULL;
1218 tmp.RightArrow = NULL;
1219 _Lines.insert(_Lines.begin() + index, tmp);
1220 _SubMenus.insert(_SubMenus.begin() + index, (CGroupSubMenu*)NULL);
1221 _GroupMenu->invalidateCoords();
1225 // ------------------------------------------------------------------------------------------------
1226 CViewTextMenu* CGroupSubMenu::addLine (const std::string &name, const std::string &ah,
1227 const std::string &params, const std::string &id,
1228 const std::string &cond, const std::string &texture,
1229 bool checkable /*= false*/, bool checked /*= false*/, bool formatted /*= false */
1232 SSubMenuEntry tmp;
1234 CViewTextMenu *pV = new CViewTextMenu(CViewBase::TCtorParam());
1237 pV->setCaseMode(_GroupMenu->getCaseMode());
1238 if (formatted)
1240 pV->setMultiLine (true);
1241 pV->setMultiLineMaxWOnly (true);
1242 pV->setTextFormatTaged (name);
1244 else
1246 pV->setText (name);
1248 pV->setColor (_GroupMenu->_Color);
1249 pV->setFontSize (_GroupMenu->_FontSize, _GroupMenu->_FontSizeCoef);
1250 pV->setShadow (_GroupMenu->_Shadow);
1251 pV->setShadowOutline (_GroupMenu->_ShadowOutline);
1252 pV->setCheckable(checkable);
1253 pV->setChecked(checked);
1254 pV->setModulateGlobalColor(_GroupMenu->_ModulateGlobalColor);
1256 pV->OldColor = _GroupMenu->_Color;
1257 pV->OldShadowColor = _GroupMenu->_ShadowColor;
1258 pV->OldColorOver = _GroupMenu->_ColorOver;
1259 pV->OldShadowColorOver = _GroupMenu->_ShadowColorOver;
1260 pV->OldColorGrayed = _GroupMenu->_ColorGrayed;
1261 pV->OldShadowColorGrayed = _GroupMenu->_ShadowColorGrayed;
1263 _GroupList->addChild (pV);
1265 CViewBitmap *checkBox = NULL;
1267 if (checkable)
1269 checkBox = createCheckBox(checked);
1270 checkBox->setTexture(texture);
1271 pV->setCheckBox(checkBox);
1274 CViewBitmap *icon = NULL;
1275 if (!texture.empty())
1277 if (_GroupList->getNumChildren() == 1)
1278 pV->setX(20);
1279 icon = createIcon(pV, texture);
1283 tmp.ViewText = pV;
1284 tmp.Separator = NULL;
1285 tmp.AHName = ah;
1286 tmp.AHParams = params;
1287 tmp.Cond = cond;
1288 tmp.CheckBox = checkBox;
1289 tmp.RightArrow = icon;
1290 if (id.empty())
1291 tmp.Id = NLMISC::toString (_Lines.size());
1292 else
1293 tmp.Id = id;
1295 pV->setId(_GroupMenu->getId()+":"+tmp.Id);
1297 _Lines.push_back (tmp);
1299 // Add an empty sub menu by default
1300 _SubMenus.push_back (NULL);
1302 _GroupMenu->invalidateCoords();
1304 return pV;
1307 CViewTextMenu* CGroupSubMenu::addLineAtIndex(uint index, const std::string &name, const std::string &ah,
1308 const std::string &params, const std::string &id /*=""*/,
1309 const std::string &cond /*=std::string()*/, const std::string &texture,
1310 bool checkable /*= false*/, bool checked /*= false*/, bool formatted /*= false */
1313 if (index > _Lines.size())
1315 nlwarning("Bad index");
1316 return NULL;
1318 SSubMenuEntry tmp;
1319 CViewTextMenu *pV = new CViewTextMenu(CViewBase::TCtorParam());
1320 pV->setSerializable( false );
1323 pV->setCaseMode(_GroupMenu->getCaseMode());
1326 if (formatted)
1328 pV->setMultiLine (true);
1329 pV->setMultiLineMaxWOnly (true);
1330 pV->setTextFormatTaged (name);
1332 else
1334 pV->setText (name);
1337 pV->setColor (_GroupMenu->_Color);
1338 pV->setFontSize (_GroupMenu->_FontSize, _GroupMenu->_FontSizeCoef);
1339 pV->setShadow (_GroupMenu->_Shadow);
1340 pV->setShadowOutline (_GroupMenu->_ShadowOutline);
1341 pV->setCheckable(checkable);
1342 pV->setChecked(checked);
1343 pV->setModulateGlobalColor(_GroupMenu->_ModulateGlobalColor);
1345 pV->OldColor = _GroupMenu->_Color;
1346 pV->OldShadowColor = _GroupMenu->_ShadowColor;
1347 pV->OldColorOver = _GroupMenu->_ColorOver;
1348 pV->OldShadowColorOver = _GroupMenu->_ShadowColorOver;
1349 pV->OldColorGrayed = _GroupMenu->_ColorGrayed;
1350 pV->OldShadowColorGrayed = _GroupMenu->_ShadowColorGrayed;
1352 _GroupList->addChildAtIndex(pV, index);
1354 CViewBitmap *checkBox = NULL;
1355 if (checkable)
1357 checkBox = createCheckBox(checked);
1358 checkBox->setTexture(texture);
1359 pV->setCheckBox(checkBox);
1362 tmp.ViewText = pV;
1363 tmp.Separator = NULL;
1364 tmp.AHName = ah;
1365 tmp.AHParams = params;
1366 tmp.Cond = cond;
1367 tmp.CheckBox = checkBox;
1368 tmp.RightArrow = NULL;
1370 if (id.empty())
1371 tmp.Id = NLMISC::toString (_Lines.size());
1372 else
1373 tmp.Id = id;
1375 pV->setId(getId()+":"+tmp.Id);
1377 _Lines.insert(_Lines.begin() + index, tmp);
1379 // Add an empty sub menu by default
1380 _SubMenus.insert(_SubMenus.begin() + index, (CGroupSubMenu*)NULL);
1382 _GroupMenu->invalidateCoords();
1384 return pV;
1388 // ------------------------------------------------------------------------------------------------
1389 void CGroupSubMenu::removeLine(uint index)
1391 if (index >= _Lines.size())
1393 nlwarning("Bad index");
1394 return;
1396 setUserGroupRight(index, NULL, false); // remove user group
1397 setUserGroupLeft(index, NULL, false); // remove user group
1398 // remove view (right arrow & checkbox)
1399 if (_Lines[index].RightArrow) delView(_Lines[index].RightArrow);
1400 if (_Lines[index].CheckBox) delView(_Lines[index].CheckBox);
1401 if (_Lines[index].Separator)
1403 // remove one separator group
1404 for(uint k = 0; k < _ChildrenGroups.size(); ++k)
1406 if (_ChildrenGroups[k]->getId() == ID_MENU_SEPARATOR)
1408 delGroup(_ChildrenGroups[k]);
1409 break;
1414 _GroupList->setDelOnRemove(index, true);
1415 _GroupList->delChild(index);
1416 _Lines.erase(_Lines.begin() + index);
1418 //invalidate selection
1419 _Selected = -1;
1421 if(_SubMenus[index])
1423 // reset it and his sons (recurs)
1424 _SubMenus[index]->reset();
1425 // then delete it
1426 _GroupMenu->delGroup(_SubMenus[index]);
1428 _SubMenus.erase(_SubMenus.begin() + index);
1429 _GroupMenu->invalidateCoords();
1432 // ------------------------------------------------------------------------------------------------
1433 void CGroupSubMenu::openSubMenu (sint32 nb)
1435 hideSubMenus ();
1436 _SubMenus[nb]->setActive (true);
1439 // ------------------------------------------------------------------------------------------------
1440 void CGroupSubMenu::hideSubMenus ()
1442 for (uint32 i = 0; i < _SubMenus.size(); ++i)
1443 if (_SubMenus[i] != NULL)
1445 _SubMenus[i]->setActive (false);
1446 _SubMenus[i]->hideSubMenus ();
1450 // ------------------------------------------------------------------------------------------------
1451 void CGroupSubMenu::reset()
1453 uint lineCount = (uint)_Lines.size();
1454 for(sint k = lineCount - 1; k >= 0; --k)
1456 removeLine(k);
1461 // ------------------------------------------------------------------------------------------------
1462 void CGroupSubMenu::removeAllUserGroups()
1464 for(uint k = 0; k < _Lines.size(); ++k)
1466 setUserGroupRight(k, NULL, false);
1467 setUserGroupLeft(k, NULL, false);
1471 // ------------------------------------------------------------------------------------------------
1472 CInterfaceGroup *CGroupSubMenu::getUserGroupRight(uint line) const
1474 if (line >= _Lines.size())
1476 nlwarning("bad index");
1477 return NULL;
1479 return _Lines[line].UserGroupRight;
1482 // ------------------------------------------------------------------------------------------------
1483 CInterfaceGroup *CGroupSubMenu::getUserGroupLeft(uint line) const
1485 if (line >= _Lines.size())
1487 nlwarning("bad index");
1488 return NULL;
1490 return _Lines[line].UserGroupLeft;
1493 // ------------------------------------------------------------------------------------------------
1494 void CGroupSubMenu::setUserGroupRight(uint line, CInterfaceGroup *group, bool ownership)
1496 if (line >= _Lines.size())
1498 nlwarning("bad index");
1499 return;
1501 if (group && isChildGroup(group))
1503 nlwarning("Group inserted twice");
1504 return;
1506 if (_Lines[line].UserGroupRight)
1508 delGroup(_Lines[line].UserGroupRight, !_Lines[line].UserGroupRightOwnership);
1510 _Lines[line].UserGroupRight = group;
1511 _Lines[line].UserGroupRightOwnership = ownership;
1512 if (group)
1514 CViewBase *prevElem = _Lines[line].CheckBox ? _Lines[line].CheckBox : _Lines[line].RightArrow;
1515 if (prevElem)
1517 prevElem->setParentPosRef (Hotspot_MR);
1518 prevElem->setPosRef (Hotspot_ML);
1519 prevElem->setParentPos(group);
1520 prevElem->setX(MENU_WIDGET_X);
1521 prevElem->setY(0);
1523 sint insertionOrder;
1524 if (prevElem)
1526 insertionOrder = getInsertionOrder(prevElem);
1528 else
1530 insertionOrder = -1;
1532 addGroup(group, insertionOrder);
1533 group->setParent(this);
1534 group->setParentPos(_GroupList);
1535 group->setParentPosRef (Hotspot_BR);
1536 group->setPosRef (Hotspot_BL);
1538 else
1540 // restore all posref..
1541 CViewBase *prevElem = _Lines[line].CheckBox ? _Lines[line].CheckBox : _Lines[line].RightArrow;
1542 if (prevElem)
1544 prevElem->setParent (this);
1545 prevElem->setParentPos (_GroupList);
1546 prevElem->setParentPosRef (Hotspot_BR);
1547 prevElem->setPosRef (Hotspot_BL);
1548 prevElem->setX (MENU_WIDGET_X);
1551 _GroupMenu->invalidateCoords();
1555 // ------------------------------------------------------------------------------------------------
1556 void CGroupSubMenu::setUserGroupLeft(uint line, CInterfaceGroup *group, bool ownership)
1558 if (line >= _Lines.size())
1560 nlwarning("bad index");
1561 return;
1563 if (group && isChildGroup(group))
1565 nlwarning("Group inserted twice");
1566 return;
1568 if (_Lines[line].UserGroupLeft)
1570 delGroup(_Lines[line].UserGroupLeft, !_Lines[line].UserGroupLeftOwnership);
1572 _Lines[line].UserGroupLeft = group;
1573 _Lines[line].UserGroupLeftOwnership = ownership;
1574 if (group)
1576 addGroup(group);
1577 group->setParent(this);
1578 group->setParentPos(this);
1579 group->setParentPosRef (Hotspot_BL);
1580 group->setPosRef (Hotspot_BL);
1581 group->setX(LEFT_MENU_WIDGET_X);
1584 _GroupMenu->invalidateCoords();
1588 // ------------------------------------------------------------------------------------------------
1589 CGroupSubMenu *CGroupSubMenu::cloneMenu(CGroupSubMenu *appendToMenu, CGroupMenu *newFather, CInterfaceGroup *initGroup /* = NULL */) const
1591 CGroupSubMenu *copyMenu = appendToMenu ? appendToMenu : new CGroupSubMenu(CViewText::TCtorParam());
1592 uint startSize = (uint)copyMenu->_Lines.size();
1593 copyMenu->setSerializable( false );
1594 copyMenu->_GroupMenu = newFather;
1595 copyMenu->initOptions(initGroup);
1596 copyMenu->_Lines.reserve(_Lines.size() + startSize);
1597 copyMenu->_SubMenus.reserve(_SubMenus.size() + startSize);
1598 // copy childrens
1599 for(uint k = 0; k < _Lines.size(); ++k)
1601 if (_Lines[k].Separator)
1603 copyMenu->addSeparator(_Lines[k].Id);
1605 else
1607 std::string texture = std::string();
1608 if(_Lines[k].ViewText->getCheckBox())
1610 texture = _Lines[k].ViewText->getCheckBox()->getTexture();
1612 CViewTextMenu *pV = NULL;
1613 pV = copyMenu->addLine (_Lines[k].ViewText->getText(), _Lines[k].AHName, _Lines[k].AHParams, _Lines[k].Id, _Lines[k].Cond,
1614 texture, _Lines[k].ViewText->getCheckable(), _Lines[k].ViewText->getChecked(), _Lines[k].ViewText->getFormatted ());
1615 copyMenu->_Lines[k].Selectable = _Lines[k].Selectable;
1616 pV->setGrayed(_Lines[k].ViewText->getGrayed());
1619 // sub menu copy if there's one
1620 if (_SubMenus[k] != NULL)
1623 if (copyMenu->_Lines.back().CheckBox)
1625 copyMenu->_Lines.back().RightArrow = copyMenu->createRightArrow(copyMenu->_Lines.back().CheckBox, true);
1627 else
1629 copyMenu->_Lines.back().RightArrow = copyMenu->createRightArrow(copyMenu->_GroupList, false);
1633 // and create the sub menu
1634 copyMenu->_SubMenus[k + startSize] = _SubMenus[k]->cloneMenu(NULL, newFather, copyMenu);
1637 if (!appendToMenu)
1639 newFather->addGroup(copyMenu);
1641 return copyMenu;
1644 // ------------------------------------------------------------------------------------------------
1645 void CGroupSubMenu::setActive(bool state)
1647 // check conditions
1648 for(uint k = 0; k < _Lines.size(); ++k)
1650 if (!_Lines[k].Cond.empty())
1652 CInterfaceExprValue result;
1653 if (CInterfaceExpr::eval(_Lines[k].Cond, result))
1655 if (result.toBool())
1657 _Lines[k].ViewText->setGrayed(!result.getBool());
1663 if(_ScrollBar && _GroupList)
1664 _ScrollBar->setTrackPos(_GroupList->getHReal());
1666 CGroupFrame::setActive(state);
1669 // ------------------------------------------------------------------------------------------------
1670 const std::string CGroupSubMenu::getActionHandler(uint lineIndex) const
1672 if (lineIndex > _Lines.size())
1674 nlwarning("Bad index");
1675 return 0;
1677 return _Lines[lineIndex].AHName;
1680 // ------------------------------------------------------------------------------------------------
1681 const std::string CGroupSubMenu::getActionHandlerParam(uint lineIndex) const
1683 if (lineIndex > _Lines.size())
1685 nlwarning("Bad index");
1686 return 0;
1688 return _Lines[lineIndex].AHParams;
1691 // ------------------------------------------------------------------------------------------------
1692 void CGroupSubMenu::setActionHandler(uint lineIndex, const std::string &ah)
1694 if (lineIndex > _Lines.size())
1696 nlwarning("Bad index");
1697 return;
1699 _Lines[lineIndex].AHName = ah;
1702 // ------------------------------------------------------------------------------------------------
1703 void CGroupSubMenu::setActionHandlerParam(uint lineIndex, const std::string &params)
1705 if (lineIndex > _Lines.size())
1707 nlwarning("Bad index");
1708 return;
1710 _Lines[lineIndex].AHParams = params;
1713 // ------------------------------------------------------------------------------------------------
1714 void CGroupSubMenu::setRightClickHandler(uint lineIndex, const std::string &ah)
1716 if (lineIndex > _Lines.size())
1718 nlwarning("Bad index");
1719 return;
1721 _Lines[lineIndex].AHRightClick = ah;
1724 // ------------------------------------------------------------------------------------------------
1725 void CGroupSubMenu::setRightClickHandlerParam(uint lineIndex, const std::string &params)
1727 if (lineIndex > _Lines.size())
1729 nlwarning("Bad index");
1730 return;
1732 _Lines[lineIndex].AHRightClickParams = params;
1735 // ------------------------------------------------------------------------------------------------
1736 void CGroupSubMenu::setSelectable(uint lineIndex, bool selectable)
1738 if (lineIndex > _Lines.size())
1740 nlwarning("Bad index");
1741 return;
1743 _Lines[lineIndex].Selectable = selectable;
1746 // ------------------------------------------------------------------------------------------------
1747 bool CGroupSubMenu::getSelectable(uint lineIndex) const
1749 if (lineIndex > _Lines.size())
1751 nlwarning("Bad index");
1752 return 0;
1754 return _Lines[lineIndex].Selectable;
1757 // ------------------------------------------------------------------------------------------------
1758 void CGroupSubMenu::setMaxVisibleLine(sint32 mvl)
1760 _MaxVisibleLine = mvl;
1763 // ------------------------------------------------------------------------------------------------
1764 const std::string &CGroupSubMenu::getLineId(uint index)
1766 if(index>=_Lines.size())
1768 static string nullString;
1769 return nullString;
1771 else
1772 return _Lines[index].Id;
1775 // ------------------------------------------------------------------------------------------------
1776 void CGroupSubMenu::setGrayedLine(uint line, bool g)
1778 if(line<_Lines.size())
1780 if (_Lines[line].ViewText)
1782 _Lines[line].ViewText->setGrayed(g);
1787 // ------------------------------------------------------------------------------------------------
1788 void CGroupSubMenu::setHiddenLine(uint line, bool h)
1790 if(line<_Lines.size())
1792 if (_Lines[line].ViewText)
1794 _Lines[line].ViewText->setActive(!h);
1799 // ------------------------------------------------------------------------------------------------
1800 int CGroupSubMenu::luaGetNumLine(CLuaState &ls)
1802 CLuaIHM::checkArgCount(ls, "getNumLine", 0);
1803 ls.push(getNumLine());
1804 return 1;
1807 // ------------------------------------------------------------------------------------------------
1808 int CGroupSubMenu::luaGetSubMenu(CLuaState &ls)
1810 const char *funcName = "getSubMenu";
1811 CLuaIHM::checkArgCount(ls, funcName, 1);
1812 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1813 CLuaIHM::pushUIOnStack(ls, getSubMenu((uint) ls.toInteger(1)));
1814 return 1;
1817 // ------------------------------------------------------------------------------------------------
1818 int CGroupSubMenu::luaAddSubMenu(CLuaState &ls)
1820 const char *funcName = "addSubMenu";
1821 CLuaIHM::checkArgCount(ls, funcName, 1);
1822 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1823 setSubMenu((uint) ls.toInteger(1), new CGroupSubMenu(CViewText::TCtorParam()));
1824 CLuaIHM::pushUIOnStack(ls, getSubMenu((uint) ls.toInteger(1)));
1825 return 1;
1828 // ------------------------------------------------------------------------------------------------
1829 int CGroupSubMenu::luaGetLineId(CLuaState &ls)
1831 const char *funcName = "getLineId";
1832 CLuaIHM::checkArgCount(ls, funcName, 1);
1833 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1834 #ifdef RYZOM_LUA_UCSTRING
1835 ucstring id = getLineId((uint) ls.toInteger(1)); // Compatibility
1836 CLuaIHM::push(ls, id);
1837 #else
1838 std::string id = getLineId((uint)ls.toInteger(1));
1839 ls.push(id);
1840 #endif
1841 return 1;
1844 // ------------------------------------------------------------------------------------------------
1845 int CGroupSubMenu::luaGetLineFromId(CLuaState &ls)
1847 const char *funcName = "getLineFromId";
1848 CLuaIHM::checkArgCount(ls, funcName, 1);
1849 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TSTRING);
1850 ls.push(getLineFromId(ls.toString(1)));
1851 return 1;
1854 // ------------------------------------------------------------------------------------------------
1855 int CGroupSubMenu::luaIsSeparator(CLuaState &ls)
1857 const char *funcName = "isSeparator";
1858 CLuaIHM::checkArgCount(ls, funcName, 1);
1859 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1860 ls.push(isSeparator((uint) ls.toInteger(1)));
1861 return 1;
1864 // ------------------------------------------------------------------------------------------------
1865 int CGroupSubMenu::luaAddLine(CLuaState &ls)
1867 const char *funcName = "addLine";
1868 CLuaIHM::checkArgCount(ls, funcName, 4);
1869 #ifdef RYZOM_LUA_UCSTRING
1870 CLuaIHM::checkArgTypeUCString(ls, funcName, 1);
1871 #else
1872 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TSTRING);
1873 #endif
1874 CLuaIHM::checkArgType(ls, funcName, 2, LUA_TSTRING);
1875 CLuaIHM::checkArgType(ls, funcName, 3, LUA_TSTRING);
1876 CLuaIHM::checkArgType(ls, funcName, 4, LUA_TSTRING);
1877 #ifdef RYZOM_LUA_UCSTRING
1878 ucstring arg1; // Compatibility
1879 nlverify(CLuaIHM::getUCStringOnStack(ls, 1, arg1));
1880 addLine(arg1.toUtf8(), ls.toString(2), ls.toString(3), ls.toString(4));
1881 #else
1882 addLine(ls.toString(1), ls.toString(2), ls.toString(3), ls.toString(4));
1883 #endif
1884 return 0;
1887 // ------------------------------------------------------------------------------------------------
1888 int CGroupSubMenu::luaAddIconLine(CLuaState &ls)
1890 const char *funcName = "addIconLine";
1891 CLuaIHM::checkArgCount(ls, funcName, 5);
1892 #ifdef RYZOM_LUA_UCSTRING
1893 CLuaIHM::checkArgTypeUCString(ls, funcName, 1);
1894 #else
1895 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TSTRING);
1896 #endif
1897 CLuaIHM::checkArgType(ls, funcName, 2, LUA_TSTRING);
1898 CLuaIHM::checkArgType(ls, funcName, 3, LUA_TSTRING);
1899 CLuaIHM::checkArgType(ls, funcName, 4, LUA_TSTRING);
1900 CLuaIHM::checkArgType(ls, funcName, 5, LUA_TSTRING);
1901 #ifdef RYZOM_LUA_UCSTRING
1902 ucstring arg1; // Compatibility
1903 nlverify(CLuaIHM::getUCStringOnStack(ls, 1, arg1));
1904 addLine(arg1.toUtf8(), ls.toString(2), ls.toString(3), ls.toString(4), string(), ls.toString(5));
1905 #else
1906 addLine(ls.toString(1), ls.toString(2), ls.toString(3), ls.toString(4), string(), ls.toString(5));
1907 #endif
1908 return 0;
1911 // ------------------------------------------------------------------------------------------------
1912 int CGroupSubMenu::luaAddLineAtIndex(CLuaState &ls)
1914 const char *funcName = "addLineAtIndex";
1915 CLuaIHM::checkArgCount(ls, funcName, 5);
1916 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1917 #ifdef RYZOM_LUA_UCSTRING
1918 CLuaIHM::checkArgTypeUCString(ls, funcName, 2);
1919 #else
1920 CLuaIHM::checkArgType(ls, funcName, 2, LUA_TSTRING);
1921 #endif
1922 CLuaIHM::checkArgType(ls, funcName, 3, LUA_TSTRING);
1923 CLuaIHM::checkArgType(ls, funcName, 4, LUA_TSTRING);
1924 CLuaIHM::checkArgType(ls, funcName, 5, LUA_TSTRING);
1925 #ifdef RYZOM_LUA_UCSTRING
1926 ucstring arg2;
1927 nlverify(CLuaIHM::getUCStringOnStack(ls, 2, arg2));
1928 addLineAtIndex((uint) ls.toInteger(1), arg2.toUtf8(), ls.toString(3), ls.toString(4), ls.toString(5));
1929 #else
1930 addLineAtIndex((uint)ls.toInteger(1), ls.toString(2), ls.toString(3), ls.toString(4), ls.toString(5));
1931 #endif
1932 return 0;
1935 // ------------------------------------------------------------------------------------------------
1936 int CGroupSubMenu::luaAddSeparator(CLuaState &ls)
1938 CLuaIHM::checkArgCount(ls, "addSeparator", 0);
1939 addSeparator();
1940 return 0;
1943 // ------------------------------------------------------------------------------------------------
1944 int CGroupSubMenu::luaAddSeparatorAtIndex(CLuaState &ls)
1946 const char *funcName = "addSeparatorAtIndex";
1947 CLuaIHM::checkArgCount(ls, funcName, 1);
1948 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1949 addSeparatorAtIndex((uint) ls.toInteger(1));
1950 return 0;
1953 // ------------------------------------------------------------------------------------------------
1954 int CGroupSubMenu::luaRemoveLine(CLuaState &ls)
1956 const char *funcName = "removeLine";
1957 CLuaIHM::checkArgCount(ls, funcName, 1);
1958 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1959 removeLine((uint) ls.toInteger(1));
1960 return 0;
1963 // ------------------------------------------------------------------------------------------------
1964 int CGroupSubMenu::luaSetUserGroupRight(CLuaState &ls)
1966 const char *funcName = "setUserGroupRight";
1967 CLuaIHM::checkArgCount(ls, funcName, 2);
1968 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1969 if (!(CLuaIHM::isUIOnStack(ls, 2) || ls.isNil(2)))
1971 CLuaIHM::fails(ls, "%s : Group required as argument 2", funcName);
1973 CInterfaceElement *el = CLuaIHM::getUIOnStack(ls, 2);
1974 CInterfaceGroup *group = dynamic_cast<CInterfaceGroup *>(el);
1975 if (el && !group)
1977 CLuaIHM::fails(ls, "%s : Group required as argument 2", funcName);
1979 setUserGroupRight((uint) ls.toInteger(1), group, true);
1980 return 0;
1983 // ------------------------------------------------------------------------------------------------
1984 int CGroupSubMenu::luaSetUserGroupLeft(CLuaState &ls)
1986 const char *funcName = "setUserGroupLeft";
1987 CLuaIHM::checkArgCount(ls, funcName, 2);
1988 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1989 if (!(CLuaIHM::isUIOnStack(ls, 2) || ls.isNil(2)))
1991 CLuaIHM::fails(ls, "%s : Group required as argument 2", funcName);
1993 CInterfaceElement *el = CLuaIHM::getUIOnStack(ls, 2);
1994 CInterfaceGroup *group = dynamic_cast<CInterfaceGroup *>(el);
1995 if (el && !group)
1997 CLuaIHM::fails(ls, "%s : Group required as argument 2", funcName);
1999 setUserGroupLeft((uint) ls.toInteger(1), group, true);
2000 return 0;
2004 // ------------------------------------------------------------------------------------------------
2005 int CGroupSubMenu::luaGetUserGroupRight(CLuaState &ls)
2007 const char *funcName = "getUserGroupRight";
2008 CLuaIHM::checkArgCount(ls, funcName, 1);
2009 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
2010 CLuaIHM::pushUIOnStack(ls, getUserGroupRight((uint) ls.toInteger(1)));
2011 return 1;
2015 // ------------------------------------------------------------------------------------------------
2016 int CGroupSubMenu::luaGetUserGroupLeft(CLuaState &ls)
2018 const char *funcName = "getUserGroupLeft";
2019 CLuaIHM::checkArgCount(ls, funcName, 1);
2020 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
2021 CInterfaceElement *pIE = getUserGroupLeft((uint) ls.toInteger(1));
2022 if (pIE)
2024 CLuaIHM::pushUIOnStack(ls, pIE);
2025 return 1;
2027 else return 0;
2030 // ------------------------------------------------------------------------------------------------
2031 int CGroupSubMenu::luaSetMaxVisibleLine(CLuaState &ls)
2033 const char *funcName = "setMaxVisibleLine";
2034 CLuaIHM::checkArgCount(ls, funcName, 1);
2035 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
2036 setMaxVisibleLine((uint) ls.toInteger(1));
2037 return 0;
2040 // ------------------------------------------------------------------------------------------------
2041 int CGroupSubMenu::luaReset(CLuaState &ls)
2043 const char *funcName = "reset";
2044 CLuaIHM::checkArgCount(ls, funcName, 0);
2045 reset();
2046 return 0;
2050 // ------------------------------------------------------------------------------------------------
2051 // CGroupMenu
2052 // ------------------------------------------------------------------------------------------------
2054 NLMISC_REGISTER_OBJECT(CViewBase, CGroupMenu, std::string, "menu");
2056 // ------------------------------------------------------------------------------------------------
2057 CGroupMenu::CGroupMenu(const TCtorParam &param)
2058 :CGroupModal(param)
2060 _Active = false;
2061 _Color = CRGBA::White;
2062 _ColorOver = CRGBA::White;
2063 _ColorGrayed = CRGBA(128, 128, 128, 255);
2064 _ShadowColor = CRGBA::Black;
2065 _ShadowColorOver = CRGBA::Black;
2066 _ShadowColorGrayed = CRGBA::Black;
2067 _HighLightOver.set(128, 0, 0, 255);
2068 _FontSize = 12;
2069 _FontSizeCoef = true;
2070 _Shadow = false;
2071 _ShadowOutline = false;
2072 _ResizeFromChildH = _ResizeFromChildW = true;
2073 _DisplayFrame = false;
2074 _RootMenu = NULL;
2075 _Space = 3;
2076 _CaseMode = CaseUpper;
2077 _Formatted = false;
2080 // ------------------------------------------------------------------------------------------------
2081 CGroupMenu::~CGroupMenu()
2085 std::string CGroupMenu::getProperty( const std::string &name ) const
2087 if( name == "extends" )
2089 return _Extends;
2091 else
2092 if( name == "case_mode" )
2094 uint32 cm = _CaseMode;
2095 return toString( cm );
2097 else
2098 if( name == "color" )
2100 return toString( _Color );
2102 else
2103 if( name == "shadow_color" )
2105 return toString( _ShadowColor );
2107 else
2108 if( name == "color_over" )
2110 return toString( _ColorOver );
2112 else
2113 if( name == "shadow_color_over" )
2115 return toString( _ShadowColorOver );
2117 else
2118 if( name == "highlight_over" )
2120 return toString( _HighLightOver );
2122 else
2123 if( name == "color_grayed" )
2125 return toString( _ColorGrayed );
2127 else
2128 if( name == "shadow_color_grayed" )
2130 return toString( _ShadowColorGrayed );
2132 else
2133 if( name == "space" )
2135 return toString( _Space );
2137 else
2138 if( name == "fontsize" )
2140 return toString( _FontSize );
2142 else
2143 if( name == "shadow" )
2145 return toString( _Shadow );
2147 else
2148 if( name == "shadow_outline" )
2150 return toString( _ShadowOutline );
2152 else
2153 if( name == "formatted" )
2155 return toString( _Formatted );
2157 else
2158 if( name == "max_visible_line" )
2160 if( _RootMenu == NULL )
2161 return "0";
2162 else
2163 return toString( _RootMenu->getMaxVisibleLine() );
2165 else
2166 return CGroupModal::getProperty( name );
2169 void CGroupMenu::setProperty( const std::string &name, const std::string &value )
2171 if( name == "extends" )
2173 _Extends = value;
2174 return;
2176 else
2177 if( name == "case_mode" )
2179 uint32 cm;
2180 if( fromString( value, cm ) )
2181 _CaseMode = (TCaseMode)cm;
2182 return;
2184 else
2185 if( name == "color" )
2187 CRGBA c;
2188 if( fromString( value, c ) )
2189 _Color = c;
2190 return;
2192 else
2193 if( name == "shadow_color" )
2195 CRGBA c;
2196 if( fromString( value, c ) )
2197 _ShadowColor = c;
2198 return;
2200 else
2201 if( name == "color_over" )
2203 CRGBA c;
2204 if( fromString( value, c ) )
2205 _ColorOver = c;
2206 return;
2208 else
2209 if( name == "shadow_color_over" )
2211 CRGBA c;
2212 if( fromString( value, c ) )
2213 _ShadowColorOver = c;
2214 return;
2216 else
2217 if( name == "highlight_over" )
2219 CRGBA c;
2220 if( fromString( value, c ) )
2221 _HighLightOver = c;
2222 return;
2224 else
2225 if( name == "color_grayed" )
2227 CRGBA c;
2228 if( fromString( value, c ) )
2229 _ColorGrayed = c;
2230 return;
2232 else
2233 if( name == "shadow_color_grayed" )
2235 CRGBA c;
2236 if( fromString( value, c ) )
2237 _ShadowColorGrayed = c;
2238 return;
2240 else
2241 if( name == "space" )
2243 uint8 i;
2244 if( fromString( value, i ) )
2245 _Space = i;
2246 return;
2248 else
2249 if( name == "fontsize" )
2251 sint32 i;
2252 if( fromString( value, i ) )
2253 _FontSize = i;
2254 return;
2256 else
2257 if( name == "shadow" )
2259 bool b;
2260 if( fromString( value, b ) )
2261 _Shadow = b;
2262 return;
2264 else
2265 if( name == "shadow_outline" )
2267 bool b;
2268 if( fromString( value, b ) )
2269 _ShadowOutline = b;
2270 return;
2272 else
2273 if( name == "formatted" )
2275 bool b;
2276 if( fromString( value, b ) )
2277 _Formatted = b;
2278 return;
2280 else
2281 if( name == "max_visible_line" )
2283 if( _RootMenu != NULL )
2285 sint32 i;
2286 if( fromString( value, i ) )
2287 _RootMenu->setMaxVisibleLine( i );
2289 return;
2291 else
2292 CGroupModal::setProperty( name, value );
2296 xmlNodePtr CGroupMenu::serialize( xmlNodePtr parentNode, const char *type ) const
2298 xmlNodePtr node = CGroupModal::serialize( parentNode, type );
2299 if( node == NULL )
2300 return NULL;
2302 xmlSetProp( node, BAD_CAST "type", BAD_CAST "menu" );
2303 xmlSetProp( node, BAD_CAST "extends", BAD_CAST _Extends.c_str() );
2304 xmlSetProp( node, BAD_CAST "case_mode", BAD_CAST toString( uint32( _CaseMode ) ).c_str() );
2305 xmlSetProp( node, BAD_CAST "color", BAD_CAST toString( _Color ).c_str() );
2306 xmlSetProp( node, BAD_CAST "shadow_color", BAD_CAST toString( _ShadowColor ).c_str() );
2307 xmlSetProp( node, BAD_CAST "color_over", BAD_CAST toString( _ColorOver ).c_str() );
2308 xmlSetProp( node, BAD_CAST "shadow_color_over", BAD_CAST toString( _ShadowColorOver ).c_str() );
2309 xmlSetProp( node, BAD_CAST "highlight_over", BAD_CAST toString( _HighLightOver ).c_str() );
2310 xmlSetProp( node, BAD_CAST "color_grayed", BAD_CAST toString( _ColorGrayed ).c_str() );
2311 xmlSetProp( node, BAD_CAST "shadow_color_grayed", BAD_CAST toString( _ShadowColorGrayed ).c_str() );
2312 xmlSetProp( node, BAD_CAST "space", BAD_CAST toString( _Space ).c_str() );
2313 xmlSetProp( node, BAD_CAST "fontsize", BAD_CAST toString( _FontSize ).c_str() );
2314 xmlSetProp( node, BAD_CAST "shadow", BAD_CAST toString( _Shadow ).c_str() );
2315 xmlSetProp( node, BAD_CAST "shadow_outline", BAD_CAST toString( _ShadowOutline ).c_str() );
2316 xmlSetProp( node, BAD_CAST "formatted", BAD_CAST toString( _Formatted ).c_str() );
2318 if( _RootMenu == NULL )
2319 xmlSetProp( node, BAD_CAST "max_visible_line", BAD_CAST "0" );
2320 else
2321 xmlSetProp( node, BAD_CAST "max_visible_line",
2322 BAD_CAST toString( _RootMenu->getMaxVisibleLine() ).c_str() );
2324 return NULL;
2327 // ------------------------------------------------------------------------------------------------
2328 bool CGroupMenu::parse (xmlNodePtr in, CInterfaceGroup *parentGroup)
2330 CXMLAutoPtr prop;
2332 _FontSize = 12;
2334 // override source menu options (if there's one)
2335 if (!CGroupModal::parse(in, parentGroup))
2336 return false;
2339 // see if this menu extends another menu
2340 prop= (char*) xmlGetProp( in, (xmlChar*)"extends" );
2341 CGroupSubMenu *gmExtended = NULL;
2342 if (prop)
2344 if( editorMode )
2345 _Extends = std::string( (const char*)prop );
2347 CGroupMenu *gm = dynamic_cast<CGroupMenu *>(CWidgetManager::getInstance()->getElementFromId(prop.str()));
2348 if (!gm)
2350 gm = dynamic_cast<CGroupMenu *>(CWidgetManager::getInstance()->getElementFromId("ui:interface:" + std::string((const char*)prop)));
2352 if (gm)
2354 gmExtended = gm->_RootMenu;
2355 // copy group frame parameters
2356 CGroupFrame::copyOptionFrom(*gm);
2357 // copy basic datas
2358 _Color = gm->_Color;
2359 _ShadowColor = gm->_ShadowColor;
2360 _Shadow = gm->_Shadow;
2361 _ShadowOutline = gm->_ShadowOutline;
2362 _FontSize = gm->_FontSize;
2363 _ColorOver = gm->_ColorOver;
2364 _ShadowColorOver = gm->_ShadowColorOver;
2365 _HighLightOver = gm->_HighLightOver;
2366 _ColorGrayed = gm->_ColorGrayed;
2367 _ShadowColorGrayed = gm->_ShadowColorGrayed;
2368 _Priority = gm->_Priority;
2369 _ModulateGlobalColor = gm->_ModulateGlobalColor;
2370 _Space = gm->_Space;
2371 _CaseMode = gm->_CaseMode;
2373 else
2375 nlwarning("Can't get menu %s or bad type", (const char *) prop);
2380 // Override the modal behaviour because of sub menus
2381 ExitClickOut = true;
2382 ExitClickL = false;
2383 ExitClickR = false;
2384 ExitKeyPushed = true;
2385 _ResizeFromChildH = _ResizeFromChildW = true;
2386 _DisplayFrame = false;
2387 _Active = false;
2388 _Formatted = false;
2390 // text colors
2391 prop= (char*) xmlGetProp( in, (xmlChar*)"color" );
2392 if (prop) _Color = convertColor(prop);
2394 prop = (char*) xmlGetProp( in, (xmlChar*)"case_mode" );
2395 if (prop)
2397 sint32 caseMode;
2398 fromString((const char*)prop, caseMode);
2399 _CaseMode = (TCaseMode)caseMode;
2402 prop= (char*) xmlGetProp( in, (xmlChar*)"shadow_color" );
2403 if (prop) _ShadowColor = convertColor(prop);
2405 prop= (char*) xmlGetProp( in, (xmlChar*)"color_over" );
2406 if (prop) _ColorOver = convertColor(prop);
2408 prop= (char*) xmlGetProp( in, (xmlChar*)"shadow_color_over" );
2409 if (prop) _ShadowColorOver = convertColor(prop);
2411 prop= (char*) xmlGetProp( in, (xmlChar*)"highlight_over" );
2412 if (prop) _HighLightOver = convertColor(prop);
2414 prop= (char*) xmlGetProp( in, (xmlChar*)"color_grayed" );
2415 if (prop) _ColorGrayed = convertColor(prop);
2417 prop= (char*) xmlGetProp( in, (xmlChar*)"shadow_color_grayed" );
2418 if (prop) _ShadowColorGrayed = convertColor(prop);
2420 prop = (char*) xmlGetProp (in, (xmlChar*)"space");
2421 if (prop) fromString((const char*)prop, _Space);
2423 // Text props
2424 prop = (char*) xmlGetProp( in, (xmlChar*)"fontsize" );
2425 if (prop) fromString((const char*)prop, _FontSize);
2427 prop = (char*) xmlGetProp( in, (xmlChar*)"shadow" );
2428 if (prop)
2429 _Shadow = convertBool(prop);
2431 prop = (char*) xmlGetProp( in, (xmlChar*)"shadow_outline" );
2432 if (prop)
2433 _ShadowOutline = convertBool(prop);
2435 prop = (char*) xmlGetProp( in, (xmlChar*)"formatted" );
2436 if (prop)
2437 _Formatted = convertBool(prop);
2440 // Read sons
2441 xmlNodePtr cur;
2442 cur = in->children;
2443 if (_RootMenu != NULL) delete _RootMenu;
2444 _RootMenu = new CGroupSubMenu(CViewText::TCtorParam());
2445 _RootMenu->setId( getId() + ":header" );
2446 _RootMenu->setSerializable( false );
2447 _RootMenu->_GroupMenu = this;
2448 _RootMenu->parse (cur);
2450 prop = (char*) xmlGetProp( in, (xmlChar*)"max_visible_line" );
2451 if (prop)
2453 sint32 maxVisibleLine;
2454 fromString((const char*)prop, maxVisibleLine);
2455 _RootMenu->setMaxVisibleLine(maxVisibleLine);
2458 if (gmExtended)
2460 gmExtended->cloneMenu(_RootMenu, this);
2462 return true;
2465 // ------------------------------------------------------------------------------------------------
2466 void CGroupMenu::recurseDraw(CGroupSubMenu *pSubMenu)
2468 pSubMenu->draw();
2470 // const vector<CInterfaceGroup*> &rGroups = pSubMenu->getGroups();
2472 for (uint32 i = 0; i < pSubMenu->getNumLines(); i++)
2474 CGroupSubMenu *pGSM = pSubMenu->getSubMenu(i);
2475 if (pGSM != NULL)
2477 recurseDraw(pGSM);
2478 CViewRenderer::getInstance()->flush();
2483 // ------------------------------------------------------------------------------------------------
2484 void CGroupMenu::draw ()
2486 if (!_Active) return;
2488 // TEMP TEMP
2489 //CViewRenderer &rVR = *CViewRenderer::getInstance();
2490 //rVR.drawRotFlipBitmap _RenderLayer, (_XReal, _YReal, _WReal, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(255, 0, 0, 255) );
2492 _RootMenu->_Active = true;
2494 if (SpawnOnMousePos)
2495 recurseDraw(_RootMenu);
2496 else
2497 CGroupModal::draw();
2500 // ------------------------------------------------------------------------------------------------
2501 bool CGroupMenu::handleEvent (const NLGUI::CEventDescriptor &event)
2503 if (!_Active)
2504 return false;
2505 return CGroupModal::handleEvent (event);
2508 // ------------------------------------------------------------------------------------------------
2509 CInterfaceElement* CGroupMenu::getElement (const std::string &id)
2511 if (id == getId()) return this;
2512 CInterfaceElement *pIE = _RootMenu->getElement(id);
2513 if (pIE != NULL)
2514 return pIE;
2515 return CGroupModal::getElement(id);
2518 // ------------------------------------------------------------------------------------------------
2519 void CGroupMenu::setActive (bool state)
2521 if (SpawnOnMousePos)
2523 CViewRenderer &rVR = *CViewRenderer::getInstance();
2524 uint32 w,h;
2525 rVR.getScreenSize(w,h);
2526 setW(w);
2527 setH(h);
2528 setX(0);
2529 setY(0);
2530 _ResizeFromChildH = _ResizeFromChildW = false;
2531 _RootMenu->_PosRef = Hotspot_TL;
2532 _RootMenu->_ParentPosRef = Hotspot_BL;
2535 CGroupFrame::setActive (state);
2537 // must recompute now the pos of the menu
2538 uint32 i;
2539 for (i = 0; i < _ChildrenGroups.size(); ++i)
2541 _ChildrenGroups[i]->setActive (true);
2544 CGroupModal::updateCoords();
2546 // hide sub menus
2547 _RootMenu->hideSubMenus();
2550 // ------------------------------------------------------------------------------------------------
2551 bool CGroupSubMenu::isSeparator(uint i) const
2553 if (i >= _SubMenus.size())
2555 nlassert("bad index");
2556 return false;
2558 return _Lines[i].Separator != NULL;
2560 // ------------------------------------------------------------------------------------------------
2561 bool CGroupMenu::isWindowUnder (sint32 x, sint32 y)
2563 for (uint32 i = 0; i < _ChildrenGroups.size(); ++i)
2564 if (_ChildrenGroups[i]->getActive ())
2565 if (_ChildrenGroups[i]->isWindowUnder(x, y))
2566 return true;
2568 return false;
2571 // ------------------------------------------------------------------------------------------------
2572 void CGroupMenu::addLine(const std::string &name, const std::string &ah, const std::string &params,
2573 const std::string &id /* = std::string()*/,
2574 const std::string &cond /*= std::string()*/, const std::string &texture,
2575 bool checkable /*= false*/, bool checked /*= false*/
2578 if (_RootMenu == NULL)
2580 _RootMenu = new CGroupSubMenu(CViewText::TCtorParam());
2581 _RootMenu->_GroupMenu = this;
2582 _RootMenu->setSerializable( false );
2583 addGroup (_RootMenu);
2585 _RootMenu->addLine (name, ah, params, id, cond, texture, checkable, checked, _Formatted);
2587 // ------------------------------------------------------------------------------------------------
2588 void CGroupMenu::addLineAtIndex(uint index, const std::string &name, const std::string &ah,
2589 const std::string &params, const std::string &id /*=std::string()*/,
2590 const std::string &cond /*=std::string()*/, const std::string &texture,
2591 bool checkable /*=false*/, bool checked /*=false*/)
2593 if (_RootMenu == NULL)
2595 _RootMenu = new CGroupSubMenu(CViewText::TCtorParam());
2596 _RootMenu->_GroupMenu = this;
2597 _RootMenu->setSerializable( false );
2598 addGroup (_RootMenu);
2600 _RootMenu->addLineAtIndex(index, name, ah, params, id, cond, texture, checkable, checked, _Formatted);
2604 // ------------------------------------------------------------------------------------------------
2605 void CGroupMenu::reset ()
2607 if ( _RootMenu )
2609 _RootMenu->reset();
2610 invalidateCoords();
2614 // ------------------------------------------------------------------------------------------------
2615 void CGroupMenu::setMinW(sint32 minW)
2617 if ( _RootMenu )
2619 _RootMenu->_GroupList->setMinW(minW-_RootMenu->getResizeFromChildWMargin());
2620 _RootMenu->_GroupList->setW(minW-_RootMenu->getResizeFromChildWMargin());
2621 _RootMenu->setW(minW-_RootMenu->getResizeFromChildWMargin());
2625 // ------------------------------------------------------------------------------------------------
2626 void CGroupMenu::setMinH(sint32 minH)
2628 if ( _RootMenu )
2630 _RootMenu->_GroupList->setMinH(minH-_RootMenu->getResizeFromChildHMargin());
2631 _RootMenu->_GroupList->setH(minH-_RootMenu->getResizeFromChildHMargin());
2632 _RootMenu->setH(minH-_RootMenu->getResizeFromChildHMargin());
2636 // ------------------------------------------------------------------------------------------------
2637 void CGroupMenu::setGrayedLine(uint line, bool g)
2639 if ( _RootMenu )
2641 _RootMenu->setGrayedLine(line, g);
2645 // ------------------------------------------------------------------------------------------------
2646 void CGroupMenu::setFontSize(uint fontSize, bool coef)
2648 _FontSize = fontSize;
2649 _FontSizeCoef = coef;
2652 // ------------------------------------------------------------------------------------------------
2653 uint CGroupMenu::getNumLine() const
2655 return _RootMenu ? _RootMenu->getNumLine() : 0;
2658 // ------------------------------------------------------------------------------------------------
2659 void CGroupMenu::deleteLine(uint index)
2661 if (index > getNumLine())
2663 nlwarning("bad index");
2664 return;
2666 _RootMenu->removeLine(index);
2669 // ------------------------------------------------------------------------------------------------
2670 const std::string CGroupMenu::getActionHandler(uint lineIndex) const
2672 return _RootMenu ? _RootMenu->getActionHandler(lineIndex) : "";
2675 // ------------------------------------------------------------------------------------------------
2676 const std::string CGroupMenu::getActionHandlerParam(uint lineIndex) const
2678 return _RootMenu ? _RootMenu->getActionHandlerParam(lineIndex) : "";
2681 // ------------------------------------------------------------------------------------------------
2682 void CGroupMenu::setActionHandler(uint lineIndex, const std::string &ah)
2684 if (_RootMenu)
2685 _RootMenu->setActionHandler(lineIndex, ah);
2688 // ------------------------------------------------------------------------------------------------
2689 void CGroupMenu::setActionHandlerParam(uint lineIndex, const std::string &params)
2691 if (_RootMenu)
2692 _RootMenu->setActionHandlerParam(lineIndex, params);
2695 // ------------------------------------------------------------------------------------------------
2696 void CGroupMenu::setRightClickHandler(uint lineIndex, const std::string &ah)
2698 if (_RootMenu)
2699 _RootMenu->setRightClickHandler(lineIndex, ah);
2702 // ------------------------------------------------------------------------------------------------
2703 void CGroupMenu::setRightClickHandlerParam(uint lineIndex, const std::string &params)
2705 if (_RootMenu)
2706 _RootMenu->setRightClickHandlerParam(lineIndex, params);
2709 // ------------------------------------------------------------------------------------------------
2710 void CGroupMenu::setUserGroupRight(uint line, CInterfaceGroup *gr, bool ownerShip /*=true*/)
2712 if (_RootMenu)
2714 _RootMenu->setUserGroupRight(line, gr, ownerShip);
2718 // ------------------------------------------------------------------------------------------------
2719 void CGroupMenu::setUserGroupLeft(uint line, CInterfaceGroup *gr, bool ownerShip /*=true*/)
2721 if (_RootMenu)
2723 _RootMenu->setUserGroupLeft(line, gr, ownerShip);
2727 // ------------------------------------------------------------------------------------------------
2728 int CGroupMenu::luaGetRootMenu(CLuaState &ls)
2730 CLuaIHM::checkArgCount(ls, "getRootMenu", 0);
2731 CLuaIHM::pushUIOnStack(ls, getRootMenu());
2732 return 1;
2735 // ------------------------------------------------------------------------------------------------
2736 int CGroupMenu::luaSetMinW(CLuaState &ls)
2738 const char *funcName = "setMinW";
2739 CLuaIHM::checkArgCount(ls, funcName, 1);
2740 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
2741 setMinW((sint32) ls.toInteger(1));
2742 return 0;