// Ryzom - MMORPG Framework
// 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 .
#include "libxml/globals.h"
#include "nel/misc/debug.h"
#include "nel/misc/xml_auto_ptr.h"
#include "nel/gui/ctrl_base.h"
#include "nel/gui/interface_group.h"
#include "nel/gui/widget_manager.h"
#include "nel/misc/i18n.h"
using namespace NLMISC;
namespace NLGUI
{
// ***************************************************************************
CCtrlBase::~CCtrlBase()
{
CWidgetManager::getInstance()->removeRefOnCtrl (this);
}
// ***************************************************************************
bool CCtrlBase::handleEvent(const NLGUI::CEventDescriptor &event)
{
if (event.getType() == NLGUI::CEventDescriptor::system)
{
NLGUI::CEventDescriptorSystem &eds = (NLGUI::CEventDescriptorSystem&)event;
if (eds.getEventTypeExtended() == NLGUI::CEventDescriptorSystem::activecalledonparent)
{
if (!((NLGUI::CEventDescriptorActiveCalledOnParent &) eds).getActive())
{
// the mouse capture should be lost when the ctrl is hidden
if (CWidgetManager::getInstance()->getCapturePointerLeft() == this)
{
CWidgetManager::getInstance()->setCapturePointerLeft(NULL);
}
if (CWidgetManager::getInstance()->getCapturePointerRight() == this)
{
CWidgetManager::getInstance()->setCapturePointerRight(NULL);
}
// NB : don't call return here because derived class may be interested
// in handling event more speciffically
}
}
}
return false;
}
std::string CCtrlBase::tooltipParentToString( TToolTipParentType type )
{
switch( type )
{
case TTMouse:
return "mouse";
break;
case TTWindow:
return "win";
break;
case TTSpecialWindow:
return "special";
break;
}
return "";
}
CCtrlBase::TToolTipParentType CCtrlBase::stringToToolTipParent( const std::string &str )
{
std::string s = toLower( str );
if( s == "mouse" )
return TTMouse;
else
if( s == "win" )
return TTWindow;
else
if( s == "special" )
return TTSpecialWindow;
else
return TTCtrl;
}
// ***************************************************************************
bool CCtrlBase::parse (xmlNodePtr cur, CInterfaceGroup *parentGroup)
{
if(!CViewBase::parse(cur, parentGroup))
return false;
CXMLAutoPtr prop;
// get static toolTip
prop = (char*) xmlGetProp( cur, (xmlChar*)"tooltip" );
if (prop)
{
const char *propPtr = prop;
_ContextHelp = ucstring(propPtr);
if( !editorMode && ( strlen(propPtr) > 2 ) )
{
if ((propPtr[0] == 'u') && (propPtr[1] == 'i'))
_ContextHelp = CI18N::get ((const char *) prop);
}
}
// Force I18N tooltip
prop = (char*) xmlGetProp( cur, (xmlChar*)"tooltip_i18n" );
if ((bool)prop && strlen((const char*)prop)>0)
{
if( !editorMode )
_ContextHelp = CI18N::get ((const char *) prop);
else
_ContextHelp = (const char*)prop;
}
// get dynamic toolTip ActionHandler
prop = (char*) xmlGetProp( cur, (xmlChar*)"on_tooltip" );
if (prop)
{
_OnContextHelp= (const char*)prop;
}
prop = (char*) xmlGetProp( cur, (xmlChar*)"on_tooltip_params" );
if (prop)
{
_OnContextHelpParams= (const char*)prop;
}
// Tooltip parent
prop = (char*) xmlGetProp( cur, (xmlChar*)"tooltip_parent" );
_ToolTipParent= TTCtrl;
if(prop)
{
_ToolTipParent = stringToToolTipParent( std::string( prop ) );
}
// Tooltip special parent
prop = (char*) xmlGetProp( cur, (xmlChar*)"tooltip_special_parent" );
_ToolTipSpecialParent= CStringShared();
if(prop)
{
_ToolTipSpecialParent= std::string((const char*)prop);
}
// Tooltip posref
THotSpot tmpParentHS, tmpChildHS;
prop = (char*) xmlGetProp( cur, (xmlChar*)"tooltip_posref" );
convertTooltipHotSpot(prop, tmpParentHS, tmpChildHS);
_ToolTipParentPosRef= tmpParentHS;
_ToolTipPosRef= tmpChildHS;
// Alternative tooltip posref : this one will be chosen
prop = (char*) xmlGetProp( cur, (xmlChar*)"tooltip_posref_alt" );
convertTooltipHotSpot(prop, tmpParentHS, tmpChildHS);
_ToolTipParentPosRefAlt = tmpParentHS;
_ToolTipPosRefAlt = tmpChildHS;
// ToolTip instant
prop = (char*) xmlGetProp( cur, (xmlChar*)"instant_help");
_ToolTipInstant= true;
if (prop) _ToolTipInstant = convertBool(prop);
return true;
}
std::string CCtrlBase::getProperty( const std::string &name ) const
{
if( name == "tooltip" )
{
return _ContextHelp.toString();
}
else
if( name == "tooltip_i18n" )
{
return _ContextHelp.toString();
}
else
if( name == "on_tooltip" )
{
return _OnContextHelp.toString();
}
else
if( name == "on_tooltip_params" )
{
return _OnContextHelpParams.toString();
}
else
if( name == "tooltip_parent" )
{
return tooltipParentToString( _ToolTipParent );
}
else
if( name == "tooltip_special_parent" )
{
return _ToolTipSpecialParent.toString();
}
else
if( name == "tooltip_posref" )
{
std::string s;
if( ( _ToolTipParentPosRef == Hotspot_TTAuto ) && ( _ToolTipPosRef == Hotspot_TTAuto ) )
return "auto";
else{
s = CInterfaceElement::HotSpotToString( _ToolTipParentPosRef );
s += " ";
s += CInterfaceElement::HotSpotToString( _ToolTipPosRef );
return s;
}
}
else
if( name == "tooltip_posref_alt" )
{
std::string s;
if( ( _ToolTipParentPosRefAlt == Hotspot_TTAuto ) && ( _ToolTipPosRefAlt == Hotspot_TTAuto ) )
return "auto";
else{
s = CInterfaceElement::HotSpotToString( _ToolTipParentPosRefAlt );
s += " ";
s += CInterfaceElement::HotSpotToString( _ToolTipPosRefAlt );
return s;
}
}
else
if( name == "instant_help" )
{
return toString( _ToolTipInstant );
}
else
return CInterfaceElement::getProperty( name );
}
void CCtrlBase::setProperty( const std::string &name, const std::string &value )
{
if( name == "tooltip" )
{
_ContextHelp = value;
return;
}
else
if( name == "tooltip_i18n" )
{
_ContextHelp = value;
return;
}
else
if( name == "on_tooltip" )
{
_OnContextHelp = value;
return;
}
else
if( name == "on_tooltip_params" )
{
_OnContextHelpParams = value;
return;
}
else
if( name == "tooltip_parent" )
{
_ToolTipParent = stringToToolTipParent( value );
return;
}
else
if( name == "tooltip_special_parent" )
{
_ToolTipSpecialParent = value;
return;
}
else
if( name == "tooltip_posref" )
{
THotSpot parentHS;
THotSpot HS;
convertTooltipHotSpot( value.c_str(), parentHS, HS );
_ToolTipParentPosRef = parentHS;
_ToolTipPosRef = HS;
return;
}
else
if( name == "tooltip_posref_alt" )
{
THotSpot parentHS;
THotSpot HS;
convertTooltipHotSpot( value.c_str(), parentHS, HS );
_ToolTipParentPosRefAlt = parentHS;
_ToolTipPosRefAlt = HS;
return;
}
else
if( name == "instant_help" )
{
bool b;
if( fromString( value, b ) )
_ToolTipInstant = b;
return;
}
else
CInterfaceElement::setProperty( name, value );
}
xmlNodePtr CCtrlBase::serialize( xmlNodePtr parentNode, const char *type ) const
{
xmlNodePtr node =
CInterfaceElement::serialize( parentNode, type );
if( node == NULL )
return NULL;
xmlNewProp( node, BAD_CAST "tooltip", BAD_CAST _ContextHelp.toString().c_str() );
xmlNewProp( node, BAD_CAST "tooltip_i18n", BAD_CAST _ContextHelp.toString().c_str() );
xmlNewProp( node, BAD_CAST "on_tooltip", BAD_CAST _OnContextHelp.toString().c_str() );
xmlNewProp( node, BAD_CAST "on_tooltip_params", BAD_CAST _OnContextHelpParams.toString().c_str() );
xmlNewProp( node, BAD_CAST "tooltip_parent", BAD_CAST tooltipParentToString( _ToolTipParent ).c_str() );
xmlNewProp( node, BAD_CAST "tooltip_special_parent", BAD_CAST _ToolTipSpecialParent.toString().c_str() );
xmlNewProp( node, BAD_CAST "tooltip_posref",
BAD_CAST TooltipHotSpotToString( _ToolTipParentPosRef, _ToolTipPosRef ).c_str() );
xmlNewProp( node, BAD_CAST "tooltip_posref_alt",
BAD_CAST TooltipHotSpotToString( _ToolTipParentPosRefAlt, _ToolTipPosRefAlt ).c_str() );
xmlNewProp( node, BAD_CAST "instant_help", BAD_CAST toString( _ToolTipInstant ).c_str() );
return node;
}
// ***************************************************************************
void CCtrlBase::convertTooltipHotSpot(const char *prop, THotSpot &parentHS, THotSpot &childHS)
{
parentHS = Hotspot_TTAuto;
childHS = Hotspot_TTAuto;
if(prop)
{
const char *ptr= (const char*)prop;
if(stricmp(ptr, "auto")==0)
{
parentHS = Hotspot_TTAuto;
childHS = Hotspot_TTAuto;
}
// valid ref?
else if(strlen(ptr)>=5)
{
THotSpot parentPosRef;
THotSpot posRef;
CInterfaceElement::convertHotSpotCouple(ptr, parentPosRef, posRef);
parentHS = parentPosRef;
childHS = posRef;
}
}
}
std::string CCtrlBase::TooltipHotSpotToString( THotSpot parent, THotSpot child )
{
std::string s;
if( ( parent == Hotspot_TTAuto ) && ( child == Hotspot_TTAuto ) )
{
s = "auto";
}
else
{
s = CInterfaceElement::HotSpotToString( parent );
s += " ";
s += CInterfaceElement::HotSpotToString( child );
}
return s;
}
// ***************************************************************************
bool CCtrlBase::emptyContextHelp() const
{
ucstring help;
getContextHelp(help);
std::string sTmp = _OnContextHelp;
return help.empty() && sTmp.empty();
}
// ***************************************************************************
void CCtrlBase::visit(CInterfaceElementVisitor *visitor)
{
nlassert(visitor);
visitor->visitCtrl(this);
CInterfaceElement::visit(visitor);
}
// ***************************************************************************
void CCtrlBase::serial(NLMISC::IStream &f)
{
CViewBase::serial(f);
f.serial(_ContextHelp);
f.serial(_OnContextHelp);
f.serial(_OnContextHelpParams);
f.serial(_ToolTipSpecialParent);
f.serialEnum(_ToolTipParent);
//
THotSpot tmpToolTipParentPosRef = _ToolTipParentPosRef;
THotSpot tmpToolTipPosRef = _ToolTipPosRef;
THotSpot tmpToolTipParentPosRefAlt = _ToolTipParentPosRefAlt;
THotSpot tmpToolTipPosRefAlt = _ToolTipPosRefAlt;
f.serialEnum(tmpToolTipParentPosRef);
f.serialEnum(tmpToolTipPosRef);
f.serialEnum(tmpToolTipParentPosRefAlt);
f.serialEnum(tmpToolTipPosRefAlt);
_ToolTipParentPosRef = tmpToolTipParentPosRef;
_ToolTipPosRef = tmpToolTipPosRef;
_ToolTipParentPosRefAlt = tmpToolTipParentPosRefAlt;
_ToolTipPosRefAlt = tmpToolTipPosRefAlt;
//
nlSerialBitBool(f, _ToolTipInstant);
}
// ***************************************************************************
std::string CCtrlBase::getContextHelpWindowName() const
{
return "context_help";
}
uint32 CCtrlBase::getDepth( CInterfaceGroup *group )
{
uint32 depth = 1;
CInterfaceGroup *parent = getParent();
while( parent != NULL )
{
if ( parent == group )
break;
else
parent = parent->getParent();
depth++;
}
// The Resizer Ctrls take the precedence over Sons controls.
return depth + getDeltaDepth();
}
}