Files
Leviathan/Client/Game/engine/Ui/KUIParser.cpp
T
2026-06-01 12:46:52 +02:00

529 lines
13 KiB
C++

#include "stdafx.h"
#include "KUIDefine.h"
#include "KUIParser.h"
#include "KUIFactory.h"
//#include "KUIUtil.h"
#pragma warning(disable:4267)
#pragma warning(disable:4312)
namespace KTOKEN_HANDLER
{
const int KTOKEN_BEGIN = 40;
const int KTOKEN_END = 41;
const int KTOKEN_ID = 42;
const int KTOKEN_ANI = 43;
const int KTOKEN_SPR = 44;
const int KTOKEN_FRAME = 45;
const int KTOKEN_RECT = 46;
const int KTOKEN_POS = 47;
const int KTOKEN_CAPTION = 48;
const int KTOKEN_TOOLTIP = 49;
const int KTOKEN_STYLE = 50;
const int KTOKEN_FLAG = 51;
const int KTOKEN_ANCHOR = 52;
const int KTOKEN_ADD_BUTTON = 53;
const int KTOKEN_GENWND = 54;
}
BEGIN_KTOKEN_MAP(KUIParser)
ON_KTOKEN("begin",KTOKEN_BEGIN,&KUIParser::_OnBeginToken)
ON_KTOKEN("end",KTOKEN_END,&KUIParser::_OnEndToken)
ON_KTOKEN("id",KTOKEN_ID, &KUIParser::_OnPropetyToken)
ON_KTOKEN("ani",KTOKEN_ANI, &KUIParser::_OnPropetyToken)
ON_KTOKEN("spr",KTOKEN_SPR, &KUIParser::_OnPropetyToken)
ON_KTOKEN("frame",KTOKEN_FRAME, &KUIParser::_OnPropetyToken)
ON_KTOKEN("rect",KTOKEN_RECT, &KUIParser::_OnPropetyToken)
ON_KTOKEN("pos",KTOKEN_POS, &KUIParser::_OnPropetyToken)
ON_KTOKEN("caption", KTOKEN_CAPTION, &KUIParser::_OnPropetyToken)
//ON_KTOKEN("tooltip",KTOKEN_TOOLTIP,&KUIParser::_OnPropetyToken)
ON_KTOKEN("info",KTOKEN_TOOLTIP,&KUIParser::_OnPropetyToken)
ON_KTOKEN("style", KTOKEN_STYLE, &KUIParser::_OnPropetyToken)
ON_KTOKEN("flag",KTOKEN_FLAG,&KUIParser::_OnPropetyToken)
ON_KTOKEN("anchor",KTOKEN_ANCHOR,&KUIParser::_OnPropetyToken)
ON_KTOKEN("add_button",KTOKEN_ADD_BUTTON,&KUIParser::_OnPropetyToken)
ON_KTOKEN("genwnd", KTOKEN_GENWND, &KUIParser::_OnGenWndCreate )
END_KTOKEN_MAP()
namespace
{
std::map<std::string, DWORD> MAP_STYLE;
std::map<std::string, DWORD> MAP_FLAG;
std::map<std::string, DWORD> MAP_ANCHOR;
struct MAPPING_INFO
{
DWORD dwFlag;
std::string sName;
};
void registerMappingInfo(std::map<std::string, DWORD>& mapInfo, MAPPING_INFO* pInfoArray, int nCount)
{
for(int i = 0; i < nCount; ++i)
mapInfo.insert( std::make_pair( pInfoArray[i].sName, pInfoArray[i].dwFlag) );
}
bool initMapInfo()
{
MAPPING_INFO STYLE_ARRAY[] =
{
// GenWnd
{ KSTYLE_NOCLOSE, "KSTYLE_NOCLOSE" },
{ KSTYLE_NOMINIMIZE, "KSTYLE_NOMINIMIZE" },
{ KSTYLE_NORESIZE, "KSTYLE_NORESIZE" },
{ KSTYLE_NOTITLE, "KSTYLE_NOTITLE" },
{ KSTYLE_NOSTATUSBAR, "KSTYLE_NOSTATUSBAR" },
{ KSTYLE_VSCROLL, "KSTYLE_VSCROLL"},
{ KSTYLE_HSCROLL, "KSTYLE_HSCROLL"},
{ KSTYLE_NOFRAME, "KSTYLE_NOFRAME"},
{ KSTYLE_NOTOPFRAME, "KSTYLE_NOTOPFRAME"},
{ KSTYLE_NOBACKGROUND, "KSTYLE_NOBACKGROUND"},
{ KSTYLE_RESIZE_LEFT, "KSTYLE_RESIZE_LEFT"},
{ KSTYLE_RESIZE_TOP, "KSTYLE_RESIZE_TOP"},
{ KSTYLE_MOVE_BY_TITLEBAR, "KSTYLE_MOVE_BY_TITLEBAR"},
{ KSTYLE_MOVE_BY_TOPFRAME, "KSTYLE_MOVE_BY_TOPFRAME"},
{ KSTYLE_MOVE_BY_ALL, "KSTYLE_MOVE_BY_ALL"},
{ KSTYLE_MOVE_BY_CUSTOM, "KSTYLE_MOVE_BY_CUSTOM"},
{ KSTYLE_NO_CLIPPING, "KSTYLE_NO_CLIPPING"},
{ KSTYLE_VERTICAL_REPEAT, "KSTYLE_VERTICAL_REPEAT"},
{ KSTYLE_HORIZONTAL_REPEAT, "KSTYLE_HORIZONTAL_REPEAT"},
{ KSTYLE_SPR_CAPTION, "KSTYLE_SPR_CAPTION"},
{ KSTYLE_ALPHA_SHOW, "KSTYLE_ALPHA_SHOW" },
// button
{ KSTYLE_BUTTON_LEFTSIDE, "KSTYLE_BUTTON_LEFTSIDE"},
{ KSTYLE_BUTTON_RIGHTSIDE, "KSTYLE_BUTTON_RIGHTSIDE"},
{ KSTYLE_BUTTON_CANDRAG, "KSTYLE_BUTTON_CANDRAG"},
{ KSTYLE_BUTTON_VERTICAL, "KSTYLE_BUTTON_VERTICAL"},
{ KSTYLE_CHECK_CAPTION_RIGHT, "KSTYLE_CHECK_CAPTION_RIGHT"},
// status bar
{ KSTYLE_SB_NOLEFTSIDE, "KSTYLE_SB_NOLEFTSIDE"},
{ KSTYLE_SB_NORIGHTSIDE, "KSTYLE_SB_NORIGHTSIDE"},
// Tab Control
{ KSTYLE_TAB_VERTICAL, "KSTYLE_TAB_VERTICAL"},
// Number Control
{ KSTYLE_NUMBER_LEFT, "KSTYLE_NUMBER_LEFT"},
{ KSTYLE_NUMBER_CENTER, "KSTYLE_NUMBER_CENTER"},
{ KSTYLE_NUMBER_RIGHT, "KSTYLE_NUMBER_RIGHT"},
// Gauge Control
{ KSTYLE_GAUGE_WITH_GRADUATION, "KSTYLE_GAUGE_WITH_GRADUATION" },
// Msg Control
{ KSTYLE_MSG_VERTICAL_REPEAT, "KSTYLE_MSG_VERTICAL_REPEAT"},
{ KSTYLE_MSG_HORIZONTAL_REPEAT, "KSTYLE_MSG_HORIZONTAL_REPEAT"},
};
registerMappingInfo( MAP_STYLE, STYLE_ARRAY, _countof(STYLE_ARRAY) );
MAPPING_INFO FLAG_ARRAY[] =
{
// GenWnd
{ KFLAG_NO_GET_MESSAGE, "KFLAG_NO_GET_MESSAGE" },
{ KFLAG_GET_PASS_MESSAGE, "KFLAG_GET_PASS_MESSAGE" },
{ KFLAG_CAN_DRAG, "KFLAG_CAN_DRAG" },
{ KFLAG_SINGLE_LINE, "KFLAG_SINGLE_LINE" },
{ KFLAG_NO_GET_FOCUS, "KFLAG_NO_GET_FOCUS" },
};
registerMappingInfo(MAP_FLAG ,FLAG_ARRAY, _countof(FLAG_ARRAY));
MAPPING_INFO ANCHOR_ARRAY[] =
{
// GenWnd
{ KANCHOR_LEFT, "KANCHOR_LEFT" },
{ KANCHOR_RIGHT, "KANCHOR_RIGHT" },
{ KANCHOR_TOP, "KANCHOR_TOP" },
{ KANCHOR_BOTTOM, "KANCHOR_BOTTOM" },
};
registerMappingInfo(MAP_ANCHOR, ANCHOR_ARRAY, _countof(ANCHOR_ARRAY));
return true;
}
DWORD getStringToDWORD(LPCSTR lpszName, std::map<std::string, DWORD>& mapInfo)
{
std::map<std::string, DWORD>::iterator it = mapInfo.find( std::string ( lpszName ) );
if( it == mapInfo.end() )
return 0;
return it->second;
}
bool bInitMapInfo = initMapInfo();
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// KUIParser Implement
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
KUIParser::KUIParser()
{
static char Whitespacechr[] = {'\n', '\r', ' ', '\t', '|'};
static char Tokendata[] =
{
KTOKEN_HANDLER::KTOKEN_COMMA, ',' ,
KTOKEN_HANDLER::KTOKEN_ASSIGN, '=' ,
KTOKEN_HANDLER::KTOKEN_SEMI_COLON, ';' ,
};
m_TokenParser.SetWhiteSpaceChar(Whitespacechr, _countof(Whitespacechr) );
m_TokenParser.SetTokenChar(Tokendata, _countof(Tokendata) );
_InitializeTokenMap();
Clear();
}
KUIParser::~KUIParser()
{
Clear();
}
void KUIParser::Clear()
{
m_bErrorFound = false;
m_nStage = KSTAGE_CONTROL_START; m_nSubStage = 0;
m_pParentObj = NULL;
SAFE_DELETE_VECTOR( m_vtParseObj );
}
bool KUIParser::DoParsing(KStream& stream)
{
Clear();
m_TokenParser.LoadStream(stream);
return !m_bErrorFound;
}
DWORD KUIParser::GetParseObjCount()
{
return m_vtParseObj.size();
}
KUIWndParseObject* KUIParser::GetParseObject(DWORD dwIndex)
{
if( dwIndex >= m_vtParseObj.size() )
{
assert(false && "Invalid Index");
return NULL;
}
return m_vtParseObj[dwIndex];
}
K_TOKEN_CALL void KUIParser::_OnNoTokenFound(DWORD dwStringPointer, DWORD dwLineCount,DWORD dwReserve1)
{
LPCSTR lpszToken = reinterpret_cast<LPCSTR>(dwStringPointer);
// Create 상태다
switch( m_nStage)
{
case KSTAGE_CONTROL_CREATE:
// 찾을수 없는 control
if( false == KUIFactory::GetInstance()->IsRegister( lpszToken) )
{
// 무조건 Error
_ErrMsgBox("파싱 에러 %d Line. 등록되지 않은 Control 입니다", dwLineCount);
return;
}
m_CurrentArg.lpszClassName = lpszToken;
m_nStage = KSTAGE_CONTROL_PROPERTY;
break;
case KSTAGE_CONTROL_ASSIGN:
_DoAssign( lpszToken, dwLineCount);
break;
default:
_ErrMsgBox("파싱 에러 %d Line. 알수 없는 Token ( %s ) 입니다", dwLineCount, lpszToken);
assert( 0 && "NUI 파싱 에러" );
return;
}
}
K_TOKEN_CALL void KUIParser::_OnCharTokenFound(DWORD dwCharType, DWORD dwLineCount, DWORD dwReserve1)
{
switch( dwCharType )
{
case KTOKEN_HANDLER::KTOKEN_SEMI_COLON:
{
_CheckStageError(KSTAGE_CONTROL_ASSIGN, dwLineCount);
m_nStage = KSTAGE_CONTROL_PROPERTY;
}
break;
default:
break;
}
}
K_TOKEN_CALL void KUIParser::_OnTokenEnd()
{
if( m_nStage != KSTAGE_CONTROL_START)
_ErrMsgBox(" end 를 빼먹었습니다");
}
K_TOKEN_CALL void KUIParser::_OnBeginToken(DWORD dwTokenID, DWORD dwLineCount,DWORD dwReserve2)
{
_CheckStageError(KSTAGE_CONTROL_START, dwLineCount);
m_nStage = KSTAGE_CONTROL_CREATE;
// Argument 초기화
m_CurrentArg = KUIWND_CREATE_ARG();
}
K_TOKEN_CALL void KUIParser::_OnEndToken(DWORD dwTokenID, DWORD dwLineCount,DWORD dwReserve2)
{
_CheckStageError(KSTAGE_CONTROL_PROPERTY,dwLineCount);
m_nStage = KSTAGE_CONTROL_START;
if( NULL == m_pParentObj)
return;
if (m_CurrentArg.lpszClassName != "genwnd" )
m_pParentObj->AddChildObj( m_CurrentArg );
else
m_pParentObj->SetCreateArg( m_CurrentArg );
}
K_TOKEN_CALL void KUIParser::_OnPropetyToken(DWORD dwTokenID, DWORD dwLineCount,DWORD dwReserve1)
{
_CheckStageError(KSTAGE_CONTROL_PROPERTY,dwLineCount);
m_nStage = KSTAGE_CONTROL_ASSIGN;
m_nSubStage = dwTokenID;
}
K_TOKEN_CALL void KUIParser::_OnGenWndCreate(DWORD dwTokenID, DWORD dwLineCount,DWORD dwReserve1)
{
_CheckStageError(KSTAGE_CONTROL_CREATE,dwLineCount);
m_nStage = KSTAGE_CONTROL_PROPERTY;
m_pParentObj = new KUIWndParseObject;
m_CurrentArg.lpszClassName = "genwnd";
m_vtParseObj.push_back( m_pParentObj) ;
}
void KUIParser::_DoAssign(LPCSTR lpszToken, DWORD dwLineCount)
{
_CheckStageError(KSTAGE_CONTROL_ASSIGN, dwLineCount);
int IntValue = ::atoi( lpszToken);
using namespace KTOKEN_HANDLER;
switch ( m_nSubStage)
{
case KTOKEN_ID:
m_CurrentArg.lpszID = lpszToken;
break;
case KTOKEN_ANI:
m_CurrentArg.lpszAniName = lpszToken;
break;
case KTOKEN_SPR:
m_CurrentArg.lpszSprName = lpszToken;
break;
case KTOKEN_FRAME:
m_CurrentArg.nFrameIndex = IntValue;
break;
case KTOKEN_RECT:
{
static int nRectCount = 0;
static int nRectArray[4];
nRectArray[nRectCount] = IntValue;
nRectCount++;
if(nRectCount == 4)
{
m_CurrentArg.rcRect = KRect(nRectArray[0], nRectArray[1], nRectArray[2], nRectArray[3]);
nRectCount = 0;
}
}
break;
case KTOKEN_POS:
{
static int nPosCount = 0;
static int nPosArray[2];
nPosArray[nPosCount] = IntValue;
nPosCount++;
if(nPosCount == 2)
{
m_CurrentArg.rcRect = KRect(nPosArray[0], nPosArray[1], -1, -1);
nPosCount = 0;
}
}
break;
case KTOKEN_CAPTION:
m_CurrentArg.lpszCaption = lpszToken;
break;
case KTOKEN_TOOLTIP:
m_CurrentArg.lpszToolTip = lpszToken;
break;
case KTOKEN_STYLE:
{
DWORD dwStyle = getStringToDWORD( lpszToken, MAP_STYLE);
if( dwStyle == 0)
_ErrMsgBox( "파싱 에러 %d. 잘못된 Style (%s) 입니다.", dwLineCount, lpszToken);
m_CurrentArg.dwStyle |= dwStyle;
}
break;
case KTOKEN_FLAG:
{
DWORD dwFlag = getStringToDWORD( lpszToken, MAP_FLAG);
if( dwFlag == 0)
_ErrMsgBox( "파싱 에러 %d. 잘못된 Flag (%s) 입니다.", dwLineCount, lpszToken);
m_CurrentArg.dwFlag |= dwFlag;
}
break;
case KTOKEN_ANCHOR:
{
DWORD dwAnchor = getStringToDWORD( lpszToken, MAP_ANCHOR);
if( dwAnchor == 0)
_ErrMsgBox( "파싱 에러 %d. 잘못된 Anchor (%s) 입니다.", dwAnchor, lpszToken);
m_CurrentArg.dwAnchor |= dwAnchor;
}
break;
case KTOKEN_ADD_BUTTON:
break;
default:
_CheckStageError( -1, dwLineCount);
break;
}
}
void KUIParser::_CheckStageError(int nStage, DWORD dwLineNumber)
{
if(m_nStage != nStage)
{
char buff[512];
switch( nStage)
{
case KSTAGE_CONTROL_START:
sprintf(buff, "begin의 시작전에 잘 못된 값이 존재합니다");
break;
case KSTAGE_CONTROL_CREATE:
sprintf(buff, "begin Keyword가 필요합니다");
break;
case KSTAGE_CONTROL_PROPERTY:
sprintf(buff, " ; (semi colon)을 빼먹거나 Control을 생성하지 않았습니다");
break;
case KSTAGE_CONTROL_ASSIGN:
sprintf(buff, "Control의 속성을 지정하는 Keyword 이후에 사용해야 합니다");
break;
default:
sprintf(buff, "알수 없는 오류입니다");
break;
}
_ErrMsgBox( "파싱 에러 %d Line. %s", dwLineNumber, buff);
}
}
void KUIParser::_ErrMsgBox(LPCSTR lpszString, ...)
{
#ifndef NDEBUG
#ifndef _RELEASE
char szBuf[1024];
va_list va;
va_start( va, lpszString );
_vsnprintf( szBuf, _countof(szBuf), lpszString, va );
va_end( va );
MessageBox( NULL, szBuf, "Error", MB_OK);
#endif
#endif
m_bErrorFound = true;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// KUIWndParseObject Implement
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
KUIWndParseObject::KUIWndParseObject()
{
}
KUIWndParseObject::~KUIWndParseObject()
{
SAFE_DELETE_VECTOR( m_vtChildParseObj );
}
DWORD KUIWndParseObject::GetChildCount()
{
return m_vtChildParseObj.size();
}
KUIWndParseObject* KUIWndParseObject::GetChildParseObj(DWORD dwIndex)
{
if( dwIndex >= m_vtChildParseObj.size() )
{
assert(false && "Invalid Index");
return NULL;
}
return m_vtChildParseObj[dwIndex];
}
KUIWndParseObject* KUIWndParseObject::AddChildObj(const KUIWND_CREATE_ARG& arg)
{
KUIWndParseObject* pObj = new KUIWndParseObject;
pObj->SetCreateArg( arg );
m_vtChildParseObj.push_back( pObj );
return m_vtChildParseObj.back();
}
const KUIWND_CREATE_ARG& KUIWndParseObject::GetCreateArg() const
{
return m_CreateArg;
}
KUIWND_CREATE_ARG& KUIWndParseObject::GetCreateArg()
{
return m_CreateArg;
}
void KUIWndParseObject::SetCreateArg(const KUIWND_CREATE_ARG& arg)
{
m_CreateArg = arg;
}