etqw-sdk/source/game/guis/UILayout.cpp

544 lines
13 KiB
C++

// Copyright (C) 2007 Id Software, Inc.
//
#include "../precompiled.h"
#pragma hdrstop
#if defined( _DEBUG ) && !defined( ID_REDIRECT_NEWDELETE )
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "UserInterfaceManager.h"
#include "UILayout.h"
#include "UserInterfaceLocal.h"
using namespace sdProperties;
SD_UI_IMPLEMENT_CLASS( sdUILayout_Static, sdUIObject_Drawable )
idCVar gui_debugLayout( "gui_debugLayout", "0", CVAR_GAME | CVAR_BOOL, "Debug UI layout classes" );
/*
============
sdUILayout_Static::sdUILayout_Static
============
*/
sdUILayout_Static::sdUILayout_Static() {
GetScope().GetProperties().RegisterProperty( "rect", rect );
GetScope().GetProperties().RegisterProperty( "absoluteRect", absoluteRect );
GetScope().GetProperties().RegisterProperty( "visible", visible );
rect = idVec4( 0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT );
absoluteRect = rect;
absoluteRect.SetReadOnly( true );
visible = 1.0f;
recalculateLayout = true;
UI_ADD_VEC4_CALLBACK( rect, sdUILayout_StaticBase, OnRectChanged )
}
/*
============
sdUILayout_Static::~sdUILayout_Static
============
*/
sdUILayout_Static::~sdUILayout_Static() {
}
/*
============
sdUILayout_Static::ApplyLayout
============
*/
void sdUILayout_Static::ApplyLayout() {
if( recalculateLayout ) {
sdUIObject* object = GetNode().GetParent();
idVec4 cachedOffset( rect );
while( object != NULL ) {
if( sdProperty* rect = object->GetScope().GetProperty( "rect", sdProperties::PT_VEC4 ) ) {
cachedOffset.ToVec2() += rect->value.vec4Value->GetValue().ToVec2();
}
object = object->GetNode().GetParent();
}
absoluteRect.SetReadOnly( false );
absoluteRect = cachedOffset;
absoluteRect.SetReadOnly( true );
DoApplyLayout();
recalculateLayout = false;
}
sdUIObject::ApplyLayout();
}
/*
============
sdUILayout_Static::UpdateToolTip
============
*/
sdUIObject* sdUILayout_Static::UpdateToolTip( const idVec2& cursor ) {
if( !visible ) {
return NULL;
}
sdUIObject* prev = NULL;
sdUIObject* child = GetNode().GetChild();
while( child != NULL ) {
prev = child;
child = child->GetNode().GetSibling();
}
child = prev;
while( child != NULL ) {
if( sdUIObject* result = child->UpdateToolTip( cursor ) ) {
return result;
}
child = child->GetNode().GetPriorSibling();
}
return NULL;
}
/*
============
sdUILayout_Static::OnRectChanged
============
*/
void sdUILayout_Static::OnRectChanged( const idVec4& oldValue, const idVec4& newValue ) {
MakeLayoutDirty();
}
/*
============
sdUILayout_StaticBase::OnChildRectChanged
============
*/
void sdUILayout_StaticBase::OnChildRectChanged( const idVec4& oldValue, const idVec4& newValue ) {
for( int i = 0; i < childRects.Num(); i++ ) {
rectInfo_t& info = childRects[ i ];
info.rect.z = info.property->value.vec4Value->GetValue().z;
info.rect.w = info.property->value.vec4Value->GetValue().w;
}
MakeLayoutDirty();
}
/*
============
sdUILayout_Static::Draw
============
*/
void sdUILayout_Static::Draw() {
if( !visible ) {
return;
}
sdUIObject* child = GetNode().GetChild();
while( child != NULL ) {
if( sdUIObject_Drawable* window = child->Cast< sdUIObject_Drawable >() ) {
window->Draw();
}
child = child->GetNode().GetSibling();
}
if( gui_debugLayout.GetBool() ) {
deviceContext->DrawClippedBox( absoluteRect.GetValue().x, absoluteRect.GetValue().y, absoluteRect.GetValue().z, absoluteRect.GetValue().w, 1.0f, colorGreen );
}
}
/*
============
sdUILayout_Static::FinalDraw
============
*/
void sdUILayout_Static::FinalDraw() {
if( !visible ) {
return;
}
sdUIObject* child = GetNode().GetChild();
while( child != NULL ) {
if( sdUIObject_Drawable* window = child->Cast< sdUIObject_Drawable >() ) {
window->FinalDraw();
}
child = child->GetNode().GetSibling();
}
}
/*
============
sdUILayout_Static::PostEvent
============
*/
bool sdUILayout_Static::PostEvent( const sdSysEvent* event ) {
if( !visible ) {
return false;
}
sdUIObject* child = GetNode().GetChild();
while( child != NULL ) {
if( child->PostEvent( event ) ) {
return true;
}
child = child->GetNode().GetSibling();
}
return false;
}
/*
============
sdUILayout_Static::HandleFocus
============
*/
bool sdUILayout_Static::HandleFocus( const sdSysEvent* event ) {
if( !visible ) {
return false;
}
sdUIObject* prev = NULL;
sdUIObject* child = GetNode().GetChild();
while( child != NULL ) {
prev = child;
child = child->GetNode().GetSibling();
}
child = prev;
while( child != NULL ) {
if( child->HandleFocus( event ) ) {
return true;
}
child = child->GetNode().GetPriorSibling();
}
return false;
}
SD_UI_IMPLEMENT_CLASS( sdUILayout_StaticBase, sdUILayout_Static )
extern const char sdUITemplateFunctionInstance_IdentifierLayout_Table[] = "Layout_Table";
idHashMap< sdUILayout_StaticBase::sdUILayoutFunction* > sdUILayout_StaticBase::layoutFunctions;
/*
============
sdUILayout_StaticBase::sdUILayout_StaticBase
============
*/
sdUILayout_StaticBase::sdUILayout_StaticBase() {
GetScope().GetProperties().RegisterProperty( "margins", margins );
GetScope().GetProperties().RegisterProperty( "spacing", spacing );
margins = idVec4( 4.0f, 4.0f, 4.0f, 4.0f );
rect = idVec4( 0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT );
spacing = idVec2( 2.0f, 2.0f );
UI_ADD_VEC4_CALLBACK( margins, sdUILayout_StaticBase, OnMarginsChanged )
UI_ADD_VEC2_CALLBACK( spacing, sdUILayout_StaticBase, OnSpacingChanged )
}
/*
============
sdUILayout_StaticBase::~sdUILayout_StaticBase
============
*/
sdUILayout_StaticBase::~sdUILayout_StaticBase() {
}
/*
============
sdUILayout_StaticBase::GetFunction
============
*/
sdUIFunctionInstance* sdUILayout_StaticBase::GetFunction( const char* name ) {
const sdUILayoutFunction* function = sdUILayout_StaticBase::FindFunction( name );
if( !function ) {
return sdUIObject::GetFunction( name );
}
return new sdUITemplateFunctionInstance< sdUILayout_StaticBase, sdUITemplateFunctionInstance_IdentifierLayout_Table >( this, function );
}
/*
============
sdUILayout_StaticBase::FindFunction
============
*/
const sdUILayout_StaticBase::sdUILayoutFunction* sdUILayout_StaticBase::FindFunction( const char* name ) {
sdUILayoutFunction** ptr;
return layoutFunctions.Get( name, &ptr ) ? *ptr : NULL;
}
/*
============
sdUILayout_StaticBase::InitFunctions
============
*/
SD_UI_PUSH_CLASS_TAG( sdUILayout_StaticBase )
void sdUILayout_StaticBase::InitFunctions( void ) {
SD_UI_ENUM_TAG( VLF_DRAW_REVERSED, "Draw children in reverse order." )
sdDeclGUI::AddDefine( va( "VLF_DRAW_REVERSED %i", VLF_DRAW_REVERSED ) );
SD_UI_ENUM_TAG( VLF_NOSIZE, "Do not extend the child window widths to the right edge of the layout edge." )
sdDeclGUI::AddDefine( va( "VLF_NOSIZE %i", VLF_NOSIZE ) );
sdDeclGUI::AddDefine( va( "VLF_DYNAMIC_CHILDREN %i", VLF_DYNAMIC_CHILDREN ) );
}
SD_UI_POP_CLASS_TAG
/*
============
sdUILayout_StaticBase::OnMarginsChanged
============
*/
void sdUILayout_StaticBase::OnMarginsChanged( const idVec4& oldValue, const idVec4& newValue ) {
MakeLayoutDirty();
}
/*
============
sdUILayout_StaticBase::OnSpacingChanged
============
*/
void sdUILayout_StaticBase::OnSpacingChanged( const idVec2& oldValue, const idVec2& newValue ) {
MakeLayoutDirty();
}
/*
============
sdUILayout_StaticBase::OnCreate
============
*/
void sdUILayout_StaticBase::OnCreate() {
sdUIObject* child = GetNode().GetChild();
while( child != NULL ) {
sdProperty* property = child->GetScope().GetProperty( "rect", sdProperties::PT_VEC4 );
if( property != NULL ) {
rectInfo_t info;
info.property = property;
info.rect = *property->value.vec4Value;
info.source = child;
childRects.Append( info );
if( TestFlag( VLF_DYNAMIC_CHILDREN ) ) {
UI_ADD_VEC4_CALLBACK( ( *property->value.vec4Value ), sdUILayout_StaticBase, OnChildRectChanged )
}
}
child = child->GetNode().GetSibling();
}
}
/*
============
sdUILayout_StaticBase::Draw
============
*/
void sdUILayout_StaticBase::Draw() {
if( !visible ) {
return;
}
if( !TestFlag( VLF_DRAW_REVERSED ) ) {
sdUILayout_Static::Draw();
return;
}
sdUIObject* prev = NULL;
sdUIObject* child = GetNode().GetChild();
while( child != NULL ) {
prev = child;
child = child->GetNode().GetSibling();
}
child = prev;
while( child != NULL ) {
if( sdUIObject_Drawable* window = child->Cast< sdUIObject_Drawable >() ) {
window->Draw();
}
child = child->GetNode().GetPriorSibling();
}
if( gui_debugLayout.GetBool() ) {
deviceContext->DrawClippedBox( absoluteRect.GetValue().x, absoluteRect.GetValue().y, absoluteRect.GetValue().z, absoluteRect.GetValue().w, 1.0f, colorGreen );
}
}
/*
============
sdUILayout_StaticBase::FinalDraw
============
*/
void sdUILayout_StaticBase::FinalDraw() {
if( !TestFlag( VLF_DRAW_REVERSED ) ) {
sdUILayout_Static::FinalDraw();
return;
}
sdUIObject* prev = NULL;
sdUIObject* child = GetNode().GetChild();
while( child != NULL ) {
prev = child;
child = child->GetNode().GetSibling();
}
child = prev;
while( child != NULL ) {
if( sdUIObject_Drawable* window = child->Cast< sdUIObject_Drawable >() ) {
window->FinalDraw();
}
child = child->GetNode().GetPriorSibling();
}
}
/*
============
sdUILayout_StaticBase::PostEvent
============
*/
bool sdUILayout_StaticBase::PostEvent( const sdSysEvent* event ) {
if( !visible ) {
return false;
}
if( !TestFlag( VLF_DRAW_REVERSED ) ) {
return sdUILayout_Static::PostEvent( event );
}
sdUIObject* prev = NULL;
sdUIObject* child = GetNode().GetChild();
while( child != NULL ) {
prev = child;
child = child->GetNode().GetSibling();
}
child = prev;
while( child != NULL ) {
if( child->PostEvent( event ) ) {
return true;
}
child = child->GetNode().GetPriorSibling();
}
return false;
}
/*
============
sdUILayout_StaticBase::HandleFocus
============
*/
bool sdUILayout_StaticBase::HandleFocus( const sdSysEvent* event ) {
if( !visible ) {
return false;
}
if( !TestFlag( VLF_DRAW_REVERSED ) ) {
return sdUILayout_Static::HandleFocus( event );
}
sdUIObject* prev = NULL;
sdUIObject* child = GetNode().GetChild();
while( child != NULL ) {
prev = child;
child = child->GetNode().GetSibling();
}
child = prev;
while( child != NULL ) {
if( child->HandleFocus( event ) ) {
return true;
}
child = child->GetNode().GetPriorSibling();
}
return false;
}
/*
============
sdUILayout_Static::MakeLayoutDirty
============
*/
void sdUILayout_Static::MakeLayoutDirty() {
recalculateLayout = true;
MakeLayoutDirty_r( this );
}
SD_UI_IMPLEMENT_CLASS( sdUILayout_Vertical, sdUILayout_StaticBase )
/*
============
sdUILayout_Vertical::sdUILayout_Vertical
============
*/
sdUILayout_Vertical::sdUILayout_Vertical() {
GetScope().GetProperties().RegisterProperty( "verticalSize", verticalSize );
verticalSize = 0.0f;
verticalSize.SetReadOnly( true );
}
/*
============
sdUILayout_Vertical::DoApplyLayout
============
*/
void sdUILayout_Vertical::DoApplyLayout() {
idVec2 offset( margins.GetValue().x, margins.GetValue().y );
for( int i = 0; i < childRects.Num(); i++ ) {
rectInfo_t& rectInfo = childRects[ i ];
idVec4 childRect = rectInfo.rect;
if( TestFlag( VLF_NOSIZE ) == false && rectInfo.source->TestFlag( OF_FIXED_LAYOUT ) == false ) {
childRect.z = rect.GetValue().z - ( margins.GetValue().x + margins.GetValue().z ) - childRect.x;
}
childRect.x = rectInfo.rect.x + offset.x;
childRect.y = rectInfo.rect.y + offset.y;
*rectInfo.property->value.vec4Value = childRect;
offset.y += rectInfo.rect.y + childRect.w + spacing.GetValue().y;
}
verticalSize.SetReadOnly( false );
verticalSize = offset.y;
verticalSize.SetReadOnly( true );
}
SD_UI_IMPLEMENT_CLASS( sdUILayout_Horizontal, sdUILayout_StaticBase )
/*
============
sdUILayout_Horizontal::DoApplyLayout
============
*/
void sdUILayout_Horizontal::DoApplyLayout() {
idVec2 offset( margins.GetValue().x, margins.GetValue().y );
for( int i = 0; i < childRects.Num(); i++ ) {
rectInfo_t& rectInfo = childRects[ i ];
idVec4 childRect = rectInfo.rect;
if( TestFlag( VLF_NOSIZE ) == false && rectInfo.source->TestFlag( OF_FIXED_LAYOUT ) == false ) {
childRect.w = rect.GetValue().w - ( margins.GetValue().y + margins.GetValue().w ) - childRect.y;
}
childRect.x += offset.x;
childRect.y += offset.y;
*rectInfo.property->value.vec4Value = childRect;
offset.x += rectInfo.rect.x + childRect.z + spacing.GetValue().x;
}
}