Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / src / gui / group_menu.cpp
blob41c153c36a892bfe40c514a502c08e29f800a601
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 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);
384 cur = cur->next;
387 _GroupMenu->addGroup (this);
388 this->_DispType = _GroupMenu->_DispType;
390 return true;
393 // ------------------------------------------------------------------------------------------------
394 CViewBitmap *CGroupSubMenu::createIcon(CInterfaceElement *parentPos, const string &texture)
396 // Add an icon to the line
397 CViewBitmap *pVB = new CViewBitmap(CViewBase::TCtorParam());
398 pVB->setSerializable( false );
399 pVB->setParent (this);
400 pVB->setParentPos (parentPos);
401 pVB->setParentPosRef (Hotspot_ML);
402 pVB->setPosRef (Hotspot_MR);
403 pVB->setTexture(texture);
404 pVB->setModulateGlobalColor(false);
405 pVB->setX (-2);
406 addView (pVB);
407 return pVB;
410 // ------------------------------------------------------------------------------------------------
411 CViewBitmap *CGroupSubMenu::createCheckBox(bool checked)
413 // Put the left arrow to the line
414 CViewBitmap *pVB = new CViewBitmap(CViewBase::TCtorParam());
415 pVB->setSerializable( false );
416 pVB->setParent (this);
417 pVB->setParentPos (_GroupList);
418 pVB->setParentPosRef (Hotspot_BR);
419 pVB->setPosRef (Hotspot_BL);
420 CInterfaceOptions *pIO = CWidgetManager::getInstance()->getOptions("menu_checkbox");
421 if (pIO)
423 pVB->setTexture(pIO->getValStr(checked ? "checked_bitmap" : "unchecked_bitmap"));
425 pVB->setX (MENU_WIDGET_X);
426 pVB->setId (ID_MENU_CHECKBOX); // always rescale to parent in update coords
427 addView (pVB);
428 return pVB;
432 // ------------------------------------------------------------------------------------------------
433 CViewBitmap *CGroupSubMenu::createRightArrow(CInterfaceElement *parentPos, bool center)
435 // Put the left arrow to the line
436 CViewBitmap *pVB = new CViewBitmap(CViewBase::TCtorParam());
437 pVB->setSerializable( false );
438 pVB->setParent (this);
439 pVB->setParentPos (parentPos);
440 if (!center)
442 pVB->setParentPosRef (Hotspot_BR);
443 pVB->setPosRef (Hotspot_BL);
445 else
447 pVB->setParentPosRef (Hotspot_MR);
448 pVB->setPosRef (Hotspot_ML);
450 pVB->setTexture("w_arrow_right_3.tga");
451 pVB->setX (MENU_WIDGET_X);
452 pVB->setId (ID_MENU_SUBMENU); // rescale to parent in update coords if asked (not needed if there's already on the left a checkbox)
453 addView (pVB);
454 return pVB;
457 // ------------------------------------------------------------------------------------------------
458 #define GET_REF_ELM(__index__) \
459 CInterfaceElement *refElm; \
460 sint32 refElmYReal= 0; \
461 sint32 refElmHReal= 0; \
462 refElm = _Lines[__index__].ViewText; \
463 if(refElm) \
465 refElmYReal= refElm->getYReal() - _Lines[__index__].TextDY; \
466 refElmHReal= _Lines[__index__].HReal; \
469 void CGroupSubMenu::updateCoords ()
471 if (_ParentPos == _GroupMenu)
473 // Root Menu
474 setX(_GroupMenu->SpawnMouseX);
475 setY(_GroupMenu->SpawnMouseY);
476 CGroupFrame::updateCoords();
478 CViewRenderer &rVR = *CViewRenderer::getInstance();
479 uint32 screenW, screenH;
480 rVR.getScreenSize(screenW, screenH);
481 if ((_XReal+_WReal) > (sint32)screenW)
482 setX(screenW-_WReal);
483 if (_YReal < 0)
484 setY(_HReal);
486 else
487 // The sub menu may go outside the screen in Y. => clamp it as possible
489 /* X/Y coords have normally been updated before by "parent" sub menus
490 Why? because setSubMenu() is typically called in "parent first" order (or it is exactly what is done in ::parse())
491 => Parent CGroupSubMenu::updateCoords() are called before their sons in CGroupMenu::updateCoords() !!!
492 => No Need to call _SubMenus[RALineNb]->updateCoords() below ! (else would call too much time because of recursion!!)
495 // must udpate correct Real coords
496 CGroupFrame::updateCoords();
498 // get screen size
499 CViewRenderer &rVR = *CViewRenderer::getInstance();
500 uint32 screenW, screenH;
501 rVR.getScreenSize(screenW, screenH);
503 sint32 hReal= getHReal();
504 // If the H is too big, abort.. can't do anything
505 if(hReal<=(sint32)screenH)
507 sint32 yReal= getYReal();
509 // compute the shift to apply to the Y of the sub menu, to respect (as possible) the screen
510 sint32 dyClamp= 0;
511 if(yReal<0)
512 dyClamp= - yReal;
513 if(yReal+hReal>(sint32)screenH)
514 dyClamp= screenH - (yReal+hReal);
515 // change then the Y
516 if(dyClamp!=0)
518 setY(getY()+dyClamp);
519 CGroupFrame::updateCoords();
524 // not yet setuped?
525 if (!_GroupList) return;
527 // get text dy position
528 sint32 textDYPos= 0;
529 textDYPos= -(1+_GroupList->getSpace())/2;
531 // Set the arrows at the right positions (in _Views we have selection and the right arrows)
532 sint32 CBLineNb = 0; // check box
533 sint32 RALineNb = 0; // right arrow
534 uint32 i;
536 sint32 maxUserGroupWidth = 0;
537 // compute max width of user groups, & adapt max height for each line
538 uint k;
540 // update all left user groups to get their width
541 sint32 maxLeftUGWidth = 0;
542 for(k = 0; k < _Lines.size(); ++k)
544 if (_Lines[k].UserGroupLeft)
546 _Lines[k].UserGroupLeft->updateCoords();
547 maxLeftUGWidth = std::max(_Lines[k].UserGroupLeft->getWReal(), maxLeftUGWidth);
551 _GroupList->setX(LEFT_MENU_WIDGET_X + maxLeftUGWidth);
553 // active separators when needed
554 bool activeLineSeen = false;
555 for (i = 0; i < _Lines.size(); ++i)
557 if (_Lines[i].Separator != NULL)
559 if (i == _Lines.size() - 1)
561 _Lines[i].Separator->setActive(false);
562 break;
564 _Lines[i].Separator->setActive(activeLineSeen);
565 activeLineSeen = false;
567 else
569 if (_Lines[i].ViewText && _Lines[i].ViewText->getActive()) activeLineSeen = true;
573 CGroupFrame::updateCoords();
575 bool mustUpdate = false;
577 if (_MaxVisibleLine > 0 && sint32(_Lines.size())>_MaxVisibleLine)
579 for(k = 0; k < _Lines.size(); ++k)
580 if (_Lines[k].ViewText)
582 // compute max height of widgets on the left of text
583 sint32 widgetMaxH = 0;
584 if (_Lines[k].UserGroupRight) widgetMaxH = _Lines[k].UserGroupRight->getHReal();
585 if (_Lines[k].UserGroupLeft) widgetMaxH = std::max(widgetMaxH, _Lines[k].UserGroupLeft->getHReal());
586 if (_Lines[k].CheckBox) widgetMaxH = std::max(widgetMaxH, _Lines[k].CheckBox->getHReal());
587 if (_Lines[k].RightArrow) widgetMaxH = std::max(widgetMaxH, _Lines[k].RightArrow->getHReal());
588 widgetMaxH = std::max(widgetMaxH, _Lines[k].ViewText->getHReal());
589 _GroupList->setMaxH(widgetMaxH*_MaxVisibleLine+_GroupList->getSpace()*(_MaxVisibleLine-1));
590 if (_ScrollBar == NULL)
592 _ScrollBar = new CCtrlScroll(CViewBase::TCtorParam());
593 _ScrollBar->setParent (this);
594 _ScrollBar->setParentPos (_GroupList);
595 _ScrollBar->setPosRef (Hotspot_BL);
596 _ScrollBar->setParentPosRef (Hotspot_BR);
597 _ScrollBar->setX (4);
598 _ScrollBar->setY (0);
599 _ScrollBar->setW (8);
600 _ScrollBar->setTextureBottomOrLeft ("w_scroll_l123_b.tga");
601 _ScrollBar->setTextureMiddle ("w_scroll_l123_m.tga");
602 _ScrollBar->setTextureTopOrRight ("w_scroll_l123_t.tga");
603 _ScrollBar->setTarget(_GroupList);
604 _SelectionView->setW (-8-8-2);
605 _ScrollBar->setSerializable( false );
606 addCtrl(_ScrollBar);
607 mustUpdate = true;
609 break;
612 else
614 _SelectionView->setW(-8);
618 // *** Setup Text
619 for(k = 0; k < _Lines.size(); ++k)
621 CInterfaceGroup *ig = _Lines[k].UserGroupRight;
622 if (ig)
624 ig->updateCoords();
625 maxUserGroupWidth = std::max(maxUserGroupWidth, ig->getWReal());
627 if (_Lines[k].ViewText)
629 // compute max height of widgets on the left of text
630 sint32 widgetMaxH = 0;
631 if (_Lines[k].UserGroupRight) widgetMaxH = _Lines[k].UserGroupRight->getHReal();
632 if (_Lines[k].UserGroupLeft) widgetMaxH = std::max(widgetMaxH, _Lines[k].UserGroupLeft->getHReal());
633 if (_Lines[k].CheckBox) widgetMaxH = std::max(widgetMaxH, _Lines[k].CheckBox->getHReal());
634 if (_Lines[k].RightArrow) widgetMaxH = std::max(widgetMaxH, _Lines[k].RightArrow->getHReal());
636 sint32 textHReal= _Lines[k].ViewText->getHReal();
637 _Lines[k].HReal= max(widgetMaxH, textHReal);
638 _Lines[k].TextDY= textDYPos;
639 if(widgetMaxH>textHReal)
640 _Lines[k].TextDY+= (widgetMaxH-textHReal) / 2;
645 // *** Update Text Positions
646 // sint32 currX = 0;
647 for(k = 0; k < _Lines.size(); ++k)
649 if (_Lines[k].ViewText)
651 // Setup Y
652 _Lines[k].ViewText->setY(_Lines[k].TextDY);
658 if (mustUpdate)
660 CGroupFrame::updateCoords();
664 // *** Setup SubMenus and CheckBoxes Positions
665 sint32 maxViewW = 0;
666 for (i = 1; i < _Views.size(); ++i)
668 CViewBitmap *pVB = dynamic_cast<CViewBitmap *>(_Views[i]);
669 if (pVB == NULL) continue;
670 if (pVB->getId() == ID_MENU_SUBMENU)
672 // Look for the next line of the menu that contains a sub menu
673 for(;;)
675 nlassert (RALineNb < (sint32)_SubMenus.size());
676 if (_SubMenus[RALineNb] != NULL) // has a check box or an arrow to indicate submenu ?
678 break;
680 ++RALineNb;
683 // get refElm and refElmYReal
684 GET_REF_ELM(RALineNb)
686 // if there is a check box, y is 0
687 if (_Lines[RALineNb].CheckBox || _Lines[RALineNb].UserGroupRight)
689 pVB->setY(0);
690 pVB->setX(MENU_WIDGET_X);
692 else
694 sint32 limY = refElmYReal + refElmHReal/2 - _GroupList->getYReal();
695 // Setup the arrow at the right pos
696 if(_GroupList->getMaxH()>=limY && limY>=0)
698 pVB->setY(refElmYReal + (refElmHReal - pVB->getHReal()) / 2 - _GroupList->getYReal());
699 pVB->setColor(_Lines[RALineNb].ViewText->getColor());
700 pVB->setActive(_Lines[RALineNb].ViewText->getActive());
701 pVB->setX(maxUserGroupWidth + MENU_WIDGET_X);
703 else
705 pVB->setY(0);
706 pVB->setActive(false);
710 if (_GroupMenu->SpawnOnMousePos)
712 _SubMenus[RALineNb]->setParentPos (this);
714 // According to mouse position, set the sub menu on the left or right, begin at top or bottom
715 CViewRenderer &rVR = *CViewRenderer::getInstance();
716 uint32 screenW, screenH;
717 rVR.getScreenSize(screenW, screenH);
718 if ((_GroupMenu->SpawnMouseX <= ((sint32)screenW/2)) && (_GroupMenu->SpawnMouseY <= ((sint32)screenH/2)))
720 _SubMenus[RALineNb]->setParentPosRef(Hotspot_BR);
721 _SubMenus[RALineNb]->setPosRef(Hotspot_BL);
722 _SubMenus[RALineNb]->setY (refElmYReal - _GroupList->getYReal());
724 if ((_GroupMenu->SpawnMouseX <= ((sint32)screenW/2)) && (_GroupMenu->SpawnMouseY > ((sint32)screenH/2)))
726 _SubMenus[RALineNb]->setParentPosRef(Hotspot_TR);
727 _SubMenus[RALineNb]->setPosRef(Hotspot_TL);
728 _SubMenus[RALineNb]->setY (refElmHReal+(refElmYReal - _GroupList->getYReal()) - _GroupList->getHReal());
730 if ((_GroupMenu->SpawnMouseX > ((sint32)screenW/2)) && (_GroupMenu->SpawnMouseY <= ((sint32)screenH/2)))
732 _SubMenus[RALineNb]->setParentPosRef(Hotspot_BL);
733 _SubMenus[RALineNb]->setPosRef(Hotspot_BR);
734 _SubMenus[RALineNb]->setY (refElmYReal - _GroupList->getYReal());
736 if ((_GroupMenu->SpawnMouseX > ((sint32)screenW/2)) && (_GroupMenu->SpawnMouseY > ((sint32)screenH/2)))
738 _SubMenus[RALineNb]->setParentPosRef(Hotspot_TL);
739 _SubMenus[RALineNb]->setPosRef(Hotspot_TR);
740 _SubMenus[RALineNb]->setY (refElmHReal+(refElmYReal - _GroupList->getYReal()) - _GroupList->getHReal());
742 _SubMenus[RALineNb]->setX(0);
744 else
746 // Setup sub menu
747 _SubMenus[RALineNb]->setParentPos (this);
748 _SubMenus[RALineNb]->setParentPosRef (Hotspot_BR);
749 _SubMenus[RALineNb]->setPosRef (Hotspot_BL);
750 _SubMenus[RALineNb]->setY (16+refElmYReal - _GroupList->getYReal() - _SubMenus[RALineNb]->getHReal());
753 ++RALineNb;
755 else if (pVB->getId() == ID_MENU_CHECKBOX)
757 for(;;)
759 nlassert (CBLineNb < (sint32)_SubMenus.size());
760 if (_Lines[CBLineNb].CheckBox != NULL) // has a check box or an arrow to indicate submenu ?
762 break;
764 ++CBLineNb;
766 // Setup the arrow at the right pos
767 if (!_Lines[CBLineNb].UserGroupRight)
769 // get refElm and refElmYReal
770 GET_REF_ELM(CBLineNb)
772 pVB->setX(maxUserGroupWidth + 2 * MENU_WIDGET_X);
774 sint32 limY = refElmYReal + refElmHReal/2 - _GroupList->getYReal();
775 // Setup the arrow at the right pos
776 if(_GroupList->getMaxH()>=limY && limY>=0)
778 pVB->setY(refElmYReal + (refElmHReal - pVB->getHReal()) / 2 - _GroupList->getYReal());
779 pVB->setActive(_Lines[CBLineNb].ViewText->getActive());
781 else
783 pVB->setY(0);
784 pVB->setActive(false);
787 else
789 pVB->setY(0);
790 pVB->setX(MENU_WIDGET_X);
792 pVB->setColor (_Lines[CBLineNb].ViewText->getColor());
794 ++CBLineNb;
797 if (maxViewW<(pVB->getWReal()+pVB->getX())) maxViewW = pVB->getWReal()+pVB->getX();
800 // setup scrollbar position in function of views width
801 if(maxViewW>0 && _ScrollBar)
802 _ScrollBar->setX(4 + maxViewW);
804 // *** Setup user groups positions
805 for(k = 0; k < _Lines.size(); ++k)
807 CInterfaceGroup *igr = _Lines[k].UserGroupRight;
808 CInterfaceGroup *igl = _Lines[k].UserGroupLeft;
809 if (igr || igl)
811 // get refElm and refElmYReal
812 GET_REF_ELM(k)
814 if (refElm)
816 if (igr)
818 igr->setX(MENU_WIDGET_X + maxUserGroupWidth - igr->getWReal());
820 sint32 limY = refElmYReal + refElmHReal/2 - _GroupList->getYReal();
821 if(_GroupList->getMaxH()>=limY && limY>=0)
823 igr->setY(refElmYReal + (refElmHReal - igr->getHReal()) / 2 - _GroupList->getYReal());
824 igr->setActive (refElm->getActive());
826 else
828 igr->setY(0);
829 igr->setActive(false);
833 if (igl)
835 sint32 limY = refElmYReal + refElmHReal/2 - _GroupList->getYReal();
836 if(_GroupList->getMaxH()>=limY && limY>=0)
838 igl->setY(refElmYReal + (refElmHReal - igl->getHReal()) / 2 - this->getYReal());
839 igl->setActive(refElm->getActive());
841 else
843 igl->setY(0);
844 igl->setActive(false);
852 sint32 SepLineNb = 0;
853 // set separator at the right position
854 for (i = 0; i < _ChildrenGroups.size(); ++i)
856 CInterfaceGroup *pIG = dynamic_cast<CInterfaceGroup *>(_ChildrenGroups[i]);
857 if (pIG == NULL) continue;
858 if (pIG->getId() != ID_MENU_SEPARATOR) continue; // is it a separator ?
860 // set good width
861 /*sint32 sw = getW() - _LeftBorder - _RightBorder;
862 sw = std::max(sw, (sint32) 0);
863 pIG->setW(sw);*/
865 // Look for the next line of the menu that contains a separator
866 CInterfaceGroup *sep = NULL;
869 nlassert (SepLineNb < (sint32)_Lines.size());
870 sep = _Lines[SepLineNb].Separator;
871 ++SepLineNb;
873 while (sep == NULL);
875 // Setup the arrow at the right pos
876 pIG->setY (sep->getYReal() - getYReal());
877 pIG->setActive(sep->getActive());
879 CGroupFrame::updateCoords();
881 //_SelectionView->setW (this->getW());
882 _SelectionView->setH (8);
883 _SelectionView->setY (4);
886 if (_Selected != -1 && _Lines[_Selected].ViewText != NULL)
888 CRGBA col= _GroupMenu->_HighLightOver;
890 _SelectionView->setColor (col);
891 _SelectionView->setModulateGlobalColor(getModulateGlobalColor());
893 // get refElm and refElmYReal
894 GET_REF_ELM(_Selected)
896 _SelectionView->setH (refElmHReal);
897 _SelectionView->setY (refElmYReal - this->getYReal());
901 // ------------------------------------------------------------------------------------------------
902 void CGroupSubMenu::checkCoords()
904 if (!_Active) return;
905 if (_GroupMenu == NULL) return;
907 // if the mouse goes out the window, unselect all (because handleEvent may not be called)
908 sint xMouse= CWidgetManager::getInstance()->getPointer()->getX();
909 sint yMouse= CWidgetManager::getInstance()->getPointer()->getY();
910 if (!((xMouse >= _XReal) &&
911 (xMouse < (_XReal + _WReal))&&
912 (yMouse > _YReal) &&
913 (yMouse <= (_YReal+ _HReal))))
914 _Selected= -1;
916 // CViewRenderer &rVR = *CViewRenderer::getInstance();
918 // Highlight (background under the selection)
919 if (_Selected != -1)
921 // display hightlight
922 if(_GroupMenu->_HighLightOver.A > 0)
924 _SelectionView->setActive (true);
925 _SelectionView->invalidateCoords();
927 else
929 _SelectionView->setActive (false);
932 else // no selection
934 _SelectionView->setActive (false);
937 // Text color if grayed or not
938 for (sint32 i = 0; i < (sint32)_Lines.size(); ++i)
940 if (_Lines[i].ViewText)
942 if (_Lines[i].ViewText->getGrayed()) // Colors when the text is grayed
944 _Lines[i].ViewText->setColor (_Lines[i].ViewText->OldColorGrayed);
945 _Lines[i].ViewText->setShadowColor (_Lines[i].ViewText->OldShadowColorGrayed);
947 else
949 if (i == _Selected) // Colors when the text is selected
951 _Lines[i].ViewText->Over = true;
952 _Lines[i].ViewText->setColor (_Lines[i].ViewText->OldColorOver);
953 _Lines[i].ViewText->setShadowColor (_Lines[i].ViewText->OldShadowColorOver);
955 else // Or finally normal colors
957 _Lines[i].ViewText->Over = false;
958 _Lines[i].ViewText->setColor (_Lines[i].ViewText->OldColor);
959 _Lines[i].ViewText->setShadowColor (_Lines[i].ViewText->OldShadowColor);
966 // ------------------------------------------------------------------------------------------------
967 void CGroupSubMenu::draw()
969 if (!_Active) return;
970 if (_GroupMenu == NULL) return;
971 CGroupFrame::draw();
974 // ------------------------------------------------------------------------------------------------
975 bool CGroupSubMenu::handleEvent (const NLGUI::CEventDescriptor &event)
977 if (!_Active)
978 return false;
980 sint32 textDYPos= 0;
981 if(_GroupList)
982 textDYPos= -(1+_GroupList->getSpace())/2;
984 if (event.getType() == NLGUI::CEventDescriptor::mouse)
986 const NLGUI::CEventDescriptorMouse &eventDesc = (const NLGUI::CEventDescriptorMouse &)event;
987 _Selected = -1;
989 // TODO First check sub menus that can be not in the area of this menu
991 if (!((eventDesc.getX() >= _XReal) &&
992 (eventDesc.getX() < (_XReal + _WReal))&&
993 (eventDesc.getY() > _YReal) &&
994 (eventDesc.getY() <= (_YReal+ _HReal))))
995 return false;
997 uint32 i = 0;
998 for (i = 0; i < _Lines.size(); ++i)
1000 if (_Lines[i].Selectable)
1002 // get refElm and refElmYReal
1003 GET_REF_ELM(i)
1005 if (refElm)
1007 if (refElm->getActive() == true)
1008 if ((eventDesc.getY() > refElmYReal) &&
1009 (eventDesc.getY() <= (refElmYReal + refElmHReal + _GroupList->getSpace())))
1011 _Selected = i;
1012 break;
1018 if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftup)
1020 // If a line is selected and the line is not grayed
1021 if ((_Selected != -1) && (!_Lines[i].ViewText->getGrayed()))
1024 CAHManager::getInstance()->runActionHandler ( _Lines[_Selected].AHName,
1025 CWidgetManager::getInstance()->getCtrlLaunchingModal(),
1026 _Lines[_Selected].AHParams );
1028 if (_SubMenus[_Selected] != NULL)
1030 openSubMenu (_Selected);
1032 else
1034 // if the menu hasn't triggered a new modal window, disable it
1035 if (CWidgetManager::getInstance()->getModalWindow() == _GroupMenu)
1037 if(_GroupMenu && _GroupMenu->getCloseSubMenuUsingPopModal())
1038 CWidgetManager::getInstance()->popModalWindow();
1039 else
1040 CWidgetManager::getInstance()->disableModalWindow ();
1046 if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightup)
1048 // If a line is selected and the line is not grayed and has right click action handler
1049 if ((_Selected != -1) && (!_Lines[i].ViewText->getGrayed()) && !_Lines[_Selected].AHRightClick.empty())
1051 CAHManager::getInstance()->runActionHandler ( _Lines[_Selected].AHRightClick,
1052 CWidgetManager::getInstance()->getCtrlLaunchingModal(),
1053 _Lines[_Selected].AHRightClickParams );
1054 return true;
1058 if (event.getType() == NLGUI::CEventDescriptor::mouse)
1060 const NLGUI::CEventDescriptorMouse &eventDesc = (const NLGUI::CEventDescriptorMouse &)event;
1062 if (_GroupList && _ScrollBar)
1064 if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousewheel)
1066 if (isIn(eventDesc.getX(), eventDesc.getY()))
1068 sint32 h = 0;
1069 for (uint32 k = 0; k < _Lines.size(); ++k)
1070 if (_Lines[k].ViewText)
1072 // compute max height of widgets on the left of text
1073 sint32 widgetMaxH = 0;
1074 if (_Lines[k].UserGroupRight) widgetMaxH = _Lines[k].UserGroupRight->getHReal();
1075 if (_Lines[k].UserGroupLeft) widgetMaxH = std::max(widgetMaxH, _Lines[k].UserGroupLeft->getHReal());
1076 if (_Lines[k].CheckBox) widgetMaxH = std::max(widgetMaxH, _Lines[k].CheckBox->getHReal());
1077 if (_Lines[k].RightArrow) widgetMaxH = std::max(widgetMaxH, _Lines[k].RightArrow->getHReal());
1078 widgetMaxH = std::max(widgetMaxH, _Lines[k].ViewText->getHReal());
1079 h = widgetMaxH+_GroupList->getSpace();
1081 if (h == 0) h = 1;
1082 _ScrollBar->moveTargetY(- eventDesc.getWheel() * h);
1084 hideSubMenus();
1086 return true;
1092 return true;
1094 return false;
1097 // ------------------------------------------------------------------------------------------------
1098 CInterfaceElement* CGroupSubMenu::getElement (const std::string &id)
1100 string sTmp = id.substr(0, _GroupMenu->getId().size());
1101 if (sTmp != _GroupMenu->getId()) return NULL;
1103 string sRest = id.substr(_GroupMenu->getId().size()+1, id.size());
1105 // Iterate through the tree to see if sRest is present
1106 CGroupSubMenu *pCurGSM = this;
1107 while (!sRest.empty())
1109 // Get the first element of the sRest
1110 string::size_type posid = sRest.find (":");
1112 if (posid == string::npos) // Is there just one token to test ?
1114 for (uint32 i = 0; i < pCurGSM->_Lines.size(); ++i)
1115 if (sRest == pCurGSM->_Lines[i].Id)
1116 return pCurGSM->_Lines[i].ViewText;
1117 sRest.clear();
1119 else // no a lot of token left
1121 string sTok = sRest.substr (0, posid);
1122 uint32 i = 0;
1123 for (i = 0; i < pCurGSM->_Lines.size(); ++i)
1124 if (sTok == pCurGSM->_Lines[i].Id)
1125 break;
1126 if (i == pCurGSM->_Lines.size())
1127 return NULL;
1129 // No sub-menus
1130 if (pCurGSM->_SubMenus[i] == NULL)
1132 // Get next token
1133 sRest = sRest.substr (posid+1);
1134 posid = sRest.find (":");
1135 if (posid == string::npos)
1136 sTok = sRest;
1137 else
1138 sTok = sRest.substr (0, posid);
1139 // Do we want left or right user group ?
1140 if (pCurGSM->_Lines[i].UserGroupRight)
1142 string sUGid = pCurGSM->_Lines[i].UserGroupRight->getId();
1143 sUGid = sUGid.substr(sUGid.rfind(':')+1,sUGid.size());
1144 if (sUGid == sTok)
1146 CInterfaceElement *pIE = pCurGSM->_Lines[i].UserGroupRight->getElement(id);
1147 return pIE;
1150 if (pCurGSM->_Lines[i].UserGroupLeft)
1152 string sUGid = pCurGSM->_Lines[i].UserGroupLeft->getId();
1153 sUGid = sUGid.substr(sUGid.rfind(':')+1,sUGid.size());
1154 if (sUGid == sTok)
1156 CInterfaceElement *pIE = pCurGSM->_Lines[i].UserGroupLeft->getElement(id);
1157 return pIE;
1161 return NULL;
1163 else
1165 pCurGSM = pCurGSM->_SubMenus[i];
1168 sRest = sRest.substr (posid+1);
1171 return NULL;
1174 // ------------------------------------------------------------------------------------------------
1175 void CGroupSubMenu::addSeparator(const std::string &id)
1177 addSeparatorAtIndex((uint)_Lines.size(), id);
1180 // ------------------------------------------------------------------------------------------------
1181 void CGroupSubMenu::addSeparatorAtIndex(uint index, const std::string &id)
1183 if (index > _Lines.size())
1185 nlwarning("Bad index");
1186 return;
1189 // create the real separator. It may be larger than the group list, this is why we create a separate group
1190 CInterfaceGroup *separator = CWidgetManager::getInstance()->getParser()->createGroupInstance("menu_separator", "", NULL, 0);
1191 if (!separator) return;
1192 separator->setSerializable( false );
1193 separator->setId(ID_MENU_SEPARATOR);
1194 separator->setSerializable( false );
1195 addGroup(separator);
1196 separator->setParent(this);
1197 // create place holder group
1198 CInterfaceGroup *ph = CWidgetManager::getInstance()->getParser()->createGroupInstance("menu_separator_empty", "", NULL, 0);
1199 if (!ph)
1201 delGroup(separator);
1202 return;
1204 _GroupList->addChildAtIndex(ph, index);
1205 SSubMenuEntry tmp;
1206 tmp.Id = id;
1207 tmp.Separator = ph;
1208 tmp.ViewText = NULL;
1209 tmp.CheckBox = NULL;
1210 tmp.RightArrow = NULL;
1211 _Lines.insert(_Lines.begin() + index, tmp);
1212 _SubMenus.insert(_SubMenus.begin() + index, (CGroupSubMenu*)NULL);
1213 _GroupMenu->invalidateCoords();
1217 // ------------------------------------------------------------------------------------------------
1218 CViewTextMenu* CGroupSubMenu::addLine (const std::string &name, const std::string &ah,
1219 const std::string &params, const std::string &id,
1220 const std::string &cond, const std::string &texture,
1221 bool checkable /*= false*/, bool checked /*= false*/, bool formatted /*= false */
1224 SSubMenuEntry tmp;
1226 CViewTextMenu *pV = new CViewTextMenu(CViewBase::TCtorParam());
1229 pV->setCaseMode(_GroupMenu->getCaseMode());
1230 if (formatted)
1232 pV->setMultiLine (true);
1233 pV->setMultiLineMaxWOnly (true);
1234 pV->setTextFormatTaged (name);
1236 else
1238 pV->setText (name);
1240 pV->setColor (_GroupMenu->_Color);
1241 pV->setFontSize (_GroupMenu->_FontSize, _GroupMenu->_FontSizeCoef);
1242 pV->setShadow (_GroupMenu->_Shadow);
1243 pV->setShadowOutline (_GroupMenu->_ShadowOutline);
1244 pV->setCheckable(checkable);
1245 pV->setChecked(checked);
1246 pV->setModulateGlobalColor(_GroupMenu->_ModulateGlobalColor);
1248 pV->OldColor = _GroupMenu->_Color;
1249 pV->OldShadowColor = _GroupMenu->_ShadowColor;
1250 pV->OldColorOver = _GroupMenu->_ColorOver;
1251 pV->OldShadowColorOver = _GroupMenu->_ShadowColorOver;
1252 pV->OldColorGrayed = _GroupMenu->_ColorGrayed;
1253 pV->OldShadowColorGrayed = _GroupMenu->_ShadowColorGrayed;
1255 _GroupList->addChild (pV);
1257 CViewBitmap *checkBox = NULL;
1259 if (checkable)
1261 checkBox = createCheckBox(checked);
1262 checkBox->setTexture(texture);
1263 pV->setCheckBox(checkBox);
1266 CViewBitmap *icon = NULL;
1267 if (!texture.empty())
1269 if (_GroupList->getNumChildren() == 1)
1270 pV->setX(20);
1271 icon = createIcon(pV, texture);
1275 tmp.ViewText = pV;
1276 tmp.Separator = NULL;
1277 tmp.AHName = ah;
1278 tmp.AHParams = params;
1279 tmp.Cond = cond;
1280 tmp.CheckBox = checkBox;
1281 tmp.RightArrow = icon;
1282 if (id.empty())
1283 tmp.Id = NLMISC::toString (_Lines.size());
1284 else
1285 tmp.Id = id;
1287 pV->setId(_GroupMenu->getId()+":"+tmp.Id);
1289 _Lines.push_back (tmp);
1291 // Add an empty sub menu by default
1292 _SubMenus.push_back (NULL);
1294 _GroupMenu->invalidateCoords();
1296 return pV;
1299 CViewTextMenu* CGroupSubMenu::addLineAtIndex(uint index, const std::string &name, const std::string &ah,
1300 const std::string &params, const std::string &id /*=""*/,
1301 const std::string &cond /*=std::string()*/, const std::string &texture,
1302 bool checkable /*= false*/, bool checked /*= false*/, bool formatted /*= false */
1305 if (index > _Lines.size())
1307 nlwarning("Bad index");
1308 return NULL;
1310 SSubMenuEntry tmp;
1311 CViewTextMenu *pV = new CViewTextMenu(CViewBase::TCtorParam());
1312 pV->setSerializable( false );
1315 pV->setCaseMode(_GroupMenu->getCaseMode());
1318 if (formatted)
1320 pV->setMultiLine (true);
1321 pV->setMultiLineMaxWOnly (true);
1322 pV->setTextFormatTaged (name);
1324 else
1326 pV->setText (name);
1329 pV->setColor (_GroupMenu->_Color);
1330 pV->setFontSize (_GroupMenu->_FontSize, _GroupMenu->_FontSizeCoef);
1331 pV->setShadow (_GroupMenu->_Shadow);
1332 pV->setShadowOutline (_GroupMenu->_ShadowOutline);
1333 pV->setCheckable(checkable);
1334 pV->setChecked(checked);
1335 pV->setModulateGlobalColor(_GroupMenu->_ModulateGlobalColor);
1337 pV->OldColor = _GroupMenu->_Color;
1338 pV->OldShadowColor = _GroupMenu->_ShadowColor;
1339 pV->OldColorOver = _GroupMenu->_ColorOver;
1340 pV->OldShadowColorOver = _GroupMenu->_ShadowColorOver;
1341 pV->OldColorGrayed = _GroupMenu->_ColorGrayed;
1342 pV->OldShadowColorGrayed = _GroupMenu->_ShadowColorGrayed;
1344 _GroupList->addChildAtIndex(pV, index);
1346 CViewBitmap *checkBox = NULL;
1347 if (checkable)
1349 checkBox = createCheckBox(checked);
1350 checkBox->setTexture(texture);
1351 pV->setCheckBox(checkBox);
1354 tmp.ViewText = pV;
1355 tmp.Separator = NULL;
1356 tmp.AHName = ah;
1357 tmp.AHParams = params;
1358 tmp.Cond = cond;
1359 tmp.CheckBox = checkBox;
1360 tmp.RightArrow = NULL;
1362 if (id.empty())
1363 tmp.Id = NLMISC::toString (_Lines.size());
1364 else
1365 tmp.Id = id;
1367 pV->setId(getId()+":"+tmp.Id);
1369 _Lines.insert(_Lines.begin() + index, tmp);
1371 // Add an empty sub menu by default
1372 _SubMenus.insert(_SubMenus.begin() + index, (CGroupSubMenu*)NULL);
1374 _GroupMenu->invalidateCoords();
1376 return pV;
1380 // ------------------------------------------------------------------------------------------------
1381 void CGroupSubMenu::removeLine(uint index)
1383 if (index >= _Lines.size())
1385 nlwarning("Bad index");
1386 return;
1388 setUserGroupRight(index, NULL, false); // remove user group
1389 setUserGroupLeft(index, NULL, false); // remove user group
1390 // remove view (right arrow & checkbox)
1391 if (_Lines[index].RightArrow) delView(_Lines[index].RightArrow);
1392 if (_Lines[index].CheckBox) delView(_Lines[index].CheckBox);
1393 if (_Lines[index].Separator)
1395 // remove one separator group
1396 for(uint k = 0; k < _ChildrenGroups.size(); ++k)
1398 if (_ChildrenGroups[k]->getId() == ID_MENU_SEPARATOR)
1400 delGroup(_ChildrenGroups[k]);
1401 break;
1406 _GroupList->setDelOnRemove(index, true);
1407 _GroupList->delChild(index);
1408 _Lines.erase(_Lines.begin() + index);
1410 //invalidate selection
1411 _Selected = -1;
1413 if(_SubMenus[index])
1415 // reset it and his sons (recurs)
1416 _SubMenus[index]->reset();
1417 // then delete it
1418 _GroupMenu->delGroup(_SubMenus[index]);
1420 _SubMenus.erase(_SubMenus.begin() + index);
1421 _GroupMenu->invalidateCoords();
1424 // ------------------------------------------------------------------------------------------------
1425 void CGroupSubMenu::openSubMenu (sint32 nb)
1427 hideSubMenus ();
1428 _SubMenus[nb]->setActive (true);
1431 // ------------------------------------------------------------------------------------------------
1432 void CGroupSubMenu::hideSubMenus ()
1434 for (uint32 i = 0; i < _SubMenus.size(); ++i)
1435 if (_SubMenus[i] != NULL)
1437 _SubMenus[i]->setActive (false);
1438 _SubMenus[i]->hideSubMenus ();
1442 // ------------------------------------------------------------------------------------------------
1443 void CGroupSubMenu::reset()
1445 uint lineCount = (uint)_Lines.size();
1446 for(sint k = lineCount - 1; k >= 0; --k)
1448 removeLine(k);
1453 // ------------------------------------------------------------------------------------------------
1454 void CGroupSubMenu::removeAllUserGroups()
1456 for(uint k = 0; k < _Lines.size(); ++k)
1458 setUserGroupRight(k, NULL, false);
1459 setUserGroupLeft(k, NULL, false);
1463 // ------------------------------------------------------------------------------------------------
1464 CInterfaceGroup *CGroupSubMenu::getUserGroupRight(uint line) const
1466 if (line >= _Lines.size())
1468 nlwarning("bad index");
1469 return NULL;
1471 return _Lines[line].UserGroupRight;
1474 // ------------------------------------------------------------------------------------------------
1475 CInterfaceGroup *CGroupSubMenu::getUserGroupLeft(uint line) const
1477 if (line >= _Lines.size())
1479 nlwarning("bad index");
1480 return NULL;
1482 return _Lines[line].UserGroupLeft;
1485 // ------------------------------------------------------------------------------------------------
1486 void CGroupSubMenu::setUserGroupRight(uint line, CInterfaceGroup *group, bool ownership)
1488 if (line >= _Lines.size())
1490 nlwarning("bad index");
1491 return;
1493 if (group && isChildGroup(group))
1495 nlwarning("Group inserted twice");
1496 return;
1498 if (_Lines[line].UserGroupRight)
1500 delGroup(_Lines[line].UserGroupRight, !_Lines[line].UserGroupRightOwnership);
1502 _Lines[line].UserGroupRight = group;
1503 _Lines[line].UserGroupRightOwnership = ownership;
1504 if (group)
1506 CViewBase *prevElem = _Lines[line].CheckBox ? _Lines[line].CheckBox : _Lines[line].RightArrow;
1507 if (prevElem)
1509 prevElem->setParentPosRef (Hotspot_MR);
1510 prevElem->setPosRef (Hotspot_ML);
1511 prevElem->setParentPos(group);
1512 prevElem->setX(MENU_WIDGET_X);
1513 prevElem->setY(0);
1515 sint insertionOrder;
1516 if (prevElem)
1518 insertionOrder = getInsertionOrder(prevElem);
1520 else
1522 insertionOrder = -1;
1524 addGroup(group, insertionOrder);
1525 group->setParent(this);
1526 group->setParentPos(_GroupList);
1527 group->setParentPosRef (Hotspot_BR);
1528 group->setPosRef (Hotspot_BL);
1530 else
1532 // restore all posref..
1533 CViewBase *prevElem = _Lines[line].CheckBox ? _Lines[line].CheckBox : _Lines[line].RightArrow;
1534 if (prevElem)
1536 prevElem->setParent (this);
1537 prevElem->setParentPos (_GroupList);
1538 prevElem->setParentPosRef (Hotspot_BR);
1539 prevElem->setPosRef (Hotspot_BL);
1540 prevElem->setX (MENU_WIDGET_X);
1543 _GroupMenu->invalidateCoords();
1547 // ------------------------------------------------------------------------------------------------
1548 void CGroupSubMenu::setUserGroupLeft(uint line, CInterfaceGroup *group, bool ownership)
1550 if (line >= _Lines.size())
1552 nlwarning("bad index");
1553 return;
1555 if (group && isChildGroup(group))
1557 nlwarning("Group inserted twice");
1558 return;
1560 if (_Lines[line].UserGroupLeft)
1562 delGroup(_Lines[line].UserGroupLeft, !_Lines[line].UserGroupLeftOwnership);
1564 _Lines[line].UserGroupLeft = group;
1565 _Lines[line].UserGroupLeftOwnership = ownership;
1566 if (group)
1568 addGroup(group);
1569 group->setParent(this);
1570 group->setParentPos(this);
1571 group->setParentPosRef (Hotspot_BL);
1572 group->setPosRef (Hotspot_BL);
1573 group->setX(LEFT_MENU_WIDGET_X);
1576 _GroupMenu->invalidateCoords();
1580 // ------------------------------------------------------------------------------------------------
1581 CGroupSubMenu *CGroupSubMenu::cloneMenu(CGroupSubMenu *appendToMenu, CGroupMenu *newFather, CInterfaceGroup *initGroup /* = NULL */) const
1583 CGroupSubMenu *copyMenu = appendToMenu ? appendToMenu : new CGroupSubMenu(CViewText::TCtorParam());
1584 uint startSize = (uint)copyMenu->_Lines.size();
1585 copyMenu->setSerializable( false );
1586 copyMenu->_GroupMenu = newFather;
1587 copyMenu->initOptions(initGroup);
1588 copyMenu->_Lines.reserve(_Lines.size() + startSize);
1589 copyMenu->_SubMenus.reserve(_SubMenus.size() + startSize);
1590 // copy childrens
1591 for(uint k = 0; k < _Lines.size(); ++k)
1593 if (_Lines[k].Separator)
1595 copyMenu->addSeparator(_Lines[k].Id);
1597 else
1599 std::string texture = std::string();
1600 if(_Lines[k].ViewText->getCheckBox())
1602 texture = _Lines[k].ViewText->getCheckBox()->getTexture();
1604 CViewTextMenu *pV = NULL;
1605 pV = copyMenu->addLine (_Lines[k].ViewText->getText(), _Lines[k].AHName, _Lines[k].AHParams, _Lines[k].Id, _Lines[k].Cond,
1606 texture, _Lines[k].ViewText->getCheckable(), _Lines[k].ViewText->getChecked(), _Lines[k].ViewText->getFormatted ());
1607 copyMenu->_Lines[k].Selectable = _Lines[k].Selectable;
1608 pV->setGrayed(_Lines[k].ViewText->getGrayed());
1611 // sub menu copy if there's one
1612 if (_SubMenus[k] != NULL)
1615 if (copyMenu->_Lines.back().CheckBox)
1617 copyMenu->_Lines.back().RightArrow = copyMenu->createRightArrow(copyMenu->_Lines.back().CheckBox, true);
1619 else
1621 copyMenu->_Lines.back().RightArrow = copyMenu->createRightArrow(copyMenu->_GroupList, false);
1625 // and create the sub menu
1626 copyMenu->_SubMenus[k + startSize] = _SubMenus[k]->cloneMenu(NULL, newFather, copyMenu);
1629 if (!appendToMenu)
1631 newFather->addGroup(copyMenu);
1633 return copyMenu;
1636 // ------------------------------------------------------------------------------------------------
1637 void CGroupSubMenu::setActive(bool state)
1639 // check conditions
1640 for(uint k = 0; k < _Lines.size(); ++k)
1642 if (!_Lines[k].Cond.empty())
1644 CInterfaceExprValue result;
1645 if (CInterfaceExpr::eval(_Lines[k].Cond, result))
1647 if (result.toBool())
1649 _Lines[k].ViewText->setGrayed(!result.getBool());
1655 if(_ScrollBar && _GroupList)
1656 _ScrollBar->setTrackPos(_GroupList->getHReal());
1658 CGroupFrame::setActive(state);
1661 // ------------------------------------------------------------------------------------------------
1662 const std::string CGroupSubMenu::getActionHandler(uint lineIndex) const
1664 if (lineIndex > _Lines.size())
1666 nlwarning("Bad index");
1667 return 0;
1669 return _Lines[lineIndex].AHName;
1672 // ------------------------------------------------------------------------------------------------
1673 const std::string CGroupSubMenu::getActionHandlerParam(uint lineIndex) const
1675 if (lineIndex > _Lines.size())
1677 nlwarning("Bad index");
1678 return 0;
1680 return _Lines[lineIndex].AHParams;
1683 // ------------------------------------------------------------------------------------------------
1684 void CGroupSubMenu::setActionHandler(uint lineIndex, const std::string &ah)
1686 if (lineIndex > _Lines.size())
1688 nlwarning("Bad index");
1689 return;
1691 _Lines[lineIndex].AHName = ah;
1694 // ------------------------------------------------------------------------------------------------
1695 void CGroupSubMenu::setActionHandlerParam(uint lineIndex, const std::string &params)
1697 if (lineIndex > _Lines.size())
1699 nlwarning("Bad index");
1700 return;
1702 _Lines[lineIndex].AHParams = params;
1705 // ------------------------------------------------------------------------------------------------
1706 void CGroupSubMenu::setRightClickHandler(uint lineIndex, const std::string &ah)
1708 if (lineIndex > _Lines.size())
1710 nlwarning("Bad index");
1711 return;
1713 _Lines[lineIndex].AHRightClick = ah;
1716 // ------------------------------------------------------------------------------------------------
1717 void CGroupSubMenu::setRightClickHandlerParam(uint lineIndex, const std::string &params)
1719 if (lineIndex > _Lines.size())
1721 nlwarning("Bad index");
1722 return;
1724 _Lines[lineIndex].AHRightClickParams = params;
1727 // ------------------------------------------------------------------------------------------------
1728 void CGroupSubMenu::setSelectable(uint lineIndex, bool selectable)
1730 if (lineIndex > _Lines.size())
1732 nlwarning("Bad index");
1733 return;
1735 _Lines[lineIndex].Selectable = selectable;
1738 // ------------------------------------------------------------------------------------------------
1739 bool CGroupSubMenu::getSelectable(uint lineIndex) const
1741 if (lineIndex > _Lines.size())
1743 nlwarning("Bad index");
1744 return 0;
1746 return _Lines[lineIndex].Selectable;
1749 // ------------------------------------------------------------------------------------------------
1750 void CGroupSubMenu::setMaxVisibleLine(sint32 mvl)
1752 _MaxVisibleLine = mvl;
1755 // ------------------------------------------------------------------------------------------------
1756 const std::string &CGroupSubMenu::getLineId(uint index)
1758 if(index>=_Lines.size())
1760 static string nullString;
1761 return nullString;
1763 else
1764 return _Lines[index].Id;
1767 // ------------------------------------------------------------------------------------------------
1768 void CGroupSubMenu::setGrayedLine(uint line, bool g)
1770 if(line<_Lines.size())
1772 if (_Lines[line].ViewText)
1774 _Lines[line].ViewText->setGrayed(g);
1779 // ------------------------------------------------------------------------------------------------
1780 void CGroupSubMenu::setHiddenLine(uint line, bool h)
1782 if(line<_Lines.size())
1784 if (_Lines[line].ViewText)
1786 _Lines[line].ViewText->setActive(!h);
1791 // ------------------------------------------------------------------------------------------------
1792 int CGroupSubMenu::luaGetNumLine(CLuaState &ls)
1794 CLuaIHM::checkArgCount(ls, "getNumLine", 0);
1795 ls.push(getNumLine());
1796 return 1;
1799 // ------------------------------------------------------------------------------------------------
1800 int CGroupSubMenu::luaGetSubMenu(CLuaState &ls)
1802 const char *funcName = "getSubMenu";
1803 CLuaIHM::checkArgCount(ls, funcName, 1);
1804 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1805 CLuaIHM::pushUIOnStack(ls, getSubMenu((uint) ls.toInteger(1)));
1806 return 1;
1809 // ------------------------------------------------------------------------------------------------
1810 int CGroupSubMenu::luaAddSubMenu(CLuaState &ls)
1812 const char *funcName = "addSubMenu";
1813 CLuaIHM::checkArgCount(ls, funcName, 1);
1814 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1815 setSubMenu((uint) ls.toInteger(1), new CGroupSubMenu(CViewText::TCtorParam()));
1816 CLuaIHM::pushUIOnStack(ls, getSubMenu((uint) ls.toInteger(1)));
1817 return 1;
1820 // ------------------------------------------------------------------------------------------------
1821 int CGroupSubMenu::luaGetLineId(CLuaState &ls)
1823 const char *funcName = "getLineId";
1824 CLuaIHM::checkArgCount(ls, funcName, 1);
1825 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1826 #ifdef RYZOM_LUA_UCSTRING
1827 ucstring id = getLineId((uint) ls.toInteger(1)); // Compatibility
1828 CLuaIHM::push(ls, id);
1829 #else
1830 std::string id = getLineId((uint)ls.toInteger(1));
1831 ls.push(id);
1832 #endif
1833 return 1;
1836 // ------------------------------------------------------------------------------------------------
1837 int CGroupSubMenu::luaGetLineFromId(CLuaState &ls)
1839 const char *funcName = "getLineFromId";
1840 CLuaIHM::checkArgCount(ls, funcName, 1);
1841 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TSTRING);
1842 ls.push(getLineFromId(ls.toString(1)));
1843 return 1;
1846 // ------------------------------------------------------------------------------------------------
1847 int CGroupSubMenu::luaIsSeparator(CLuaState &ls)
1849 const char *funcName = "isSeparator";
1850 CLuaIHM::checkArgCount(ls, funcName, 1);
1851 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1852 ls.push(isSeparator((uint) ls.toInteger(1)));
1853 return 1;
1856 // ------------------------------------------------------------------------------------------------
1857 int CGroupSubMenu::luaAddLine(CLuaState &ls)
1859 const char *funcName = "addLine";
1860 CLuaIHM::checkArgCount(ls, funcName, 4);
1861 #ifdef RYZOM_LUA_UCSTRING
1862 CLuaIHM::checkArgTypeUCString(ls, funcName, 1);
1863 #else
1864 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TSTRING);
1865 #endif
1866 CLuaIHM::checkArgType(ls, funcName, 2, LUA_TSTRING);
1867 CLuaIHM::checkArgType(ls, funcName, 3, LUA_TSTRING);
1868 CLuaIHM::checkArgType(ls, funcName, 4, LUA_TSTRING);
1869 #ifdef RYZOM_LUA_UCSTRING
1870 ucstring arg1; // Compatibility
1871 nlverify(CLuaIHM::getUCStringOnStack(ls, 1, arg1));
1872 addLine(arg1.toUtf8(), ls.toString(2), ls.toString(3), ls.toString(4));
1873 #else
1874 addLine(ls.toString(1), ls.toString(2), ls.toString(3), ls.toString(4));
1875 #endif
1876 return 0;
1879 // ------------------------------------------------------------------------------------------------
1880 int CGroupSubMenu::luaAddIconLine(CLuaState &ls)
1882 const char *funcName = "addIconLine";
1883 CLuaIHM::checkArgCount(ls, funcName, 5);
1884 #ifdef RYZOM_LUA_UCSTRING
1885 CLuaIHM::checkArgTypeUCString(ls, funcName, 1);
1886 #else
1887 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TSTRING);
1888 #endif
1889 CLuaIHM::checkArgType(ls, funcName, 2, LUA_TSTRING);
1890 CLuaIHM::checkArgType(ls, funcName, 3, LUA_TSTRING);
1891 CLuaIHM::checkArgType(ls, funcName, 4, LUA_TSTRING);
1892 CLuaIHM::checkArgType(ls, funcName, 5, LUA_TSTRING);
1893 #ifdef RYZOM_LUA_UCSTRING
1894 ucstring arg1; // Compatibility
1895 nlverify(CLuaIHM::getUCStringOnStack(ls, 1, arg1));
1896 addLine(arg1.toUtf8(), ls.toString(2), ls.toString(3), ls.toString(4), string(), ls.toString(5));
1897 #else
1898 addLine(ls.toString(1), ls.toString(2), ls.toString(3), ls.toString(4), string(), ls.toString(5));
1899 #endif
1900 return 0;
1903 // ------------------------------------------------------------------------------------------------
1904 int CGroupSubMenu::luaAddLineAtIndex(CLuaState &ls)
1906 const char *funcName = "addLineAtIndex";
1907 CLuaIHM::checkArgCount(ls, funcName, 5);
1908 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1909 #ifdef RYZOM_LUA_UCSTRING
1910 CLuaIHM::checkArgTypeUCString(ls, funcName, 2);
1911 #else
1912 CLuaIHM::checkArgType(ls, funcName, 2, LUA_TSTRING);
1913 #endif
1914 CLuaIHM::checkArgType(ls, funcName, 3, LUA_TSTRING);
1915 CLuaIHM::checkArgType(ls, funcName, 4, LUA_TSTRING);
1916 CLuaIHM::checkArgType(ls, funcName, 5, LUA_TSTRING);
1917 #ifdef RYZOM_LUA_UCSTRING
1918 ucstring arg2;
1919 nlverify(CLuaIHM::getUCStringOnStack(ls, 2, arg2));
1920 addLineAtIndex((uint) ls.toInteger(1), arg2.toUtf8(), ls.toString(3), ls.toString(4), ls.toString(5));
1921 #else
1922 addLineAtIndex((uint)ls.toInteger(1), ls.toString(2), ls.toString(3), ls.toString(4), ls.toString(5));
1923 #endif
1924 return 0;
1927 // ------------------------------------------------------------------------------------------------
1928 int CGroupSubMenu::luaAddSeparator(CLuaState &ls)
1930 CLuaIHM::checkArgCount(ls, "addSeparator", 0);
1931 addSeparator();
1932 return 0;
1935 // ------------------------------------------------------------------------------------------------
1936 int CGroupSubMenu::luaAddSeparatorAtIndex(CLuaState &ls)
1938 const char *funcName = "addSeparatorAtIndex";
1939 CLuaIHM::checkArgCount(ls, funcName, 1);
1940 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1941 addSeparatorAtIndex((uint) ls.toInteger(1));
1942 return 0;
1945 // ------------------------------------------------------------------------------------------------
1946 int CGroupSubMenu::luaRemoveLine(CLuaState &ls)
1948 const char *funcName = "removeLine";
1949 CLuaIHM::checkArgCount(ls, funcName, 1);
1950 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1951 removeLine((uint) ls.toInteger(1));
1952 return 0;
1955 // ------------------------------------------------------------------------------------------------
1956 int CGroupSubMenu::luaSetUserGroupRight(CLuaState &ls)
1958 const char *funcName = "setUserGroupRight";
1959 CLuaIHM::checkArgCount(ls, funcName, 2);
1960 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1961 if (!(CLuaIHM::isUIOnStack(ls, 2) || ls.isNil(2)))
1963 CLuaIHM::fails(ls, "%s : Group required as argument 2", funcName);
1965 CInterfaceElement *el = CLuaIHM::getUIOnStack(ls, 2);
1966 CInterfaceGroup *group = dynamic_cast<CInterfaceGroup *>(el);
1967 if (el && !group)
1969 CLuaIHM::fails(ls, "%s : Group required as argument 2", funcName);
1971 setUserGroupRight((uint) ls.toInteger(1), group, true);
1972 return 0;
1975 // ------------------------------------------------------------------------------------------------
1976 int CGroupSubMenu::luaSetUserGroupLeft(CLuaState &ls)
1978 const char *funcName = "setUserGroupLeft";
1979 CLuaIHM::checkArgCount(ls, funcName, 2);
1980 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
1981 if (!(CLuaIHM::isUIOnStack(ls, 2) || ls.isNil(2)))
1983 CLuaIHM::fails(ls, "%s : Group required as argument 2", funcName);
1985 CInterfaceElement *el = CLuaIHM::getUIOnStack(ls, 2);
1986 CInterfaceGroup *group = dynamic_cast<CInterfaceGroup *>(el);
1987 if (el && !group)
1989 CLuaIHM::fails(ls, "%s : Group required as argument 2", funcName);
1991 setUserGroupLeft((uint) ls.toInteger(1), group, true);
1992 return 0;
1996 // ------------------------------------------------------------------------------------------------
1997 int CGroupSubMenu::luaGetUserGroupRight(CLuaState &ls)
1999 const char *funcName = "getUserGroupRight";
2000 CLuaIHM::checkArgCount(ls, funcName, 1);
2001 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
2002 CLuaIHM::pushUIOnStack(ls, getUserGroupRight((uint) ls.toInteger(1)));
2003 return 1;
2007 // ------------------------------------------------------------------------------------------------
2008 int CGroupSubMenu::luaGetUserGroupLeft(CLuaState &ls)
2010 const char *funcName = "getUserGroupLeft";
2011 CLuaIHM::checkArgCount(ls, funcName, 1);
2012 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
2013 CInterfaceElement *pIE = getUserGroupLeft((uint) ls.toInteger(1));
2014 if (pIE)
2016 CLuaIHM::pushUIOnStack(ls, pIE);
2017 return 1;
2019 else return 0;
2022 // ------------------------------------------------------------------------------------------------
2023 int CGroupSubMenu::luaSetMaxVisibleLine(CLuaState &ls)
2025 const char *funcName = "setMaxVisibleLine";
2026 CLuaIHM::checkArgCount(ls, funcName, 1);
2027 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
2028 setMaxVisibleLine((uint) ls.toInteger(1));
2029 return 0;
2032 // ------------------------------------------------------------------------------------------------
2033 int CGroupSubMenu::luaReset(CLuaState &ls)
2035 const char *funcName = "reset";
2036 CLuaIHM::checkArgCount(ls, funcName, 0);
2037 reset();
2038 return 0;
2042 // ------------------------------------------------------------------------------------------------
2043 // CGroupMenu
2044 // ------------------------------------------------------------------------------------------------
2046 NLMISC_REGISTER_OBJECT(CViewBase, CGroupMenu, std::string, "menu");
2048 // ------------------------------------------------------------------------------------------------
2049 CGroupMenu::CGroupMenu(const TCtorParam &param)
2050 :CGroupModal(param)
2052 _Active = false;
2053 _Color = CRGBA::White;
2054 _ColorOver = CRGBA::White;
2055 _ColorGrayed = CRGBA(128, 128, 128, 255);
2056 _ShadowColor = CRGBA::Black;
2057 _ShadowColorOver = CRGBA::Black;
2058 _ShadowColorGrayed = CRGBA::Black;
2059 _HighLightOver.set(128, 0, 0, 255);
2060 _FontSize = 12;
2061 _FontSizeCoef = true;
2062 _Shadow = false;
2063 _ShadowOutline = false;
2064 _ResizeFromChildH = _ResizeFromChildW = true;
2065 _DisplayFrame = false;
2066 _RootMenu = NULL;
2067 _Space = 3;
2068 _CaseMode = CaseUpper;
2069 _Formatted = false;
2072 // ------------------------------------------------------------------------------------------------
2073 CGroupMenu::~CGroupMenu()
2077 std::string CGroupMenu::getProperty( const std::string &name ) const
2079 if( name == "extends" )
2081 return _Extends;
2083 else
2084 if( name == "case_mode" )
2086 uint32 cm = _CaseMode;
2087 return toString( cm );
2089 else
2090 if( name == "color" )
2092 return toString( _Color );
2094 else
2095 if( name == "shadow_color" )
2097 return toString( _ShadowColor );
2099 else
2100 if( name == "color_over" )
2102 return toString( _ColorOver );
2104 else
2105 if( name == "shadow_color_over" )
2107 return toString( _ShadowColorOver );
2109 else
2110 if( name == "highlight_over" )
2112 return toString( _HighLightOver );
2114 else
2115 if( name == "color_grayed" )
2117 return toString( _ColorGrayed );
2119 else
2120 if( name == "shadow_color_grayed" )
2122 return toString( _ShadowColorGrayed );
2124 else
2125 if( name == "space" )
2127 return toString( _Space );
2129 else
2130 if( name == "fontsize" )
2132 return toString( _FontSize );
2134 else
2135 if( name == "shadow" )
2137 return toString( _Shadow );
2139 else
2140 if( name == "shadow_outline" )
2142 return toString( _ShadowOutline );
2144 else
2145 if( name == "formatted" )
2147 return toString( _Formatted );
2149 else
2150 if( name == "max_visible_line" )
2152 if( _RootMenu == NULL )
2153 return "0";
2154 else
2155 return toString( _RootMenu->getMaxVisibleLine() );
2157 else
2158 return CGroupModal::getProperty( name );
2161 void CGroupMenu::setProperty( const std::string &name, const std::string &value )
2163 if( name == "extends" )
2165 _Extends = value;
2166 return;
2168 else
2169 if( name == "case_mode" )
2171 uint32 cm;
2172 if( fromString( value, cm ) )
2173 _CaseMode = (TCaseMode)cm;
2174 return;
2176 else
2177 if( name == "color" )
2179 CRGBA c;
2180 if( fromString( value, c ) )
2181 _Color = c;
2182 return;
2184 else
2185 if( name == "shadow_color" )
2187 CRGBA c;
2188 if( fromString( value, c ) )
2189 _ShadowColor = c;
2190 return;
2192 else
2193 if( name == "color_over" )
2195 CRGBA c;
2196 if( fromString( value, c ) )
2197 _ColorOver = c;
2198 return;
2200 else
2201 if( name == "shadow_color_over" )
2203 CRGBA c;
2204 if( fromString( value, c ) )
2205 _ShadowColorOver = c;
2206 return;
2208 else
2209 if( name == "highlight_over" )
2211 CRGBA c;
2212 if( fromString( value, c ) )
2213 _HighLightOver = c;
2214 return;
2216 else
2217 if( name == "color_grayed" )
2219 CRGBA c;
2220 if( fromString( value, c ) )
2221 _ColorGrayed = c;
2222 return;
2224 else
2225 if( name == "shadow_color_grayed" )
2227 CRGBA c;
2228 if( fromString( value, c ) )
2229 _ShadowColorGrayed = c;
2230 return;
2232 else
2233 if( name == "space" )
2235 uint8 i;
2236 if( fromString( value, i ) )
2237 _Space = i;
2238 return;
2240 else
2241 if( name == "fontsize" )
2243 sint32 i;
2244 if( fromString( value, i ) )
2245 _FontSize = i;
2246 return;
2248 else
2249 if( name == "shadow" )
2251 bool b;
2252 if( fromString( value, b ) )
2253 _Shadow = b;
2254 return;
2256 else
2257 if( name == "shadow_outline" )
2259 bool b;
2260 if( fromString( value, b ) )
2261 _ShadowOutline = b;
2262 return;
2264 else
2265 if( name == "formatted" )
2267 bool b;
2268 if( fromString( value, b ) )
2269 _Formatted = b;
2270 return;
2272 else
2273 if( name == "max_visible_line" )
2275 if( _RootMenu != NULL )
2277 sint32 i;
2278 if( fromString( value, i ) )
2279 _RootMenu->setMaxVisibleLine( i );
2281 return;
2283 else
2284 CGroupModal::setProperty( name, value );
2288 xmlNodePtr CGroupMenu::serialize( xmlNodePtr parentNode, const char *type ) const
2290 xmlNodePtr node = CGroupModal::serialize( parentNode, type );
2291 if( node == NULL )
2292 return NULL;
2294 xmlSetProp( node, BAD_CAST "type", BAD_CAST "menu" );
2295 xmlSetProp( node, BAD_CAST "extends", BAD_CAST _Extends.c_str() );
2296 xmlSetProp( node, BAD_CAST "case_mode", BAD_CAST toString( uint32( _CaseMode ) ).c_str() );
2297 xmlSetProp( node, BAD_CAST "color", BAD_CAST toString( _Color ).c_str() );
2298 xmlSetProp( node, BAD_CAST "shadow_color", BAD_CAST toString( _ShadowColor ).c_str() );
2299 xmlSetProp( node, BAD_CAST "color_over", BAD_CAST toString( _ColorOver ).c_str() );
2300 xmlSetProp( node, BAD_CAST "shadow_color_over", BAD_CAST toString( _ShadowColorOver ).c_str() );
2301 xmlSetProp( node, BAD_CAST "highlight_over", BAD_CAST toString( _HighLightOver ).c_str() );
2302 xmlSetProp( node, BAD_CAST "color_grayed", BAD_CAST toString( _ColorGrayed ).c_str() );
2303 xmlSetProp( node, BAD_CAST "shadow_color_grayed", BAD_CAST toString( _ShadowColorGrayed ).c_str() );
2304 xmlSetProp( node, BAD_CAST "space", BAD_CAST toString( _Space ).c_str() );
2305 xmlSetProp( node, BAD_CAST "fontsize", BAD_CAST toString( _FontSize ).c_str() );
2306 xmlSetProp( node, BAD_CAST "shadow", BAD_CAST toString( _Shadow ).c_str() );
2307 xmlSetProp( node, BAD_CAST "shadow_outline", BAD_CAST toString( _ShadowOutline ).c_str() );
2308 xmlSetProp( node, BAD_CAST "formatted", BAD_CAST toString( _Formatted ).c_str() );
2310 if( _RootMenu == NULL )
2311 xmlSetProp( node, BAD_CAST "max_visible_line", BAD_CAST "0" );
2312 else
2313 xmlSetProp( node, BAD_CAST "max_visible_line",
2314 BAD_CAST toString( _RootMenu->getMaxVisibleLine() ).c_str() );
2316 return NULL;
2319 // ------------------------------------------------------------------------------------------------
2320 bool CGroupMenu::parse (xmlNodePtr in, CInterfaceGroup *parentGroup)
2322 CXMLAutoPtr prop;
2324 _FontSize = 12;
2326 // override source menu options (if there's one)
2327 if (!CGroupModal::parse(in, parentGroup))
2328 return false;
2331 // see if this menu extends another menu
2332 prop= (char*) xmlGetProp( in, (xmlChar*)"extends" );
2333 CGroupSubMenu *gmExtended = NULL;
2334 if (prop)
2336 if( editorMode )
2337 _Extends = std::string( (const char*)prop );
2339 CGroupMenu *gm = dynamic_cast<CGroupMenu *>(CWidgetManager::getInstance()->getElementFromId(prop.str()));
2340 if (!gm)
2342 gm = dynamic_cast<CGroupMenu *>(CWidgetManager::getInstance()->getElementFromId("ui:interface:" + std::string((const char*)prop)));
2344 if (gm)
2346 gmExtended = gm->_RootMenu;
2347 // copy group frame parameters
2348 CGroupFrame::copyOptionFrom(*gm);
2349 // copy basic datas
2350 _Color = gm->_Color;
2351 _ShadowColor = gm->_ShadowColor;
2352 _Shadow = gm->_Shadow;
2353 _ShadowOutline = gm->_ShadowOutline;
2354 _FontSize = gm->_FontSize;
2355 _ColorOver = gm->_ColorOver;
2356 _ShadowColorOver = gm->_ShadowColorOver;
2357 _HighLightOver = gm->_HighLightOver;
2358 _ColorGrayed = gm->_ColorGrayed;
2359 _ShadowColorGrayed = gm->_ShadowColorGrayed;
2360 _Priority = gm->_Priority;
2361 _ModulateGlobalColor = gm->_ModulateGlobalColor;
2362 _Space = gm->_Space;
2363 _CaseMode = gm->_CaseMode;
2365 else
2367 nlwarning("Can't get menu %s or bad type", (const char *) prop);
2372 // Override the modal behaviour because of sub menus
2373 ExitClickOut = true;
2374 ExitClickL = false;
2375 ExitClickR = false;
2376 ExitKeyPushed = true;
2377 _ResizeFromChildH = _ResizeFromChildW = true;
2378 _DisplayFrame = false;
2379 _Active = false;
2380 _Formatted = false;
2382 // text colors
2383 prop= (char*) xmlGetProp( in, (xmlChar*)"color" );
2384 if (prop) _Color = convertColor(prop);
2386 prop = (char*) xmlGetProp( in, (xmlChar*)"case_mode" );
2387 if (prop)
2389 sint32 caseMode;
2390 fromString((const char*)prop, caseMode);
2391 _CaseMode = (TCaseMode)caseMode;
2394 prop= (char*) xmlGetProp( in, (xmlChar*)"shadow_color" );
2395 if (prop) _ShadowColor = convertColor(prop);
2397 prop= (char*) xmlGetProp( in, (xmlChar*)"color_over" );
2398 if (prop) _ColorOver = convertColor(prop);
2400 prop= (char*) xmlGetProp( in, (xmlChar*)"shadow_color_over" );
2401 if (prop) _ShadowColorOver = convertColor(prop);
2403 prop= (char*) xmlGetProp( in, (xmlChar*)"highlight_over" );
2404 if (prop) _HighLightOver = convertColor(prop);
2406 prop= (char*) xmlGetProp( in, (xmlChar*)"color_grayed" );
2407 if (prop) _ColorGrayed = convertColor(prop);
2409 prop= (char*) xmlGetProp( in, (xmlChar*)"shadow_color_grayed" );
2410 if (prop) _ShadowColorGrayed = convertColor(prop);
2412 prop = (char*) xmlGetProp (in, (xmlChar*)"space");
2413 if (prop) fromString((const char*)prop, _Space);
2415 // Text props
2416 prop = (char*) xmlGetProp( in, (xmlChar*)"fontsize" );
2417 if (prop) fromString((const char*)prop, _FontSize);
2419 prop = (char*) xmlGetProp( in, (xmlChar*)"shadow" );
2420 if (prop)
2421 _Shadow = convertBool(prop);
2423 prop = (char*) xmlGetProp( in, (xmlChar*)"shadow_outline" );
2424 if (prop)
2425 _ShadowOutline = convertBool(prop);
2427 prop = (char*) xmlGetProp( in, (xmlChar*)"formatted" );
2428 if (prop)
2429 _Formatted = convertBool(prop);
2432 // Read sons
2433 xmlNodePtr cur;
2434 cur = in->children;
2435 if (_RootMenu != NULL) delete _RootMenu;
2436 _RootMenu = new CGroupSubMenu(CViewText::TCtorParam());
2437 _RootMenu->setId( getId() + ":header" );
2438 _RootMenu->setSerializable( false );
2439 _RootMenu->_GroupMenu = this;
2440 _RootMenu->parse (cur);
2442 prop = (char*) xmlGetProp( in, (xmlChar*)"max_visible_line" );
2443 if (prop)
2445 sint32 maxVisibleLine;
2446 fromString((const char*)prop, maxVisibleLine);
2447 _RootMenu->setMaxVisibleLine(maxVisibleLine);
2450 if (gmExtended)
2452 gmExtended->cloneMenu(_RootMenu, this);
2454 return true;
2457 // ------------------------------------------------------------------------------------------------
2458 void CGroupMenu::recurseDraw(CGroupSubMenu *pSubMenu)
2460 pSubMenu->draw();
2462 // const vector<CInterfaceGroup*> &rGroups = pSubMenu->getGroups();
2464 for (uint32 i = 0; i < pSubMenu->getNumLines(); i++)
2466 CGroupSubMenu *pGSM = pSubMenu->getSubMenu(i);
2467 if (pGSM != NULL)
2469 recurseDraw(pGSM);
2470 CViewRenderer::getInstance()->flush();
2475 // ------------------------------------------------------------------------------------------------
2476 void CGroupMenu::draw ()
2478 if (!_Active) return;
2480 // TEMP TEMP
2481 //CViewRenderer &rVR = *CViewRenderer::getInstance();
2482 //rVR.drawRotFlipBitmap _RenderLayer, (_XReal, _YReal, _WReal, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(255, 0, 0, 255) );
2484 _RootMenu->_Active = true;
2486 if (SpawnOnMousePos)
2487 recurseDraw(_RootMenu);
2488 else
2489 CGroupModal::draw();
2492 // ------------------------------------------------------------------------------------------------
2493 bool CGroupMenu::handleEvent (const NLGUI::CEventDescriptor &event)
2495 if (!_Active)
2496 return false;
2497 return CGroupModal::handleEvent (event);
2500 // ------------------------------------------------------------------------------------------------
2501 CInterfaceElement* CGroupMenu::getElement (const std::string &id)
2503 if (id == getId()) return this;
2504 CInterfaceElement *pIE = _RootMenu->getElement(id);
2505 if (pIE != NULL)
2506 return pIE;
2507 return CGroupModal::getElement(id);
2510 // ------------------------------------------------------------------------------------------------
2511 void CGroupMenu::setActive (bool state)
2513 if (SpawnOnMousePos)
2515 CViewRenderer &rVR = *CViewRenderer::getInstance();
2516 uint32 w,h;
2517 rVR.getScreenSize(w,h);
2518 setW(w);
2519 setH(h);
2520 setX(0);
2521 setY(0);
2522 _ResizeFromChildH = _ResizeFromChildW = false;
2523 _RootMenu->_PosRef = Hotspot_TL;
2524 _RootMenu->_ParentPosRef = Hotspot_BL;
2527 CGroupFrame::setActive (state);
2529 // must recompute now the pos of the menu
2530 uint32 i;
2531 for (i = 0; i < _ChildrenGroups.size(); ++i)
2533 _ChildrenGroups[i]->setActive (true);
2536 CGroupModal::updateCoords();
2538 // hide sub menus
2539 _RootMenu->hideSubMenus();
2542 // ------------------------------------------------------------------------------------------------
2543 bool CGroupSubMenu::isSeparator(uint i) const
2545 if (i >= _SubMenus.size())
2547 nlassert("bad index");
2548 return false;
2550 return _Lines[i].Separator != NULL;
2552 // ------------------------------------------------------------------------------------------------
2553 bool CGroupMenu::isWindowUnder (sint32 x, sint32 y)
2555 for (uint32 i = 0; i < _ChildrenGroups.size(); ++i)
2556 if (_ChildrenGroups[i]->getActive ())
2557 if (_ChildrenGroups[i]->isWindowUnder(x, y))
2558 return true;
2560 return false;
2563 // ------------------------------------------------------------------------------------------------
2564 void CGroupMenu::addLine(const std::string &name, const std::string &ah, const std::string &params,
2565 const std::string &id /* = std::string()*/,
2566 const std::string &cond /*= std::string()*/, const std::string &texture,
2567 bool checkable /*= false*/, bool checked /*= false*/
2570 if (_RootMenu == NULL)
2572 _RootMenu = new CGroupSubMenu(CViewText::TCtorParam());
2573 _RootMenu->_GroupMenu = this;
2574 _RootMenu->setSerializable( false );
2575 addGroup (_RootMenu);
2577 _RootMenu->addLine (name, ah, params, id, cond, texture, checkable, checked, _Formatted);
2579 // ------------------------------------------------------------------------------------------------
2580 void CGroupMenu::addLineAtIndex(uint index, const std::string &name, const std::string &ah,
2581 const std::string &params, const std::string &id /*=std::string()*/,
2582 const std::string &cond /*=std::string()*/, const std::string &texture,
2583 bool checkable /*=false*/, bool checked /*=false*/)
2585 if (_RootMenu == NULL)
2587 _RootMenu = new CGroupSubMenu(CViewText::TCtorParam());
2588 _RootMenu->_GroupMenu = this;
2589 _RootMenu->setSerializable( false );
2590 addGroup (_RootMenu);
2592 _RootMenu->addLineAtIndex(index, name, ah, params, id, cond, texture, checkable, checked, _Formatted);
2596 // ------------------------------------------------------------------------------------------------
2597 void CGroupMenu::reset ()
2599 if ( _RootMenu )
2601 _RootMenu->reset();
2602 invalidateCoords();
2606 // ------------------------------------------------------------------------------------------------
2607 void CGroupMenu::setMinW(sint32 minW)
2609 if ( _RootMenu )
2611 _RootMenu->_GroupList->setMinW(minW-_RootMenu->getResizeFromChildWMargin());
2612 _RootMenu->_GroupList->setW(minW-_RootMenu->getResizeFromChildWMargin());
2613 _RootMenu->setW(minW-_RootMenu->getResizeFromChildWMargin());
2617 // ------------------------------------------------------------------------------------------------
2618 void CGroupMenu::setMinH(sint32 minH)
2620 if ( _RootMenu )
2622 _RootMenu->_GroupList->setMinH(minH-_RootMenu->getResizeFromChildHMargin());
2623 _RootMenu->_GroupList->setH(minH-_RootMenu->getResizeFromChildHMargin());
2624 _RootMenu->setH(minH-_RootMenu->getResizeFromChildHMargin());
2628 // ------------------------------------------------------------------------------------------------
2629 void CGroupMenu::setGrayedLine(uint line, bool g)
2631 if ( _RootMenu )
2633 _RootMenu->setGrayedLine(line, g);
2637 // ------------------------------------------------------------------------------------------------
2638 void CGroupMenu::setFontSize(uint fontSize, bool coef)
2640 _FontSize = fontSize;
2641 _FontSizeCoef = coef;
2644 // ------------------------------------------------------------------------------------------------
2645 uint CGroupMenu::getNumLine() const
2647 return _RootMenu ? _RootMenu->getNumLine() : 0;
2650 // ------------------------------------------------------------------------------------------------
2651 void CGroupMenu::deleteLine(uint index)
2653 if (index > getNumLine())
2655 nlwarning("bad index");
2656 return;
2658 _RootMenu->removeLine(index);
2661 // ------------------------------------------------------------------------------------------------
2662 const std::string CGroupMenu::getActionHandler(uint lineIndex) const
2664 return _RootMenu ? _RootMenu->getActionHandler(lineIndex) : "";
2667 // ------------------------------------------------------------------------------------------------
2668 const std::string CGroupMenu::getActionHandlerParam(uint lineIndex) const
2670 return _RootMenu ? _RootMenu->getActionHandlerParam(lineIndex) : "";
2673 // ------------------------------------------------------------------------------------------------
2674 void CGroupMenu::setActionHandler(uint lineIndex, const std::string &ah)
2676 if (_RootMenu)
2677 _RootMenu->setActionHandler(lineIndex, ah);
2680 // ------------------------------------------------------------------------------------------------
2681 void CGroupMenu::setActionHandlerParam(uint lineIndex, const std::string &params)
2683 if (_RootMenu)
2684 _RootMenu->setActionHandlerParam(lineIndex, params);
2687 // ------------------------------------------------------------------------------------------------
2688 void CGroupMenu::setRightClickHandler(uint lineIndex, const std::string &ah)
2690 if (_RootMenu)
2691 _RootMenu->setRightClickHandler(lineIndex, ah);
2694 // ------------------------------------------------------------------------------------------------
2695 void CGroupMenu::setRightClickHandlerParam(uint lineIndex, const std::string &params)
2697 if (_RootMenu)
2698 _RootMenu->setRightClickHandlerParam(lineIndex, params);
2701 // ------------------------------------------------------------------------------------------------
2702 void CGroupMenu::setUserGroupRight(uint line, CInterfaceGroup *gr, bool ownerShip /*=true*/)
2704 if (_RootMenu)
2706 _RootMenu->setUserGroupRight(line, gr, ownerShip);
2710 // ------------------------------------------------------------------------------------------------
2711 void CGroupMenu::setUserGroupLeft(uint line, CInterfaceGroup *gr, bool ownerShip /*=true*/)
2713 if (_RootMenu)
2715 _RootMenu->setUserGroupLeft(line, gr, ownerShip);
2719 // ------------------------------------------------------------------------------------------------
2720 int CGroupMenu::luaGetRootMenu(CLuaState &ls)
2722 CLuaIHM::checkArgCount(ls, "getRootMenu", 0);
2723 CLuaIHM::pushUIOnStack(ls, getRootMenu());
2724 return 1;
2727 // ------------------------------------------------------------------------------------------------
2728 int CGroupMenu::luaSetMinW(CLuaState &ls)
2730 const char *funcName = "setMinW";
2731 CLuaIHM::checkArgCount(ls, funcName, 1);
2732 CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
2733 setMinW((sint32) ls.toInteger(1));
2734 return 0;