2300 lines
67 KiB
C++
2300 lines
67 KiB
C++
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
|
// Copyright (C) 2010 Winch Gate Property Limited
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
#include "stdpch.h"
|
|
#include "interface_manager.h"
|
|
#include "interface_expr.h"
|
|
#include "group_menu.h"
|
|
#include "game_share/xml_auto_ptr.h"
|
|
#include "view_bitmap.h"
|
|
#include "action_handler.h" // Just for getAllParams
|
|
#include "lua_ihm.h"
|
|
|
|
#include "nel/misc/i18n.h"
|
|
|
|
using namespace NLMISC;
|
|
using namespace std;
|
|
|
|
|
|
static const std::string ID_MENU_CHECKBOX = "menu_cb";
|
|
static const std::string ID_MENU_SEPARATOR = "menu_separator";
|
|
static const std::string ID_MENU_SUBMENU = "menu_sb";
|
|
|
|
static const uint MENU_WIDGET_X = 2;
|
|
static const uint LEFT_MENU_WIDGET_X = 4;
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
// CGroupSubMenu
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
bool CViewTextMenu::getGrayed() const
|
|
{
|
|
return _Grayed;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CViewTextMenu::setGrayed (bool g)
|
|
{
|
|
_Grayed = g;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CViewTextMenu::setCheckable(bool c)
|
|
{
|
|
if (!c)
|
|
{
|
|
_Checkable = false;
|
|
_CheckBox = NULL;
|
|
}
|
|
else
|
|
{
|
|
_Checkable = true;
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CViewTextMenu::setChecked(bool c)
|
|
{
|
|
if (_CheckBox)
|
|
{
|
|
CInterfaceOptions *pIO = CInterfaceManager::getInstance()->getOptions("menu_checkbox");
|
|
if (!pIO) return;
|
|
_CheckBox->setTexture(pIO->getValStr(c ? "checked_bitmap" : "unchecked_bitmap"));
|
|
}
|
|
_Checked = c;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
sint32 CViewTextMenu::getAlpha() const
|
|
{
|
|
if (_Grayed)
|
|
{
|
|
return OldColorGrayed.A;
|
|
}
|
|
else
|
|
{
|
|
if (Over)
|
|
return OldColorOver.A;
|
|
else
|
|
return OldColor.A;
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CViewTextMenu::setAlpha (sint32 a)
|
|
{
|
|
OldShadowColor.A = OldColor.A = (uint8)a;
|
|
OldShadowColorOver.A = OldColorOver.A = (uint8)a;
|
|
OldShadowColorGrayed.A = OldShadowColorGrayed.A = (uint8)a;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
// CGroupSubMenu
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CGroupSubMenu::CGroupSubMenu(const TCtorParam ¶m)
|
|
: CGroupFrame(param)
|
|
{
|
|
_SelectionView = NULL;
|
|
_GroupList = NULL;
|
|
_GroupMenu = NULL;
|
|
_Selected = -1;
|
|
_MaxVisibleLine = -1;
|
|
_ScrollBar = NULL;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CGroupSubMenu::~CGroupSubMenu()
|
|
{
|
|
removeAllUserGroups();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
sint CGroupSubMenu::getLineFromId(const std::string &id)
|
|
{
|
|
for (uint k = 0; k < _Lines.size(); ++k)
|
|
{
|
|
if (_Lines[k].Id == id)
|
|
{
|
|
return (sint) k;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CGroupSubMenu *CGroupSubMenu::getSubMenu(uint index) const
|
|
{
|
|
if (index >= _SubMenus.size())
|
|
{
|
|
nlassert("bad index");
|
|
return NULL;
|
|
}
|
|
return _SubMenus[index];
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::setSubMenu(uint index, CGroupSubMenu *sub)
|
|
{
|
|
nlassert(sub != NULL);
|
|
nlassert(index < _SubMenus.size());
|
|
|
|
if (_SubMenus[index] != NULL)
|
|
{
|
|
// must delete from the group menu (if not found, just delete)
|
|
if( !_GroupMenu || !_GroupMenu->delGroup(_SubMenus[index]) )
|
|
delete _SubMenus[index];
|
|
_SubMenus[index] = NULL;
|
|
delView(_Lines[index].RightArrow);
|
|
}
|
|
|
|
if (_Lines[index].CheckBox)
|
|
_Lines[index].RightArrow = createRightArrow(_Lines[index].CheckBox, true);
|
|
else
|
|
_Lines[index].RightArrow = createRightArrow(_GroupList, false);
|
|
|
|
sub->_GroupMenu = _GroupMenu;
|
|
sub->initOptions(this);
|
|
_GroupMenu->addGroup (sub);
|
|
sub->_DispType = _GroupMenu->_DispType;
|
|
_SubMenus[index] = sub;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::initOptions(CInterfaceGroup *parent)
|
|
{
|
|
// Initialization
|
|
// me
|
|
_Parent = _GroupMenu;
|
|
if (parent == NULL)
|
|
{
|
|
setParentPos (_GroupMenu);
|
|
setParentPosRef (Hotspot_TL);
|
|
setPosRef (Hotspot_TL);
|
|
}
|
|
else
|
|
{
|
|
setParentPos (parent);
|
|
setParentPosRef (Hotspot_BR);
|
|
setPosRef (Hotspot_BL);
|
|
}
|
|
_DisplayFrame = true;
|
|
_ResizeFromChildH = true;
|
|
_ResizeFromChildW = true;
|
|
_ResizeFromChildHMargin = 8;
|
|
_ResizeFromChildWMargin = 8;
|
|
_ModulateGlobalColor = _GroupMenu->_ModulateGlobalColor;
|
|
// the selection
|
|
if (_SelectionView == NULL)
|
|
{
|
|
_SelectionView = new CViewBitmap(CViewBase::TCtorParam());
|
|
// CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
|
// CViewRenderer &rVR = pIM->getViewRenderer();
|
|
_SelectionView->setParent (this);
|
|
_SelectionView->setActive (false);
|
|
_SelectionView->setTexture ("blank.tga");
|
|
_SelectionView->setScale (true);
|
|
_SelectionView->setX (4);
|
|
_SelectionView->setSizeRef(1); // sizeref on W
|
|
_SelectionView->setW (-8);
|
|
addView (_SelectionView, 0);
|
|
}
|
|
// the group list
|
|
if (_GroupList == NULL)
|
|
{
|
|
_GroupList = new CGroupList(CViewBase::TCtorParam());
|
|
_GroupList->setParent (this);
|
|
_GroupList->setParentPos (this);
|
|
_GroupList->setX (4);
|
|
_GroupList->setY (4);
|
|
_GroupList->setSpace (_GroupMenu->_Space);
|
|
addGroup (_GroupList);
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
bool CGroupSubMenu::parse (xmlNodePtr cur, CInterfaceGroup *parent)
|
|
{
|
|
initOptions(parent);
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
// the children
|
|
while (cur)
|
|
{
|
|
CViewTextMenu *pV = NULL;
|
|
|
|
CXMLAutoPtr id((const char*) xmlGetProp (cur, (xmlChar*)"id"));
|
|
|
|
if (stricmp((char*)cur->name, "separator") == 0)
|
|
{
|
|
if (id)
|
|
{
|
|
addSeparator((const char *) id);
|
|
}
|
|
else
|
|
{
|
|
addSeparator();
|
|
}
|
|
}
|
|
else
|
|
if (stricmp((char*)cur->name, "action") == 0)
|
|
{
|
|
string strId, strAh, strParams, strCond, strTexture="";
|
|
ucstring ucstrName;
|
|
|
|
if (id) strId = (const char*)id;
|
|
CXMLAutoPtr name((const char*) xmlGetProp (cur, (xmlChar*)"name"));
|
|
|
|
if (name)
|
|
{
|
|
const char *ptrName = (const char*)name;
|
|
ucstrName = ucstring(ptrName);
|
|
if ((strlen(ptrName)>2) && (ptrName[0] == 'u') && (ptrName[1] == 'i'))
|
|
ucstrName = CI18N::get (ptrName);
|
|
}
|
|
|
|
CXMLAutoPtr ah((const char*) xmlGetProp (cur, (xmlChar*)"handler"));
|
|
if (ah) strAh = (const char*)ah;
|
|
CXMLAutoPtr cond((const char*) xmlGetProp (cur, (xmlChar*)"cond"));
|
|
if (cond) strCond = (const char*)cond;
|
|
CXMLAutoPtr params((const char*) xmlGetProp (cur, (xmlChar*)"params"));
|
|
if (params) strParams = (const char*)params;
|
|
CXMLAutoPtr strCheckable((const char*) xmlGetProp (cur, (xmlChar*)"checkable"));
|
|
bool bCheckable = false;
|
|
if (strCheckable) bCheckable = convertBool (strCheckable);
|
|
CXMLAutoPtr strChecked((const char*) xmlGetProp (cur, (xmlChar*)"checked"));
|
|
bool bChecked = false;
|
|
if (strChecked) bChecked = convertBool (strChecked);
|
|
bool bFormatted = false;
|
|
CXMLAutoPtr strFormatted((const char*) xmlGetProp (cur, (xmlChar*)"formatted"));
|
|
if (strFormatted) bFormatted = convertBool (strFormatted);
|
|
|
|
pV = addLine (ucstrName, strAh, strParams, strId, strCond, strTexture, bCheckable, bChecked, bFormatted);
|
|
|
|
CXMLAutoPtr strSelectable((const char*) xmlGetProp (cur, (xmlChar*)"selectable"));
|
|
bool bSelectable = true;
|
|
if (strSelectable) bSelectable = convertBool (strSelectable);
|
|
_Lines.back().Selectable = bSelectable;
|
|
|
|
|
|
CXMLAutoPtr grayed((const char*) xmlGetProp (cur, (xmlChar*)"grayed"));
|
|
bool bGrayed = false;
|
|
if (grayed) bGrayed = convertBool (grayed);
|
|
pV->setGrayed(bGrayed);
|
|
|
|
// Is this line has a sub menu ?
|
|
xmlNodePtr child = cur->children;
|
|
if (child != NULL)
|
|
{
|
|
if (_Lines.back().CheckBox)
|
|
{
|
|
_Lines.back().RightArrow = createRightArrow(_Lines.back().CheckBox, true);
|
|
}
|
|
else
|
|
{
|
|
_Lines.back().RightArrow = createRightArrow(_GroupList, false);
|
|
}
|
|
// and create the sub menu
|
|
CGroupSubMenu *childMenu = new CGroupSubMenu(CViewText::TCtorParam());
|
|
childMenu->_GroupMenu = _GroupMenu;
|
|
childMenu->parse (child, this);
|
|
|
|
CXMLAutoPtr MVL((const char*) xmlGetProp(cur, (xmlChar*)"max_visible_line"));
|
|
if (MVL)
|
|
{
|
|
sint32 maxVisibleLine;
|
|
fromString((const char*)MVL, maxVisibleLine);
|
|
childMenu->setMaxVisibleLine(maxVisibleLine);
|
|
}
|
|
|
|
_SubMenus.back() = childMenu;
|
|
}
|
|
|
|
// Add user groups
|
|
// Left
|
|
CXMLAutoPtr usergroup((const char*) xmlGetProp (cur, (xmlChar*)"usergroup_l"));
|
|
if (usergroup)
|
|
{
|
|
vector< pair<string,string> > vparams;
|
|
CXMLAutoPtr ugparams((const char*) xmlGetProp (cur, (xmlChar*)"usergroup_params_l"));
|
|
if (ugparams)
|
|
{
|
|
IActionHandler::getAllParams((const char*)ugparams, vparams);
|
|
}
|
|
|
|
string completeId = _Parent->getId() + ":" + _Lines[_Lines.size()-1].Id;
|
|
CInterfaceGroup *pUGLeft = im->createGroupInstance((const char*)usergroup, completeId, vparams);
|
|
if (pUGLeft)
|
|
setUserGroupLeft(_Lines.size()-1, pUGLeft, true);
|
|
}
|
|
usergroup = (char*) xmlGetProp (cur, (xmlChar*)"usergroup_r");
|
|
if (usergroup)
|
|
{
|
|
vector< pair<string,string> > vparams;
|
|
CXMLAutoPtr ugparams((const char*) xmlGetProp (cur, (xmlChar*)"usergroup_params_r"));
|
|
if (ugparams)
|
|
{
|
|
IActionHandler::getAllParams((const char*)ugparams, vparams);
|
|
}
|
|
|
|
string completeId = _Parent->getId() + ":" + _Lines[_Lines.size()-1].Id;
|
|
CInterfaceGroup *pUG = im->createGroupInstance((const char*)usergroup, completeId, vparams);
|
|
if (pUG)
|
|
setUserGroupRight(_Lines.size()-1, pUG, true);
|
|
}
|
|
}
|
|
cur = cur->next;
|
|
}
|
|
|
|
_GroupMenu->addGroup (this);
|
|
this->_DispType = _GroupMenu->_DispType;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CViewBitmap *CGroupSubMenu::createCheckBox(bool checked)
|
|
{
|
|
// Put the left arrow to the line
|
|
CViewBitmap *pVB = new CViewBitmap(CViewBase::TCtorParam());
|
|
pVB->setParent (this);
|
|
pVB->setParentPos (_GroupList);
|
|
pVB->setParentPosRef (Hotspot_BR);
|
|
pVB->setPosRef (Hotspot_BL);
|
|
CInterfaceOptions *pIO = CInterfaceManager::getInstance()->getOptions("menu_checkbox");
|
|
if (pIO)
|
|
{
|
|
pVB->setTexture(pIO->getValStr(checked ? "checked_bitmap" : "unchecked_bitmap"));
|
|
}
|
|
pVB->setX (MENU_WIDGET_X);
|
|
pVB->setId (ID_MENU_CHECKBOX); // always rescale to parent in update coords
|
|
addView (pVB);
|
|
return pVB;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CViewBitmap *CGroupSubMenu::createRightArrow(CInterfaceElement *parentPos, bool center)
|
|
{
|
|
// Put the left arrow to the line
|
|
CViewBitmap *pVB = new CViewBitmap(CViewBase::TCtorParam());
|
|
pVB->setParent (this);
|
|
pVB->setParentPos (parentPos);
|
|
if (!center)
|
|
{
|
|
pVB->setParentPosRef (Hotspot_BR);
|
|
pVB->setPosRef (Hotspot_BL);
|
|
}
|
|
else
|
|
{
|
|
pVB->setParentPosRef (Hotspot_MR);
|
|
pVB->setPosRef (Hotspot_ML);
|
|
}
|
|
pVB->setTexture("w_arrow_right_3.tga");
|
|
pVB->setX (MENU_WIDGET_X);
|
|
pVB->setId (ID_MENU_SUBMENU); // rescale to parent in update coords if asked (not needed if there's already on the left a checkbox)
|
|
addView (pVB);
|
|
return pVB;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
#define GET_REF_ELM(__index__) \
|
|
CInterfaceElement *refElm; \
|
|
sint32 refElmYReal= 0; \
|
|
sint32 refElmHReal= 0; \
|
|
refElm = _Lines[__index__].ViewText; \
|
|
if(refElm) \
|
|
{ \
|
|
refElmYReal= refElm->getYReal() - _Lines[__index__].TextDY; \
|
|
refElmHReal= _Lines[__index__].HReal; \
|
|
}
|
|
|
|
void CGroupSubMenu::updateCoords ()
|
|
{
|
|
if (_ParentPos == _GroupMenu)
|
|
{
|
|
// Root Menu
|
|
setX(_GroupMenu->SpawnMouseX);
|
|
setY(_GroupMenu->SpawnMouseY);
|
|
CGroupFrame::updateCoords();
|
|
|
|
CViewRenderer &rVR = CInterfaceManager::getInstance()->getViewRenderer();
|
|
uint32 screenW, screenH;
|
|
rVR.getScreenSize(screenW, screenH);
|
|
if ((_XReal+_WReal) > (sint32)screenW)
|
|
setX(screenW-_WReal);
|
|
if (_YReal < 0)
|
|
setY(_HReal);
|
|
}
|
|
else
|
|
// The sub menu may go outside the screen in Y. => clamp it as possible
|
|
{
|
|
/* X/Y coords have normally been updated before by "parent" sub menus
|
|
Why? because setSubMenu() is typically called in "parent first" order (or it is exactly what is done in ::parse())
|
|
=> Parent CGroupSubMenu::updateCoords() are called before their sons in CGroupMenu::updateCoords() !!!
|
|
=> No Need to call _SubMenus[RALineNb]->updateCoords() below ! (else would call too much time because of recursion!!)
|
|
*/
|
|
|
|
// must udpate correct Real coords
|
|
CGroupFrame::updateCoords();
|
|
|
|
// get screen size
|
|
CViewRenderer &rVR = CInterfaceManager::getInstance()->getViewRenderer();
|
|
uint32 screenW, screenH;
|
|
rVR.getScreenSize(screenW, screenH);
|
|
|
|
sint32 hReal= getHReal();
|
|
// If the H is too big, abort.. can't do anything
|
|
if(hReal<=(sint32)screenH)
|
|
{
|
|
sint32 yReal= getYReal();
|
|
|
|
// compute the shift to apply to the Y of the sub menu, to respect (as possible) the screen
|
|
sint32 dyClamp= 0;
|
|
if(yReal<0)
|
|
dyClamp= - yReal;
|
|
if(yReal+hReal>(sint32)screenH)
|
|
dyClamp= screenH - (yReal+hReal);
|
|
// change then the Y
|
|
if(dyClamp!=0)
|
|
{
|
|
setY(getY()+dyClamp);
|
|
CGroupFrame::updateCoords();
|
|
}
|
|
}
|
|
}
|
|
|
|
// not yet setuped?
|
|
if (!_GroupList) return;
|
|
|
|
// get text dy position
|
|
sint32 textDYPos= 0;
|
|
textDYPos= -(1+_GroupList->getSpace())/2;
|
|
|
|
// Set the arrows at the right positions (in _Views we have selection and the right arrows)
|
|
sint32 CBLineNb = 0; // check box
|
|
sint32 RALineNb = 0; // right arrow
|
|
uint32 i;
|
|
|
|
sint32 maxUserGroupWidth = 0;
|
|
// compute max width of user groups, & adapt max height for each line
|
|
uint k;
|
|
|
|
// update all left user groups to get their width
|
|
sint32 maxLeftUGWidth = 0;
|
|
for(k = 0; k < _Lines.size(); ++k)
|
|
{
|
|
if (_Lines[k].UserGroupLeft)
|
|
{
|
|
_Lines[k].UserGroupLeft->updateCoords();
|
|
maxLeftUGWidth = std::max(_Lines[k].UserGroupLeft->getWReal(), maxLeftUGWidth);
|
|
}
|
|
}
|
|
|
|
_GroupList->setX(LEFT_MENU_WIDGET_X + maxLeftUGWidth);
|
|
|
|
// active separators when needed
|
|
bool activeLineSeen = false;
|
|
for (i = 0; i < _Lines.size(); ++i)
|
|
{
|
|
if (_Lines[i].Separator != NULL)
|
|
{
|
|
if (i == _Lines.size() - 1)
|
|
{
|
|
_Lines[i].Separator->setActive(false);
|
|
break;
|
|
}
|
|
_Lines[i].Separator->setActive(activeLineSeen);
|
|
activeLineSeen = false;
|
|
}
|
|
else
|
|
{
|
|
if (_Lines[i].ViewText && _Lines[i].ViewText->getActive()) activeLineSeen = true;
|
|
}
|
|
}
|
|
|
|
CGroupFrame::updateCoords();
|
|
|
|
bool mustUpdate = false;
|
|
|
|
if (_MaxVisibleLine > 0 && sint32(_Lines.size())>_MaxVisibleLine)
|
|
{
|
|
for(k = 0; k < _Lines.size(); ++k)
|
|
if (_Lines[k].ViewText)
|
|
{
|
|
// compute max height of widgets on the left of text
|
|
sint32 widgetMaxH = 0;
|
|
if (_Lines[k].UserGroupRight) widgetMaxH = _Lines[k].UserGroupRight->getHReal();
|
|
if (_Lines[k].UserGroupLeft) widgetMaxH = std::max(widgetMaxH, _Lines[k].UserGroupLeft->getHReal());
|
|
if (_Lines[k].CheckBox) widgetMaxH = std::max(widgetMaxH, _Lines[k].CheckBox->getHReal());
|
|
if (_Lines[k].RightArrow) widgetMaxH = std::max(widgetMaxH, _Lines[k].RightArrow->getHReal());
|
|
widgetMaxH = std::max(widgetMaxH, _Lines[k].ViewText->getHReal());
|
|
_GroupList->setMaxH(widgetMaxH*_MaxVisibleLine+_GroupList->getSpace()*(_MaxVisibleLine-1));
|
|
if (_ScrollBar == NULL)
|
|
{
|
|
_ScrollBar = new CCtrlScroll(CViewBase::TCtorParam());
|
|
_ScrollBar->setParent (this);
|
|
_ScrollBar->setParentPos (_GroupList);
|
|
_ScrollBar->setPosRef (Hotspot_BL);
|
|
_ScrollBar->setParentPosRef (Hotspot_BR);
|
|
_ScrollBar->setX (4);
|
|
_ScrollBar->setY (0);
|
|
_ScrollBar->setW (8);
|
|
_ScrollBar->setTextureBottomOrLeft ("w_scroll_l123_b.tga");
|
|
_ScrollBar->setTextureMiddle ("w_scroll_l123_m.tga");
|
|
_ScrollBar->setTextureTopOrRight ("w_scroll_l123_t.tga");
|
|
_ScrollBar->setTarget(_GroupList);
|
|
_SelectionView->setW (-8-8-2);
|
|
addCtrl(_ScrollBar);
|
|
mustUpdate = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_SelectionView->setW(-8);
|
|
}
|
|
|
|
|
|
// *** Setup Text
|
|
for(k = 0; k < _Lines.size(); ++k)
|
|
{
|
|
CInterfaceGroup *ig = _Lines[k].UserGroupRight;
|
|
if (ig)
|
|
{
|
|
ig->updateCoords();
|
|
maxUserGroupWidth = std::max(maxUserGroupWidth, ig->getWReal());
|
|
}
|
|
if (_Lines[k].ViewText)
|
|
{
|
|
// compute max height of widgets on the left of text
|
|
sint32 widgetMaxH = 0;
|
|
if (_Lines[k].UserGroupRight) widgetMaxH = _Lines[k].UserGroupRight->getHReal();
|
|
if (_Lines[k].UserGroupLeft) widgetMaxH = std::max(widgetMaxH, _Lines[k].UserGroupLeft->getHReal());
|
|
if (_Lines[k].CheckBox) widgetMaxH = std::max(widgetMaxH, _Lines[k].CheckBox->getHReal());
|
|
if (_Lines[k].RightArrow) widgetMaxH = std::max(widgetMaxH, _Lines[k].RightArrow->getHReal());
|
|
|
|
sint32 textHReal= _Lines[k].ViewText->getHReal();
|
|
_Lines[k].HReal= max(widgetMaxH, textHReal);
|
|
_Lines[k].TextDY= textDYPos;
|
|
if(widgetMaxH>textHReal)
|
|
_Lines[k].TextDY+= (widgetMaxH-textHReal) / 2;
|
|
}
|
|
}
|
|
|
|
|
|
// *** Update Text Positions
|
|
// sint32 currX = 0;
|
|
for(k = 0; k < _Lines.size(); ++k)
|
|
{
|
|
if (_Lines[k].ViewText)
|
|
{
|
|
// Setup Y
|
|
_Lines[k].ViewText->setY(_Lines[k].TextDY);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (mustUpdate)
|
|
{
|
|
CGroupFrame::updateCoords();
|
|
}
|
|
|
|
|
|
// *** Setup SubMenus and CheckBoxes Positions
|
|
sint32 maxViewW = 0;
|
|
for (i = 1; i < _Views.size(); ++i)
|
|
{
|
|
CViewBitmap *pVB = dynamic_cast<CViewBitmap *>(_Views[i]);
|
|
if (pVB == NULL) continue;
|
|
if (pVB->getId() == ID_MENU_SUBMENU)
|
|
{
|
|
// Look for the next line of the menu that contains a sub menu
|
|
for(;;)
|
|
{
|
|
nlassert (RALineNb < (sint32)_SubMenus.size());
|
|
if (_SubMenus[RALineNb] != NULL) // has a check box or an arrow to indicate submenu ?
|
|
{
|
|
break;
|
|
}
|
|
++RALineNb;
|
|
}
|
|
|
|
// get refElm and refElmYReal
|
|
GET_REF_ELM(RALineNb)
|
|
|
|
// if there is a check box, y is 0
|
|
if (_Lines[RALineNb].CheckBox || _Lines[RALineNb].UserGroupRight)
|
|
{
|
|
pVB->setY(0);
|
|
pVB->setX(MENU_WIDGET_X);
|
|
}
|
|
else
|
|
{
|
|
sint32 limY = refElmYReal + refElmHReal/2 - _GroupList->getYReal();
|
|
// Setup the arrow at the right pos
|
|
if(_GroupList->getMaxH()>=limY && limY>=0)
|
|
{
|
|
pVB->setY(refElmYReal + (refElmHReal - pVB->getHReal()) / 2 - _GroupList->getYReal());
|
|
pVB->setColor(_Lines[RALineNb].ViewText->getColor());
|
|
pVB->setActive(_Lines[RALineNb].ViewText->getActive());
|
|
pVB->setX(maxUserGroupWidth + MENU_WIDGET_X);
|
|
}
|
|
else
|
|
{
|
|
pVB->setY(0);
|
|
pVB->setActive(false);
|
|
}
|
|
}
|
|
|
|
if (_GroupMenu->SpawnOnMousePos)
|
|
{
|
|
_SubMenus[RALineNb]->setParentPos (this);
|
|
|
|
// According to mouse position, set the sub menu on the left or right, begin at top or bottom
|
|
CViewRenderer &rVR = CInterfaceManager::getInstance()->getViewRenderer();
|
|
uint32 screenW, screenH;
|
|
rVR.getScreenSize(screenW, screenH);
|
|
if ((_GroupMenu->SpawnMouseX <= ((sint32)screenW/2)) && (_GroupMenu->SpawnMouseY <= ((sint32)screenH/2)))
|
|
{
|
|
_SubMenus[RALineNb]->setParentPosRef(Hotspot_BR);
|
|
_SubMenus[RALineNb]->setPosRef(Hotspot_BL);
|
|
_SubMenus[RALineNb]->setY (refElmYReal - _GroupList->getYReal());
|
|
}
|
|
if ((_GroupMenu->SpawnMouseX <= ((sint32)screenW/2)) && (_GroupMenu->SpawnMouseY > ((sint32)screenH/2)))
|
|
{
|
|
_SubMenus[RALineNb]->setParentPosRef(Hotspot_TR);
|
|
_SubMenus[RALineNb]->setPosRef(Hotspot_TL);
|
|
_SubMenus[RALineNb]->setY (refElmHReal+(refElmYReal - _GroupList->getYReal()) - _GroupList->getHReal());
|
|
}
|
|
if ((_GroupMenu->SpawnMouseX > ((sint32)screenW/2)) && (_GroupMenu->SpawnMouseY <= ((sint32)screenH/2)))
|
|
{
|
|
_SubMenus[RALineNb]->setParentPosRef(Hotspot_BL);
|
|
_SubMenus[RALineNb]->setPosRef(Hotspot_BR);
|
|
_SubMenus[RALineNb]->setY (refElmYReal - _GroupList->getYReal());
|
|
}
|
|
if ((_GroupMenu->SpawnMouseX > ((sint32)screenW/2)) && (_GroupMenu->SpawnMouseY > ((sint32)screenH/2)))
|
|
{
|
|
_SubMenus[RALineNb]->setParentPosRef(Hotspot_TL);
|
|
_SubMenus[RALineNb]->setPosRef(Hotspot_TR);
|
|
_SubMenus[RALineNb]->setY (refElmHReal+(refElmYReal - _GroupList->getYReal()) - _GroupList->getHReal());
|
|
}
|
|
_SubMenus[RALineNb]->setX(0);
|
|
}
|
|
else
|
|
{
|
|
// Setup sub menu
|
|
_SubMenus[RALineNb]->setParentPos (this);
|
|
_SubMenus[RALineNb]->setParentPosRef (Hotspot_BR);
|
|
_SubMenus[RALineNb]->setPosRef (Hotspot_BL);
|
|
_SubMenus[RALineNb]->setY (16+refElmYReal - _GroupList->getYReal() - _SubMenus[RALineNb]->getHReal());
|
|
}
|
|
|
|
++RALineNb;
|
|
}
|
|
else if (pVB->getId() == ID_MENU_CHECKBOX)
|
|
{
|
|
for(;;)
|
|
{
|
|
nlassert (CBLineNb < (sint32)_SubMenus.size());
|
|
if (_Lines[CBLineNb].CheckBox != NULL) // has a check box or an arrow to indicate submenu ?
|
|
{
|
|
break;
|
|
}
|
|
++CBLineNb;
|
|
}
|
|
// Setup the arrow at the right pos
|
|
if (!_Lines[CBLineNb].UserGroupRight)
|
|
{
|
|
// get refElm and refElmYReal
|
|
GET_REF_ELM(CBLineNb)
|
|
|
|
pVB->setX(maxUserGroupWidth + 2 * MENU_WIDGET_X);
|
|
|
|
sint32 limY = refElmYReal + refElmHReal/2 - _GroupList->getYReal();
|
|
// Setup the arrow at the right pos
|
|
if(_GroupList->getMaxH()>=limY && limY>=0){
|
|
|
|
pVB->setY(refElmYReal + (refElmHReal - pVB->getHReal()) / 2 - _GroupList->getYReal());
|
|
pVB->setActive(_Lines[CBLineNb].ViewText->getActive());
|
|
}
|
|
else
|
|
{
|
|
pVB->setY(0);
|
|
pVB->setActive(false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pVB->setY(0);
|
|
pVB->setX(MENU_WIDGET_X);
|
|
}
|
|
pVB->setColor (_Lines[CBLineNb].ViewText->getColor());
|
|
//
|
|
++CBLineNb;
|
|
}
|
|
|
|
if (maxViewW<(pVB->getWReal()+pVB->getX())) maxViewW = pVB->getWReal()+pVB->getX();
|
|
}
|
|
|
|
// setup scrollbar position in function of views width
|
|
if(maxViewW>0 && _ScrollBar)
|
|
_ScrollBar->setX(4 + maxViewW);
|
|
|
|
// *** Setup user groups positions
|
|
for(k = 0; k < _Lines.size(); ++k)
|
|
{
|
|
CInterfaceGroup *igr = _Lines[k].UserGroupRight;
|
|
CInterfaceGroup *igl = _Lines[k].UserGroupLeft;
|
|
if (igr || igl)
|
|
{
|
|
// get refElm and refElmYReal
|
|
GET_REF_ELM(k)
|
|
|
|
if (refElm)
|
|
{
|
|
if (igr)
|
|
{
|
|
igr->setX(MENU_WIDGET_X + maxUserGroupWidth - igr->getWReal());
|
|
|
|
sint32 limY = refElmYReal + refElmHReal/2 - _GroupList->getYReal();
|
|
if(_GroupList->getMaxH()>=limY && limY>=0)
|
|
{
|
|
igr->setY(refElmYReal + (refElmHReal - igr->getHReal()) / 2 - _GroupList->getYReal());
|
|
igr->setActive (refElm->getActive());
|
|
}
|
|
else
|
|
{
|
|
igr->setY(0);
|
|
igr->setActive(false);
|
|
}
|
|
}
|
|
|
|
if (igl)
|
|
{
|
|
sint32 limY = refElmYReal + refElmHReal/2 - _GroupList->getYReal();
|
|
if(_GroupList->getMaxH()>=limY && limY>=0)
|
|
{
|
|
igl->setY(refElmYReal + (refElmHReal - igl->getHReal()) / 2 - this->getYReal());
|
|
igl->setActive(refElm->getActive());
|
|
}
|
|
else
|
|
{
|
|
igl->setY(0);
|
|
igl->setActive(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
sint32 SepLineNb = 0;
|
|
// set separator at the right position
|
|
for (i = 0; i < _ChildrenGroups.size(); ++i)
|
|
{
|
|
CInterfaceGroup *pIG = dynamic_cast<CInterfaceGroup *>(_ChildrenGroups[i]);
|
|
if (pIG == NULL) continue;
|
|
if (pIG->getId() != ID_MENU_SEPARATOR) continue; // is it a separator ?
|
|
|
|
// set good width
|
|
/*sint32 sw = getW() - _LeftBorder - _RightBorder;
|
|
sw = std::max(sw, (sint32) 0);
|
|
pIG->setW(sw);*/
|
|
|
|
// Look for the next line of the menu that contains a separator
|
|
CInterfaceGroup *sep = NULL;
|
|
do
|
|
{
|
|
nlassert (SepLineNb < (sint32)_Lines.size());
|
|
sep = _Lines[SepLineNb].Separator;
|
|
++SepLineNb;
|
|
}
|
|
while (sep == NULL);
|
|
|
|
// Setup the arrow at the right pos
|
|
pIG->setY (sep->getYReal() - getYReal());
|
|
pIG->setActive(sep->getActive());
|
|
}
|
|
CGroupFrame::updateCoords();
|
|
|
|
//_SelectionView->setW (this->getW());
|
|
_SelectionView->setH (8);
|
|
_SelectionView->setY (4);
|
|
|
|
|
|
if (_Selected != -1 && _Lines[_Selected].ViewText != NULL)
|
|
{
|
|
CRGBA col= _GroupMenu->_HighLightOver;
|
|
|
|
_SelectionView->setColor (col);
|
|
_SelectionView->setModulateGlobalColor(getModulateGlobalColor());
|
|
|
|
// get refElm and refElmYReal
|
|
GET_REF_ELM(_Selected)
|
|
|
|
_SelectionView->setH (refElmHReal);
|
|
_SelectionView->setY (refElmYReal - this->getYReal());
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::checkCoords()
|
|
{
|
|
if (!_Active) return;
|
|
if (_GroupMenu == NULL) return;
|
|
|
|
// if the mouse goes out the window, unselect all (because handleEvent may not be called)
|
|
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
|
sint xMouse= pIM->getPointer()->getX();
|
|
sint yMouse= pIM->getPointer()->getY();
|
|
if (!((xMouse >= _XReal) &&
|
|
(xMouse < (_XReal + _WReal))&&
|
|
(yMouse > _YReal) &&
|
|
(yMouse <= (_YReal+ _HReal))))
|
|
_Selected= -1;
|
|
|
|
// CViewRenderer &rVR = pIM->getViewRenderer();
|
|
|
|
// Highlight (background under the selection)
|
|
if (_Selected != -1)
|
|
{
|
|
// display hightlight
|
|
if(_GroupMenu->_HighLightOver.A > 0)
|
|
{
|
|
_SelectionView->setActive (true);
|
|
_SelectionView->invalidateCoords();
|
|
}
|
|
else
|
|
{
|
|
_SelectionView->setActive (false);
|
|
}
|
|
}
|
|
else // no selection
|
|
{
|
|
_SelectionView->setActive (false);
|
|
}
|
|
|
|
// Text color if grayed or not
|
|
for (sint32 i = 0; i < (sint32)_Lines.size(); ++i)
|
|
{
|
|
if (_Lines[i].ViewText)
|
|
{
|
|
if (_Lines[i].ViewText->getGrayed()) // Colors when the text is grayed
|
|
{
|
|
_Lines[i].ViewText->setColor (_Lines[i].ViewText->OldColorGrayed);
|
|
_Lines[i].ViewText->setShadowColor (_Lines[i].ViewText->OldShadowColorGrayed);
|
|
}
|
|
else
|
|
{
|
|
if (i == _Selected) // Colors when the text is selected
|
|
{
|
|
_Lines[i].ViewText->Over = true;
|
|
_Lines[i].ViewText->setColor (_Lines[i].ViewText->OldColorOver);
|
|
_Lines[i].ViewText->setShadowColor (_Lines[i].ViewText->OldShadowColorOver);
|
|
}
|
|
else // Or finally normal colors
|
|
{
|
|
_Lines[i].ViewText->Over = false;
|
|
_Lines[i].ViewText->setColor (_Lines[i].ViewText->OldColor);
|
|
_Lines[i].ViewText->setShadowColor (_Lines[i].ViewText->OldShadowColor);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::draw()
|
|
{
|
|
if (!_Active) return;
|
|
if (_GroupMenu == NULL) return;
|
|
CGroupFrame::draw();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
bool CGroupSubMenu::handleEvent (const CEventDescriptor &event)
|
|
{
|
|
if (!_Active)
|
|
return false;
|
|
|
|
sint32 textDYPos= 0;
|
|
if(_GroupList)
|
|
textDYPos= -(1+_GroupList->getSpace())/2;
|
|
|
|
if (event.getType() == CEventDescriptor::mouse)
|
|
{
|
|
const CEventDescriptorMouse &eventDesc = (const CEventDescriptorMouse &)event;
|
|
_Selected = -1;
|
|
|
|
// TODO First check sub menus that can be not in the area of this menu
|
|
|
|
if (!((eventDesc.getX() >= _XReal) &&
|
|
(eventDesc.getX() < (_XReal + _WReal))&&
|
|
(eventDesc.getY() > _YReal) &&
|
|
(eventDesc.getY() <= (_YReal+ _HReal))))
|
|
return false;
|
|
|
|
uint32 i = 0;
|
|
for (i = 0; i < _Lines.size(); ++i)
|
|
{
|
|
if (_Lines[i].Selectable)
|
|
{
|
|
// get refElm and refElmYReal
|
|
GET_REF_ELM(i)
|
|
|
|
if (refElm)
|
|
{
|
|
if (refElm->getActive() == true)
|
|
if ((eventDesc.getY() > refElmYReal) &&
|
|
(eventDesc.getY() <= (refElmYReal + refElmHReal + _GroupList->getSpace())))
|
|
{
|
|
_Selected = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftup)
|
|
{
|
|
// If a line is selected and the line is not grayed
|
|
if ((_Selected != -1) && (!_Lines[i].ViewText->getGrayed()))
|
|
{
|
|
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
|
pIM->runActionHandler ( _Lines[_Selected].AHName,
|
|
pIM->getCtrlLaunchingModal(),
|
|
_Lines[_Selected].AHParams );
|
|
|
|
if (_SubMenus[_Selected] != NULL)
|
|
{
|
|
openSubMenu (_Selected);
|
|
}
|
|
else
|
|
{
|
|
// if the menu hasn't triggered a new modal window, disable it
|
|
if (pIM->getModalWindow() == _GroupMenu)
|
|
{
|
|
if(_GroupMenu && _GroupMenu->getCloseSubMenuUsingPopModal())
|
|
pIM->popModalWindow();
|
|
else
|
|
pIM->disableModalWindow ();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (event.getType() == CEventDescriptor::mouse)
|
|
{
|
|
const CEventDescriptorMouse &eventDesc = (const CEventDescriptorMouse &)event;
|
|
//
|
|
if (_GroupList && _ScrollBar)
|
|
{
|
|
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mousewheel)
|
|
{
|
|
if (isIn(eventDesc.getX(), eventDesc.getY()))
|
|
{
|
|
sint32 h = 0;
|
|
for (uint32 k = 0; k < _Lines.size(); ++k)
|
|
if (_Lines[k].ViewText)
|
|
{
|
|
// compute max height of widgets on the left of text
|
|
sint32 widgetMaxH = 0;
|
|
if (_Lines[k].UserGroupRight) widgetMaxH = _Lines[k].UserGroupRight->getHReal();
|
|
if (_Lines[k].UserGroupLeft) widgetMaxH = std::max(widgetMaxH, _Lines[k].UserGroupLeft->getHReal());
|
|
if (_Lines[k].CheckBox) widgetMaxH = std::max(widgetMaxH, _Lines[k].CheckBox->getHReal());
|
|
if (_Lines[k].RightArrow) widgetMaxH = std::max(widgetMaxH, _Lines[k].RightArrow->getHReal());
|
|
widgetMaxH = std::max(widgetMaxH, _Lines[k].ViewText->getHReal());
|
|
h = widgetMaxH+_GroupList->getSpace();
|
|
}
|
|
if (h == 0) h = 1;
|
|
_ScrollBar->moveTargetY(- eventDesc.getWheel() * h);
|
|
|
|
hideSubMenus();
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CInterfaceElement* CGroupSubMenu::getElement (const std::string &id)
|
|
{
|
|
string sTmp = id.substr(0, _GroupMenu->getId().size());
|
|
if (sTmp != _GroupMenu->getId()) return NULL;
|
|
|
|
string sRest = id.substr(_GroupMenu->getId().size()+1, id.size());
|
|
|
|
// Iterate through the tree to see if sRest is present
|
|
CGroupSubMenu *pCurGSM = this;
|
|
while (!sRest.empty())
|
|
{
|
|
// Get the first element of the sRest
|
|
string::size_type posid = sRest.find (":");
|
|
|
|
if (posid == string::npos) // Is there just one token to test ?
|
|
{
|
|
for (uint32 i = 0; i < pCurGSM->_Lines.size(); ++i)
|
|
if (sRest == pCurGSM->_Lines[i].Id)
|
|
return pCurGSM->_Lines[i].ViewText;
|
|
sRest = "";
|
|
}
|
|
else // no a lot of token left
|
|
{
|
|
string sTok = sRest.substr (0, posid);
|
|
uint32 i = 0;
|
|
for (i = 0; i < pCurGSM->_Lines.size(); ++i)
|
|
if (sTok == pCurGSM->_Lines[i].Id)
|
|
break;
|
|
if (i == pCurGSM->_Lines.size())
|
|
return NULL;
|
|
|
|
// No sub-menus
|
|
if (pCurGSM->_SubMenus[i] == NULL)
|
|
{
|
|
// Get next token
|
|
sRest = sRest.substr (posid+1);
|
|
posid = sRest.find (":");
|
|
if (posid == string::npos)
|
|
sTok = sRest;
|
|
else
|
|
sTok = sRest.substr (0, posid);
|
|
// Do we want left or right user group ?
|
|
if (pCurGSM->_Lines[i].UserGroupRight)
|
|
{
|
|
string sUGid = pCurGSM->_Lines[i].UserGroupRight->getId();
|
|
sUGid = sUGid.substr(sUGid.rfind(':')+1,sUGid.size());
|
|
if (sUGid == sTok)
|
|
{
|
|
CInterfaceElement *pIE = pCurGSM->_Lines[i].UserGroupRight->getElement(id);
|
|
return pIE;
|
|
}
|
|
}
|
|
if (pCurGSM->_Lines[i].UserGroupLeft)
|
|
{
|
|
string sUGid = pCurGSM->_Lines[i].UserGroupLeft->getId();
|
|
sUGid = sUGid.substr(sUGid.rfind(':')+1,sUGid.size());
|
|
if (sUGid == sTok)
|
|
{
|
|
CInterfaceElement *pIE = pCurGSM->_Lines[i].UserGroupLeft->getElement(id);
|
|
return pIE;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
pCurGSM = pCurGSM->_SubMenus[i];
|
|
}
|
|
}
|
|
sRest = sRest.substr (posid+1);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::addSeparator(const std::string &id)
|
|
{
|
|
addSeparatorAtIndex(_Lines.size(), id);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::addSeparatorAtIndex(uint index, const std::string &id)
|
|
{
|
|
if (index > _Lines.size())
|
|
{
|
|
nlwarning("Bad index");
|
|
return;
|
|
}
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
// create the real separator. It may be larger than the group list, this is why we create a separate group
|
|
CInterfaceGroup *separator = im->createGroupInstance("menu_separator", "", NULL, 0);
|
|
if (!separator) return;
|
|
separator->setId(ID_MENU_SEPARATOR);
|
|
addGroup(separator);
|
|
separator->setParent(this);
|
|
// create place holder group
|
|
CInterfaceGroup *ph = im->createGroupInstance("menu_separator_empty", "", NULL, 0);
|
|
if (!ph)
|
|
{
|
|
delGroup(separator);
|
|
return;
|
|
}
|
|
_GroupList->addChildAtIndex(ph, index);
|
|
SSubMenuEntry tmp;
|
|
tmp.Id = id;
|
|
tmp.Separator = ph;
|
|
tmp.ViewText = NULL;
|
|
tmp.CheckBox = NULL;
|
|
tmp.RightArrow = NULL;
|
|
_Lines.insert(_Lines.begin() + index, tmp);
|
|
_SubMenus.insert(_SubMenus.begin() + index, NULL);
|
|
_GroupMenu->invalidateCoords();
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CViewTextMenu* CGroupSubMenu::addLine (const ucstring &name, const std::string &ah,
|
|
const std::string ¶ms, const std::string &id,
|
|
const std::string &cond, const std::string &texture,
|
|
bool checkable /*= false*/, bool checked /*= false*/, bool formatted /*= false */
|
|
)
|
|
{
|
|
SSubMenuEntry tmp;
|
|
|
|
CViewTextMenu *pV = new CViewTextMenu(CViewBase::TCtorParam());
|
|
|
|
|
|
pV->setCaseMode(_GroupMenu->getCaseMode());
|
|
if (formatted)
|
|
{
|
|
pV->setMultiLine (true);
|
|
pV->setMultiLineMaxWOnly (true);
|
|
pV->setTextFormatTaged (name);
|
|
}
|
|
else
|
|
{
|
|
pV->setText (name);
|
|
}
|
|
pV->setColor (_GroupMenu->_Color);
|
|
pV->setFontSize (_GroupMenu->_FontSize);
|
|
pV->setShadow (_GroupMenu->_Shadow);
|
|
pV->setCheckable(checkable);
|
|
pV->setChecked(checked);
|
|
pV->setModulateGlobalColor(_GroupMenu->_ModulateGlobalColor);
|
|
|
|
pV->OldColor = _GroupMenu->_Color;
|
|
pV->OldShadowColor = _GroupMenu->_ShadowColor;
|
|
pV->OldColorOver = _GroupMenu->_ColorOver;
|
|
pV->OldShadowColorOver = _GroupMenu->_ShadowColorOver;
|
|
pV->OldColorGrayed = _GroupMenu->_ColorGrayed;
|
|
pV->OldShadowColorGrayed = _GroupMenu->_ShadowColorGrayed;
|
|
|
|
_GroupList->addChild (pV);
|
|
|
|
CViewBitmap *checkBox = NULL;
|
|
|
|
if (checkable)
|
|
{
|
|
checkBox = createCheckBox(checked);
|
|
checkBox->setTexture(texture);
|
|
pV->setCheckBox(checkBox);
|
|
}
|
|
|
|
tmp.ViewText = pV;
|
|
tmp.Separator = NULL;
|
|
tmp.AHName = ah;
|
|
tmp.AHParams = params;
|
|
tmp.Cond = cond;
|
|
tmp.CheckBox = checkBox;
|
|
tmp.RightArrow = NULL;
|
|
if (id.empty())
|
|
tmp.Id = NLMISC::toString (_Lines.size());
|
|
else
|
|
tmp.Id = id;
|
|
|
|
pV->setId(_GroupMenu->getId()+":"+tmp.Id);
|
|
|
|
_Lines.push_back (tmp);
|
|
|
|
// Add an empty sub menu by default
|
|
_SubMenus.push_back (NULL);
|
|
|
|
_GroupMenu->invalidateCoords();
|
|
|
|
return pV;
|
|
}
|
|
|
|
CViewTextMenu* CGroupSubMenu::addLineAtIndex(uint index, const ucstring &name, const std::string &ah,
|
|
const std::string ¶ms, const std::string &id /*=""*/,
|
|
const std::string &cond /*=std::string()*/, const std::string &texture,
|
|
bool checkable /*= false*/, bool checked /*= false*/, bool formatted /*= false */
|
|
)
|
|
{
|
|
if (index > _Lines.size())
|
|
{
|
|
nlwarning("Bad index");
|
|
return NULL;
|
|
}
|
|
SSubMenuEntry tmp;
|
|
CViewTextMenu *pV = new CViewTextMenu(CViewBase::TCtorParam());
|
|
|
|
|
|
pV->setCaseMode(_GroupMenu->getCaseMode());
|
|
|
|
|
|
if (formatted)
|
|
{
|
|
pV->setMultiLine (true);
|
|
pV->setMultiLineMaxWOnly (true);
|
|
pV->setTextFormatTaged (name);
|
|
}
|
|
else
|
|
{
|
|
pV->setText (name);
|
|
}
|
|
|
|
pV->setColor (_GroupMenu->_Color);
|
|
pV->setFontSize (_GroupMenu->_FontSize);
|
|
pV->setShadow (_GroupMenu->_Shadow);
|
|
pV->setCheckable(checkable);
|
|
pV->setChecked(checked);
|
|
pV->setModulateGlobalColor(_GroupMenu->_ModulateGlobalColor);
|
|
|
|
pV->OldColor = _GroupMenu->_Color;
|
|
pV->OldShadowColor = _GroupMenu->_ShadowColor;
|
|
pV->OldColorOver = _GroupMenu->_ColorOver;
|
|
pV->OldShadowColorOver = _GroupMenu->_ShadowColorOver;
|
|
pV->OldColorGrayed = _GroupMenu->_ColorGrayed;
|
|
pV->OldShadowColorGrayed = _GroupMenu->_ShadowColorGrayed;
|
|
|
|
_GroupList->addChildAtIndex(pV, index);
|
|
|
|
CViewBitmap *checkBox = NULL;
|
|
if (checkable)
|
|
{
|
|
checkBox = createCheckBox(checked);
|
|
checkBox->setTexture(texture);
|
|
pV->setCheckBox(checkBox);
|
|
}
|
|
|
|
tmp.ViewText = pV;
|
|
tmp.Separator = NULL;
|
|
tmp.AHName = ah;
|
|
tmp.AHParams = params;
|
|
tmp.Cond = cond;
|
|
tmp.CheckBox = checkBox;
|
|
tmp.RightArrow = NULL;
|
|
|
|
if (id.empty())
|
|
tmp.Id = NLMISC::toString (_Lines.size());
|
|
else
|
|
tmp.Id = id;
|
|
|
|
pV->setId(getId()+":"+tmp.Id);
|
|
|
|
_Lines.insert(_Lines.begin() + index, tmp);
|
|
|
|
// Add an empty sub menu by default
|
|
_SubMenus.insert(_SubMenus.begin() + index, NULL);
|
|
|
|
_GroupMenu->invalidateCoords();
|
|
|
|
return pV;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::removeLine(uint index)
|
|
{
|
|
if (index >= _Lines.size())
|
|
{
|
|
nlwarning("Bad index");
|
|
return;
|
|
}
|
|
setUserGroupRight(index, NULL, false); // remove user group
|
|
setUserGroupLeft(index, NULL, false); // remove user group
|
|
// remove view (right arrow & checkbox)
|
|
if (_Lines[index].RightArrow) delView(_Lines[index].RightArrow);
|
|
if (_Lines[index].CheckBox) delView(_Lines[index].CheckBox);
|
|
if (_Lines[index].Separator)
|
|
{
|
|
// remove one separator group
|
|
for(uint k = 0; k < _ChildrenGroups.size(); ++k)
|
|
{
|
|
if (_ChildrenGroups[k]->getId() == ID_MENU_SEPARATOR)
|
|
{
|
|
delGroup(_ChildrenGroups[k]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
_GroupList->setDelOnRemove(index, true);
|
|
_GroupList->delChild(index);
|
|
_Lines.erase(_Lines.begin() + index);
|
|
|
|
//invalidate selection
|
|
_Selected = -1;
|
|
|
|
if(_SubMenus[index])
|
|
{
|
|
// reset it and his sons (recurs)
|
|
_SubMenus[index]->reset();
|
|
// then delete it
|
|
_GroupMenu->delGroup(_SubMenus[index]);
|
|
}
|
|
_SubMenus.erase(_SubMenus.begin() + index);
|
|
_GroupMenu->invalidateCoords();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::openSubMenu (sint32 nb)
|
|
{
|
|
hideSubMenus ();
|
|
_SubMenus[nb]->setActive (true);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::hideSubMenus ()
|
|
{
|
|
for (uint32 i = 0; i < _SubMenus.size(); ++i)
|
|
if (_SubMenus[i] != NULL)
|
|
{
|
|
_SubMenus[i]->setActive (false);
|
|
_SubMenus[i]->hideSubMenus ();
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::reset()
|
|
{
|
|
uint lineCount = _Lines.size();
|
|
for(sint k = lineCount - 1; k >= 0; --k)
|
|
{
|
|
removeLine(k);
|
|
}
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::removeAllUserGroups()
|
|
{
|
|
for(uint k = 0; k < _Lines.size(); ++k)
|
|
{
|
|
setUserGroupRight(k, NULL, false);
|
|
setUserGroupLeft(k, NULL, false);
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CInterfaceGroup *CGroupSubMenu::getUserGroupRight(uint line) const
|
|
{
|
|
if (line >= _Lines.size())
|
|
{
|
|
nlwarning("bad index");
|
|
return NULL;
|
|
}
|
|
return _Lines[line].UserGroupRight;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CInterfaceGroup *CGroupSubMenu::getUserGroupLeft(uint line) const
|
|
{
|
|
if (line >= _Lines.size())
|
|
{
|
|
nlwarning("bad index");
|
|
return NULL;
|
|
}
|
|
return _Lines[line].UserGroupLeft;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::setUserGroupRight(uint line, CInterfaceGroup *group, bool ownership)
|
|
{
|
|
if (line >= _Lines.size())
|
|
{
|
|
nlwarning("bad index");
|
|
return;
|
|
}
|
|
if (group && isChildGroup(group))
|
|
{
|
|
nlwarning("Group inserted twice");
|
|
return;
|
|
}
|
|
if (_Lines[line].UserGroupRight)
|
|
{
|
|
delGroup(_Lines[line].UserGroupRight, !_Lines[line].UserGroupRightOwnership);
|
|
}
|
|
_Lines[line].UserGroupRight = group;
|
|
_Lines[line].UserGroupRightOwnership = ownership;
|
|
if (group)
|
|
{
|
|
CViewBase *prevElem = _Lines[line].CheckBox ? _Lines[line].CheckBox : _Lines[line].RightArrow;
|
|
if (prevElem)
|
|
{
|
|
prevElem->setParentPosRef (Hotspot_MR);
|
|
prevElem->setPosRef (Hotspot_ML);
|
|
prevElem->setParentPos(group);
|
|
prevElem->setX(MENU_WIDGET_X);
|
|
prevElem->setY(0);
|
|
}
|
|
sint insertionOrder;
|
|
if (prevElem)
|
|
{
|
|
insertionOrder = getInsertionOrder(prevElem);
|
|
}
|
|
else
|
|
{
|
|
insertionOrder = -1;
|
|
}
|
|
addGroup(group, insertionOrder);
|
|
group->setParent(this);
|
|
group->setParentPos(_GroupList);
|
|
group->setParentPosRef (Hotspot_BR);
|
|
group->setPosRef (Hotspot_BL);
|
|
}
|
|
else
|
|
{
|
|
// restore all posref..
|
|
CViewBase *prevElem = _Lines[line].CheckBox ? _Lines[line].CheckBox : _Lines[line].RightArrow;
|
|
if (prevElem)
|
|
{
|
|
prevElem->setParent (this);
|
|
prevElem->setParentPos (_GroupList);
|
|
prevElem->setParentPosRef (Hotspot_BR);
|
|
prevElem->setPosRef (Hotspot_BL);
|
|
prevElem->setX (MENU_WIDGET_X);
|
|
}
|
|
}
|
|
_GroupMenu->invalidateCoords();
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::setUserGroupLeft(uint line, CInterfaceGroup *group, bool ownership)
|
|
{
|
|
if (line >= _Lines.size())
|
|
{
|
|
nlwarning("bad index");
|
|
return;
|
|
}
|
|
if (group && isChildGroup(group))
|
|
{
|
|
nlwarning("Group inserted twice");
|
|
return;
|
|
}
|
|
if (_Lines[line].UserGroupLeft)
|
|
{
|
|
delGroup(_Lines[line].UserGroupLeft, !_Lines[line].UserGroupLeftOwnership);
|
|
}
|
|
_Lines[line].UserGroupLeft = group;
|
|
_Lines[line].UserGroupLeftOwnership = ownership;
|
|
if (group)
|
|
{
|
|
addGroup(group);
|
|
group->setParent(this);
|
|
group->setParentPos(this);
|
|
group->setParentPosRef (Hotspot_BL);
|
|
group->setPosRef (Hotspot_BL);
|
|
group->setX(LEFT_MENU_WIDGET_X);
|
|
}
|
|
|
|
_GroupMenu->invalidateCoords();
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CGroupSubMenu *CGroupSubMenu::cloneMenu(CGroupSubMenu *appendToMenu, CGroupMenu *newFather, CInterfaceGroup *initGroup /* = NULL */) const
|
|
{
|
|
CGroupSubMenu *copyMenu = appendToMenu ? appendToMenu : new CGroupSubMenu(CViewText::TCtorParam());
|
|
uint startSize = copyMenu->_Lines.size();
|
|
copyMenu->_GroupMenu = newFather;
|
|
copyMenu->initOptions(initGroup);
|
|
copyMenu->_Lines.reserve(_Lines.size() + startSize);
|
|
copyMenu->_SubMenus.reserve(_SubMenus.size() + startSize);
|
|
// copy childrens
|
|
for(uint k = 0; k < _Lines.size(); ++k)
|
|
{
|
|
if (_Lines[k].Separator)
|
|
{
|
|
copyMenu->addSeparator(_Lines[k].Id);
|
|
}
|
|
else
|
|
{
|
|
std::string texture = std::string();
|
|
if(_Lines[k].ViewText->getCheckBox())
|
|
{
|
|
texture = _Lines[k].ViewText->getCheckBox()->getTexture();
|
|
}
|
|
CViewTextMenu *pV = NULL;
|
|
pV = copyMenu->addLine (_Lines[k].ViewText->getText(), _Lines[k].AHName, _Lines[k].AHParams, _Lines[k].Id, _Lines[k].Cond,
|
|
texture, _Lines[k].ViewText->getCheckable(), _Lines[k].ViewText->getChecked(), _Lines[k].ViewText->getFormatted ());
|
|
copyMenu->_Lines[k].Selectable = _Lines[k].Selectable;
|
|
pV->setGrayed(_Lines[k].ViewText->getGrayed());
|
|
}
|
|
|
|
// sub menu copy if there's one
|
|
if (_SubMenus[k] != NULL)
|
|
{
|
|
|
|
if (copyMenu->_Lines.back().CheckBox)
|
|
{
|
|
copyMenu->_Lines.back().RightArrow = copyMenu->createRightArrow(copyMenu->_Lines.back().CheckBox, true);
|
|
}
|
|
else
|
|
{
|
|
copyMenu->_Lines.back().RightArrow = copyMenu->createRightArrow(copyMenu->_GroupList, false);
|
|
}
|
|
|
|
|
|
// and create the sub menu
|
|
copyMenu->_SubMenus[k + startSize] = _SubMenus[k]->cloneMenu(NULL, newFather, copyMenu);
|
|
}
|
|
}
|
|
if (!appendToMenu)
|
|
{
|
|
newFather->addGroup(copyMenu);
|
|
}
|
|
return copyMenu;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::setActive(bool state)
|
|
{
|
|
// check conditions
|
|
for(uint k = 0; k < _Lines.size(); ++k)
|
|
{
|
|
if (!_Lines[k].Cond.empty())
|
|
{
|
|
CInterfaceExprValue result;
|
|
if (CInterfaceExpr::eval(_Lines[k].Cond, result))
|
|
{
|
|
if (result.toBool())
|
|
{
|
|
_Lines[k].ViewText->setGrayed(!result.getBool());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(_ScrollBar && _GroupList)
|
|
_ScrollBar->setTrackPos(_GroupList->getHReal());
|
|
|
|
CGroupFrame::setActive(state);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
const std::string CGroupSubMenu::getActionHandler(uint lineIndex) const
|
|
{
|
|
if (lineIndex > _Lines.size())
|
|
{
|
|
nlwarning("Bad index");
|
|
return 0;
|
|
}
|
|
return _Lines[lineIndex].AHName;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
const std::string CGroupSubMenu::getActionHandlerParam(uint lineIndex) const
|
|
{
|
|
if (lineIndex > _Lines.size())
|
|
{
|
|
nlwarning("Bad index");
|
|
return 0;
|
|
}
|
|
return _Lines[lineIndex].AHParams;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::setSelectable(uint lineIndex, bool selectable)
|
|
{
|
|
if (lineIndex > _Lines.size())
|
|
{
|
|
nlwarning("Bad index");
|
|
return;
|
|
}
|
|
_Lines[lineIndex].Selectable = selectable;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
bool CGroupSubMenu::getSelectable(uint lineIndex) const
|
|
{
|
|
if (lineIndex > _Lines.size())
|
|
{
|
|
nlwarning("Bad index");
|
|
return 0;
|
|
}
|
|
return _Lines[lineIndex].Selectable;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::setMaxVisibleLine(sint32 mvl)
|
|
{
|
|
_MaxVisibleLine = mvl;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
const std::string &CGroupSubMenu::getLineId(uint index)
|
|
{
|
|
if(index>=_Lines.size())
|
|
{
|
|
static string nullString;
|
|
return nullString;
|
|
}
|
|
else
|
|
return _Lines[index].Id;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::setGrayedLine(uint line, bool g)
|
|
{
|
|
if(line<_Lines.size())
|
|
{
|
|
if (_Lines[line].ViewText)
|
|
{
|
|
_Lines[line].ViewText->setGrayed(g);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupSubMenu::setHiddenLine(uint line, bool h)
|
|
{
|
|
if(line<_Lines.size())
|
|
{
|
|
if (_Lines[line].ViewText)
|
|
{
|
|
_Lines[line].ViewText->setActive(!h);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaGetNumLine(CLuaState &ls)
|
|
{
|
|
CLuaIHM::checkArgCount(ls, "getNumLine", 0);
|
|
ls.push((double) getNumLine());
|
|
return 1;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaGetSubMenu(CLuaState &ls)
|
|
{
|
|
const char *funcName = "getSubMenu";
|
|
CLuaIHM::checkArgCount(ls, funcName, 1);
|
|
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
|
|
CLuaIHM::pushUIOnStack(ls, getSubMenu((uint) ls.toNumber(1)));
|
|
return 1;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaAddSubMenu(CLuaState &ls)
|
|
{
|
|
const char *funcName = "addSubMenu";
|
|
CLuaIHM::checkArgCount(ls, funcName, 1);
|
|
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
|
|
setSubMenu((uint) ls.toNumber(1), new CGroupSubMenu(CViewText::TCtorParam()));
|
|
CLuaIHM::pushUIOnStack(ls, getSubMenu((uint) ls.toNumber(1)));
|
|
return 1;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaGetLineId(CLuaState &ls)
|
|
{
|
|
const char *funcName = "getLineId";
|
|
CLuaIHM::checkArgCount(ls, funcName, 1);
|
|
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
|
|
std::string id = getLineId((uint) ls.toNumber(1));
|
|
CLuaIHM::push(ls, id);
|
|
return 1;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaGetLineFromId(CLuaState &ls)
|
|
{
|
|
const char *funcName = "getLineFromId";
|
|
CLuaIHM::checkArgCount(ls, funcName, 1);
|
|
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TSTRING);
|
|
ls.push((double) getLineFromId(ls.toString(1)));
|
|
return 1;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaIsSeparator(CLuaState &ls)
|
|
{
|
|
const char *funcName = "isSeparator";
|
|
CLuaIHM::checkArgCount(ls, funcName, 1);
|
|
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
|
|
ls.push(isSeparator((uint) ls.toNumber(1)));
|
|
return 1;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaAddLine(CLuaState &ls)
|
|
{
|
|
const char *funcName = "addLine";
|
|
CLuaIHM::checkArgCount(ls, funcName, 4);
|
|
CLuaIHM::checkArgTypeUCString(ls, funcName, 1);
|
|
CLuaIHM::checkArgType(ls, funcName, 2, LUA_TSTRING);
|
|
CLuaIHM::checkArgType(ls, funcName, 3, LUA_TSTRING);
|
|
CLuaIHM::checkArgType(ls, funcName, 4, LUA_TSTRING);
|
|
ucstring arg1;
|
|
nlverify(CLuaIHM::getUCStringOnStack(ls, 1, arg1));
|
|
addLine(arg1, ls.toString(2), ls.toString(3), ls.toString(4));
|
|
return 0;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaAddLineAtIndex(CLuaState &ls)
|
|
{
|
|
const char *funcName = "addLineAtIndex";
|
|
CLuaIHM::checkArgCount(ls, funcName, 5);
|
|
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
|
|
CLuaIHM::checkArgTypeUCString(ls, funcName, 2);
|
|
CLuaIHM::checkArgType(ls, funcName, 3, LUA_TSTRING);
|
|
CLuaIHM::checkArgType(ls, funcName, 4, LUA_TSTRING);
|
|
CLuaIHM::checkArgType(ls, funcName, 5, LUA_TSTRING);
|
|
ucstring arg2;
|
|
nlverify(CLuaIHM::getUCStringOnStack(ls, 2, arg2));
|
|
addLineAtIndex((uint) ls.toNumber(1), arg2, ls.toString(3), ls.toString(4), ls.toString(5));
|
|
return 0;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaAddSeparator(CLuaState &ls)
|
|
{
|
|
CLuaIHM::checkArgCount(ls, "addSeparator", 0);
|
|
addSeparator();
|
|
return 0;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaAddSeparatorAtIndex(CLuaState &ls)
|
|
{
|
|
const char *funcName = "addSeparatorAtIndex";
|
|
CLuaIHM::checkArgCount(ls, funcName, 1);
|
|
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
|
|
addSeparatorAtIndex((uint) ls.toNumber(1));
|
|
return 0;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaRemoveLine(CLuaState &ls)
|
|
{
|
|
const char *funcName = "removeLine";
|
|
CLuaIHM::checkArgCount(ls, funcName, 1);
|
|
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
|
|
removeLine((uint) ls.toNumber(1));
|
|
return 0;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaSetUserGroupRight(CLuaState &ls)
|
|
{
|
|
const char *funcName = "setUserGroupRight";
|
|
CLuaIHM::checkArgCount(ls, funcName, 2);
|
|
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
|
|
if (!(CLuaIHM::isUIOnStack(ls, 2) || ls.isNil(2)))
|
|
{
|
|
CLuaIHM::fails(ls, toString("%s : Group required as argument 2", funcName));
|
|
}
|
|
CInterfaceElement *el = CLuaIHM::getUIOnStack(ls, 2);
|
|
CInterfaceGroup *group = dynamic_cast<CInterfaceGroup *>(el);
|
|
if (el && !group)
|
|
{
|
|
CLuaIHM::fails(ls, "%s : Group required as argument 2", funcName);
|
|
}
|
|
setUserGroupRight((uint) ls.toNumber(1), group, true);
|
|
return 0;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaSetUserGroupLeft(CLuaState &ls)
|
|
{
|
|
const char *funcName = "setUserGroupLeft";
|
|
CLuaIHM::checkArgCount(ls, funcName, 2);
|
|
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
|
|
if (!(CLuaIHM::isUIOnStack(ls, 2) || ls.isNil(2)))
|
|
{
|
|
CLuaIHM::fails(ls, "%s : Group required as argument 2", funcName);
|
|
}
|
|
CInterfaceElement *el = CLuaIHM::getUIOnStack(ls, 2);
|
|
CInterfaceGroup *group = dynamic_cast<CInterfaceGroup *>(el);
|
|
if (el && !group)
|
|
{
|
|
CLuaIHM::fails(ls, "%s : Group required as argument 2", funcName);
|
|
}
|
|
setUserGroupLeft((uint) ls.toNumber(1), group, true);
|
|
return 0;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaGetUserGroupRight(CLuaState &ls)
|
|
{
|
|
const char *funcName = "getUserGroupRight";
|
|
CLuaIHM::checkArgCount(ls, funcName, 1);
|
|
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
|
|
CLuaIHM::pushUIOnStack(ls, getUserGroupRight((uint) ls.toNumber(1)));
|
|
return 1;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaGetUserGroupLeft(CLuaState &ls)
|
|
{
|
|
const char *funcName = "getUserGroupLeft";
|
|
CLuaIHM::checkArgCount(ls, funcName, 1);
|
|
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
|
|
CInterfaceElement *pIE = getUserGroupLeft((uint) ls.toNumber(1));
|
|
if (pIE)
|
|
{
|
|
CLuaIHM::pushUIOnStack(ls, pIE);
|
|
return 1;
|
|
}
|
|
else return 0;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaSetMaxVisibleLine(CLuaState &ls)
|
|
{
|
|
const char *funcName = "setMaxVisibleLine";
|
|
CLuaIHM::checkArgCount(ls, funcName, 1);
|
|
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
|
|
setMaxVisibleLine((uint) ls.toNumber(1));
|
|
return 0;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupSubMenu::luaReset(CLuaState &ls)
|
|
{
|
|
const char *funcName = "reset";
|
|
CLuaIHM::checkArgCount(ls, funcName, 0);
|
|
reset();
|
|
return 0;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
// CGroupMenu
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
NLMISC_REGISTER_OBJECT(CViewBase, CGroupMenu, std::string, "menu");
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CGroupMenu::CGroupMenu(const TCtorParam ¶m)
|
|
:CGroupModal(param)
|
|
{
|
|
_Active = false;
|
|
_Color = CRGBA::White;
|
|
_ColorOver = CRGBA::White;
|
|
_ColorGrayed = CRGBA(128, 128, 128, 255);
|
|
_ShadowColor = CRGBA::Black;
|
|
_ShadowColorOver = CRGBA::Black;
|
|
_ShadowColorGrayed = CRGBA::Black;
|
|
_HighLightOver.set(128, 0, 0, 255);
|
|
_FontSize = 12;
|
|
_Shadow = false;
|
|
_ResizeFromChildH = _ResizeFromChildW = true;
|
|
_DisplayFrame = false;
|
|
_RootMenu = NULL;
|
|
_Space = 3;
|
|
_CaseMode = CaseUpper;
|
|
_Formatted = false;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CGroupMenu::~CGroupMenu()
|
|
{
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
bool CGroupMenu::parse (xmlNodePtr in, CInterfaceGroup *parentGroup)
|
|
{
|
|
CXMLAutoPtr prop;
|
|
|
|
_FontSize = 12;
|
|
|
|
// override source menu options (if there's one)
|
|
if (!CGroupModal::parse(in, parentGroup))
|
|
return false;
|
|
|
|
|
|
// see if this menu extends another menu
|
|
prop= (char*) xmlGetProp( in, (xmlChar*)"extends" );
|
|
CGroupSubMenu *gmExtended = NULL;
|
|
if (prop)
|
|
{
|
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
|
CGroupMenu *gm = dynamic_cast<CGroupMenu *>(im->getElementFromId(prop));
|
|
if (!gm)
|
|
{
|
|
gm = dynamic_cast<CGroupMenu *>(im->getElementFromId("ui:interface:" + std::string((const char*)prop)));
|
|
}
|
|
if (gm)
|
|
{
|
|
gmExtended = gm->_RootMenu;
|
|
// copy group frame parameters
|
|
CGroupFrame::copyOptionFrom(*gm);
|
|
// copy basic datas
|
|
_Color = gm->_Color;
|
|
_ShadowColor = gm->_ShadowColor;
|
|
_Shadow = gm->_Shadow;
|
|
_FontSize = gm->_FontSize;
|
|
_ColorOver = gm->_ColorOver;
|
|
_ShadowColorOver = gm->_ShadowColorOver;
|
|
_HighLightOver = gm->_HighLightOver;
|
|
_ColorGrayed = gm->_ColorGrayed;
|
|
_ShadowColorGrayed = gm->_ShadowColorGrayed;
|
|
_Priority = gm->_Priority;
|
|
_ModulateGlobalColor = gm->_ModulateGlobalColor;
|
|
_Space = gm->_Space;
|
|
_CaseMode = gm->_CaseMode;
|
|
}
|
|
else
|
|
{
|
|
nlwarning("Can't get menu %s or bad type", (const char *) prop);
|
|
}
|
|
}
|
|
|
|
|
|
// Override the modal behaviour because of sub menus
|
|
ExitClickOut = true;
|
|
ExitClickL = false;
|
|
ExitClickR = false;
|
|
ExitKeyPushed = true;
|
|
_ResizeFromChildH = _ResizeFromChildW = true;
|
|
_DisplayFrame = false;
|
|
_Active = false;
|
|
_Formatted = false;
|
|
|
|
// text colors
|
|
prop= (char*) xmlGetProp( in, (xmlChar*)"color" );
|
|
if (prop) _Color = convertColor(prop);
|
|
|
|
prop = (char*) xmlGetProp( in, (xmlChar*)"case_mode" );
|
|
if (prop)
|
|
{
|
|
sint32 caseMode;
|
|
fromString((const char*)prop, caseMode);
|
|
_CaseMode = (TCaseMode)caseMode;
|
|
}
|
|
|
|
prop= (char*) xmlGetProp( in, (xmlChar*)"shadow_color" );
|
|
if (prop) _ShadowColor = convertColor(prop);
|
|
|
|
prop= (char*) xmlGetProp( in, (xmlChar*)"color_over" );
|
|
if (prop) _ColorOver = convertColor(prop);
|
|
|
|
prop= (char*) xmlGetProp( in, (xmlChar*)"shadow_color_over" );
|
|
if (prop) _ShadowColorOver = convertColor(prop);
|
|
|
|
prop= (char*) xmlGetProp( in, (xmlChar*)"highlight_over" );
|
|
if (prop) _HighLightOver = convertColor(prop);
|
|
|
|
prop= (char*) xmlGetProp( in, (xmlChar*)"color_grayed" );
|
|
if (prop) _ColorGrayed = convertColor(prop);
|
|
|
|
prop= (char*) xmlGetProp( in, (xmlChar*)"shadow_color_grayed" );
|
|
if (prop) _ShadowColorGrayed = convertColor(prop);
|
|
|
|
prop = (char*) xmlGetProp (in, (xmlChar*)"space");
|
|
if (prop) fromString((const char*)prop, _Space);
|
|
|
|
// Text props
|
|
prop = (char*) xmlGetProp( in, (xmlChar*)"fontsize" );
|
|
if (prop) fromString((const char*)prop, _FontSize);
|
|
|
|
prop = (char*) xmlGetProp( in, (xmlChar*)"shadow" );
|
|
if (prop)
|
|
_Shadow = convertBool(prop);
|
|
|
|
prop = (char*) xmlGetProp( in, (xmlChar*)"formatted" );
|
|
if (prop)
|
|
_Formatted = convertBool(prop);
|
|
|
|
|
|
// Read sons
|
|
xmlNodePtr cur;
|
|
cur = in->children;
|
|
if (_RootMenu != NULL) delete _RootMenu;
|
|
_RootMenu = new CGroupSubMenu(CViewText::TCtorParam());
|
|
_RootMenu->_GroupMenu = this;
|
|
_RootMenu->parse (cur);
|
|
|
|
prop = (char*) xmlGetProp( in, (xmlChar*)"max_visible_line" );
|
|
if (prop)
|
|
{
|
|
sint32 maxVisibleLine;
|
|
fromString((const char*)prop, maxVisibleLine);
|
|
_RootMenu->setMaxVisibleLine(maxVisibleLine);
|
|
}
|
|
|
|
if (gmExtended)
|
|
{
|
|
gmExtended->cloneMenu(_RootMenu, this);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupMenu::recurseDraw(CGroupSubMenu *pSubMenu)
|
|
{
|
|
pSubMenu->draw();
|
|
|
|
// const vector<CInterfaceGroup*> &rGroups = pSubMenu->getGroups();
|
|
|
|
for (uint32 i = 0; i < pSubMenu->getNumLines(); i++)
|
|
{
|
|
CGroupSubMenu *pGSM = pSubMenu->getSubMenu(i);
|
|
if (pGSM != NULL)
|
|
{
|
|
recurseDraw(pGSM);
|
|
CInterfaceManager::getInstance()->getViewRenderer().flush();
|
|
}
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupMenu::draw ()
|
|
{
|
|
if (!_Active) return;
|
|
|
|
// TEMP TEMP
|
|
//CViewRenderer &rVR = CInterfaceManager::getInstance()->getViewRenderer();
|
|
//rVR.drawRotFlipBitmap _RenderLayer, (_XReal, _YReal, _WReal, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(255, 0, 0, 255) );
|
|
|
|
_RootMenu->_Active = true;
|
|
|
|
if (SpawnOnMousePos)
|
|
recurseDraw(_RootMenu);
|
|
else
|
|
CGroupModal::draw();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
bool CGroupMenu::handleEvent (const CEventDescriptor &event)
|
|
{
|
|
if (!_Active)
|
|
return false;
|
|
return CGroupModal::handleEvent (event);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CInterfaceElement* CGroupMenu::getElement (const std::string &id)
|
|
{
|
|
if (id == getId()) return this;
|
|
CInterfaceElement *pIE = _RootMenu->getElement(id);
|
|
if (pIE != NULL)
|
|
return pIE;
|
|
return CGroupModal::getElement(id);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupMenu::setActive (bool state)
|
|
{
|
|
if (SpawnOnMousePos)
|
|
{
|
|
CViewRenderer &rVR = CInterfaceManager::getInstance()->getViewRenderer();
|
|
uint32 w,h;
|
|
rVR.getScreenSize(w,h);
|
|
setW(w);
|
|
setH(h);
|
|
setX(0);
|
|
setY(0);
|
|
_ResizeFromChildH = _ResizeFromChildW = false;
|
|
_RootMenu->_PosRef = Hotspot_TL;
|
|
_RootMenu->_ParentPosRef = Hotspot_BL;
|
|
}
|
|
|
|
CGroupFrame::setActive (state);
|
|
|
|
// must recompute now the pos of the menu
|
|
uint32 i;
|
|
for (i = 0; i < _ChildrenGroups.size(); ++i)
|
|
{
|
|
_ChildrenGroups[i]->setActive (true);
|
|
}
|
|
|
|
CGroupModal::updateCoords();
|
|
|
|
// hide sub menus
|
|
_RootMenu->hideSubMenus();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
bool CGroupSubMenu::isSeparator(uint i) const
|
|
{
|
|
if (i >= _SubMenus.size())
|
|
{
|
|
nlassert("bad index");
|
|
return false;
|
|
}
|
|
return _Lines[i].Separator != NULL;
|
|
}
|
|
// ------------------------------------------------------------------------------------------------
|
|
bool CGroupMenu::isWindowUnder (sint32 x, sint32 y)
|
|
{
|
|
for (uint32 i = 0; i < _ChildrenGroups.size(); ++i)
|
|
if (_ChildrenGroups[i]->getActive ())
|
|
if (_ChildrenGroups[i]->isWindowUnder(x, y))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupMenu::addLine (const string &name, const string &ah, const string ¶ms,
|
|
const std::string &id/*=std::string()*/,
|
|
const std::string &cond /*= std::string()*/, const std::string &texture,
|
|
bool checkable /*= false*/, bool checked /*= false*/
|
|
)
|
|
{
|
|
if (_RootMenu == NULL)
|
|
{
|
|
_RootMenu = new CGroupSubMenu(CViewText::TCtorParam());
|
|
_RootMenu->_GroupMenu = this;
|
|
addGroup (_RootMenu);
|
|
}
|
|
|
|
_RootMenu->addLine (name, ah, params, id, cond, texture, checkable, checked, _Formatted);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupMenu::addLine(const ucstring &name, const std::string &ah, const std::string ¶ms,
|
|
const std::string &id /* = std::string()*/,
|
|
const std::string &cond /*= std::string()*/, const std::string &texture,
|
|
bool checkable /*= false*/, bool checked /*= false*/
|
|
)
|
|
{
|
|
if (_RootMenu == NULL)
|
|
{
|
|
_RootMenu = new CGroupSubMenu(CViewText::TCtorParam());
|
|
_RootMenu->_GroupMenu = this;
|
|
addGroup (_RootMenu);
|
|
}
|
|
_RootMenu->addLine (name, ah, params, id, cond, texture, checkable, checked, _Formatted);
|
|
}
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupMenu::addLineAtIndex(uint index, const ucstring &name, const std::string &ah,
|
|
const std::string ¶ms, const std::string &id /*=std::string()*/,
|
|
const std::string &cond /*=std::string()*/, const std::string &texture,
|
|
bool checkable /*=false*/, bool checked /*=false*/)
|
|
{
|
|
if (_RootMenu == NULL)
|
|
{
|
|
_RootMenu = new CGroupSubMenu(CViewText::TCtorParam());
|
|
_RootMenu->_GroupMenu = this;
|
|
addGroup (_RootMenu);
|
|
}
|
|
_RootMenu->addLineAtIndex(index, name, ah, params, id, cond, texture, checkable, checked, _Formatted);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupMenu::reset ()
|
|
{
|
|
if ( _RootMenu )
|
|
{
|
|
_RootMenu->reset();
|
|
invalidateCoords();
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupMenu::setMinW(sint32 minW)
|
|
{
|
|
if ( _RootMenu )
|
|
{
|
|
_RootMenu->_GroupList->setMinW(minW-_RootMenu->getResizeFromChildWMargin());
|
|
_RootMenu->_GroupList->setW(minW-_RootMenu->getResizeFromChildWMargin());
|
|
_RootMenu->setW(minW-_RootMenu->getResizeFromChildWMargin());
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupMenu::setGrayedLine(uint line, bool g)
|
|
{
|
|
if ( _RootMenu )
|
|
{
|
|
_RootMenu->setGrayedLine(line, g);
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
uint CGroupMenu::getNumLine() const
|
|
{
|
|
return _RootMenu ? _RootMenu->getNumLine() : 0;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupMenu::deleteLine(uint index)
|
|
{
|
|
if (index > getNumLine())
|
|
{
|
|
nlwarning("bad index");
|
|
return;
|
|
}
|
|
_RootMenu->removeLine(index);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
const std::string CGroupMenu::getActionHandler(uint lineIndex) const
|
|
{
|
|
return _RootMenu ? _RootMenu->getActionHandler(lineIndex) : "";
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
const std::string CGroupMenu::getActionHandlerParam(uint lineIndex) const
|
|
{
|
|
return _RootMenu ? _RootMenu->getActionHandlerParam(lineIndex) : "";
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupMenu::setUserGroupRight(uint line, CInterfaceGroup *gr, bool ownerShip /*=true*/)
|
|
{
|
|
if (_RootMenu)
|
|
{
|
|
_RootMenu->setUserGroupRight(line, gr, ownerShip);
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void CGroupMenu::setUserGroupLeft(uint line, CInterfaceGroup *gr, bool ownerShip /*=true*/)
|
|
{
|
|
if (_RootMenu)
|
|
{
|
|
_RootMenu->setUserGroupLeft(line, gr, ownerShip);
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupMenu::luaGetRootMenu(CLuaState &ls)
|
|
{
|
|
CLuaIHM::checkArgCount(ls, "getRootMenu", 0);
|
|
CLuaIHM::pushUIOnStack(ls, getRootMenu());
|
|
return 1;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int CGroupMenu::luaSetMinW(CLuaState &ls)
|
|
{
|
|
const char *funcName = "setMinW";
|
|
CLuaIHM::checkArgCount(ls, funcName, 1);
|
|
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
|
|
setMinW((sint32) ls.toNumber(1));
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|