You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
321 lines
8.5 KiB
321 lines
8.5 KiB
//============ Copyright (c) Valve Corporation, All rights reserved. ============ |
|
// |
|
// Base class for panels used to edit nodes in layout system definitions. |
|
// |
|
//=============================================================================== |
|
|
|
#include "vgui_controls/Panel.h" |
|
#include "vgui_controls/Label.h" |
|
#include "vgui_controls/Button.h" |
|
#include "vgui_controls/TextEntry.h" |
|
#include "KeyValues.h" |
|
#include "layout_system_editor/layout_system_kv_editor.h" |
|
#include "layout_system_editor/rule_instance_node_panel.h" |
|
#include "layout_system_editor/state_node_panel.h" |
|
#include "node_panel.h" |
|
|
|
using namespace vgui; |
|
|
|
CNodePanel::CNodePanel( Panel *pParent, const char *pName ) : |
|
BaseClass( pParent, pName ), |
|
m_pNodeKV( NULL ), |
|
m_pEditor( NULL ), |
|
m_bShowNameEditBox( false ), |
|
m_bShowDeleteButton( false ) |
|
{ |
|
m_pLabel = new Label( this, "Label", "" ); |
|
m_pLabel->SetMouseInputEnabled( false ); |
|
m_pNameEditBox = new TextEntry( this, "TextEntry" ); |
|
m_NodeLabel[0] = '\0'; |
|
m_NodeName[0] = '\0'; |
|
|
|
m_pRootSizer = new CBoxSizer( ESLD_VERTICAL ); |
|
|
|
m_pLabelSizer = new CBoxSizer( ESLD_HORIZONTAL ); |
|
m_pLabelSizer->AddPanel( m_pLabel, SizerAddArgs_t().Padding( 2 ) ); |
|
m_pLabelSizer->AddPanel( m_pNameEditBox, SizerAddArgs_t().Padding( 2 ).MinSize( 200, 20 ) ); |
|
m_pRootSizer->AddSizer( m_pLabelSizer, SizerAddArgs_t().Padding( 5 ) ); |
|
|
|
m_pHeadingSizer = new CBoxSizer( ESLD_HORIZONTAL ); |
|
m_pLabelSizer->AddSizer( m_pHeadingSizer, SizerAddArgs_t().Padding( 0 ).Expand( 1.0f ) ); |
|
|
|
m_pDeleteSelfButton = new Button( this, "DeleteSelf", "X", this, "DeleteSelf" ); |
|
m_pLabelSizer->AddPanel( m_pDeleteSelfButton, SizerAddArgs_t().Padding( 2 ) ); |
|
|
|
m_pChildSizer = new CBoxSizer( ESLD_VERTICAL ); |
|
m_pChildIndentSizer = new CBoxSizer( ESLD_HORIZONTAL ); |
|
m_pChildIndentSizer->AddSpacer( SizerAddArgs_t().MinSize( 0, 0 ).Padding( 0 ) ); |
|
m_pChildIndentSizer->AddSizer( m_pChildSizer, SizerAddArgs_t().Padding( 0 ).Expand( 1.0f ) ); |
|
m_pRootSizer->AddSizer( m_pChildIndentSizer, SizerAddArgs_t().Padding( 0 ).Expand( 1.0f ) ); |
|
|
|
SetSizer( m_pRootSizer ); |
|
|
|
// We want a transparent background for the label. |
|
m_pLabel->SetPaintBackgroundEnabled( false ); |
|
} |
|
|
|
void CNodePanel::ApplySchemeSettings( vgui::IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
SetBorder( pScheme->GetBorder( "RaisedBorder" ) ); |
|
} |
|
|
|
void CNodePanel::OnCommand( const char *pCommand ) |
|
{ |
|
if ( Q_stricmp( pCommand, "DeleteSelf" ) == 0 ) |
|
{ |
|
DeleteSelf(); |
|
return; |
|
} |
|
|
|
BaseClass::OnCommand( pCommand ); |
|
} |
|
|
|
void CNodePanel::OnAddRule( KeyValues *pKV ) |
|
{ |
|
int nIndex = pKV->GetInt( "index", -1 ); |
|
Assert( nIndex != -1 ); |
|
InsertChildData( nIndex, new KeyValues( "rule_instance", NULL, "<null>" ) ); |
|
} |
|
|
|
void CNodePanel::OnAddState( KeyValues *pKV ) |
|
{ |
|
int nIndex = pKV->GetInt( "index", -1 ); |
|
Assert( nIndex != -1 ); |
|
InsertChildData( nIndex, new KeyValues( "state", "name", "MyNewState" ) ); |
|
} |
|
|
|
void CNodePanel::OnTextChanged( vgui::Panel *pPanel ) |
|
{ |
|
Assert( pPanel == m_pNameEditBox ); |
|
const int nMaxTextLength = 2048; |
|
char buf[nMaxTextLength]; |
|
m_pNameEditBox->GetText( buf, nMaxTextLength ); |
|
buf[nMaxTextLength - 1] = '\0'; |
|
SetNodeName( buf ); |
|
} |
|
|
|
void CNodePanel::SetData( KeyValues *pNodeKV ) |
|
{ |
|
if ( m_pNodeKV != NULL && m_pNodeKV != pNodeKV ) |
|
{ |
|
CNodePanel *pParentNodePanel = dynamic_cast< CNodePanel * >( GetParent() ); |
|
if ( pParentNodePanel != NULL ) |
|
{ |
|
Assert( pParentNodePanel->m_pNodeKV->ContainsSubKey( m_pNodeKV ) ); |
|
|
|
if ( pNodeKV != NULL ) |
|
{ |
|
// Must replace parent's sub key with ours |
|
pParentNodePanel->m_pNodeKV->SwapSubKey( m_pNodeKV, pNodeKV ); |
|
} |
|
else |
|
{ |
|
// Just remove the parent's sub key |
|
pParentNodePanel->m_pNodeKV->RemoveSubKey( m_pNodeKV ); |
|
} |
|
|
|
} |
|
m_pNodeKV->deleteThis(); |
|
} |
|
|
|
m_pNodeKV = pNodeKV; |
|
|
|
RecreateControls(); |
|
} |
|
|
|
void CNodePanel::RecreateControls() |
|
{ |
|
ClearHeading(); |
|
ClearChildren(); |
|
|
|
CreatePanelContents(); |
|
|
|
UpdateState(); |
|
} |
|
|
|
void CNodePanel::UpdateState() |
|
{ |
|
if ( m_NodeLabel[0] != '\0' ) |
|
{ |
|
m_pLabel->SetText( m_NodeLabel ); |
|
m_pLabel->SetVisible( true ); |
|
} |
|
else |
|
{ |
|
m_pLabel->SetText( "" ); |
|
m_pLabel->SetVisible( false ); |
|
} |
|
|
|
if ( m_bShowNameEditBox ) |
|
{ |
|
m_pNameEditBox->SetText( m_NodeName ); |
|
} |
|
m_pNameEditBox->SetVisible( m_bShowNameEditBox ); |
|
m_pDeleteSelfButton->SetVisible( m_bShowDeleteButton ); |
|
|
|
// Show or hide the "add" buttons on the CNewElementPanel objects |
|
for ( int i = 0; i < m_pChildSizer->GetElementCount(); ++ i ) |
|
{ |
|
if ( m_pChildSizer->GetElementType( i ) == ESET_PANEL ) |
|
{ |
|
CNewElementPanel *pNewElementPanel = dynamic_cast< CNewElementPanel * >( m_pChildSizer->GetPanel( i ) ); |
|
if ( pNewElementPanel != NULL ) |
|
{ |
|
pNewElementPanel->SetVisible( GetEditor()->ShouldShowAddButtons() ); |
|
} |
|
} |
|
} |
|
|
|
// Update state on all children |
|
for ( int i = 0; i < m_ChildPanels.Count(); ++ i ) |
|
{ |
|
m_ChildPanels[i]->UpdateState(); |
|
} |
|
} |
|
|
|
void CNodePanel::InvalidateEditorLayout() |
|
{ |
|
if ( m_pEditor != NULL ) |
|
{ |
|
m_pEditor->InvalidateLayout(); |
|
} |
|
} |
|
|
|
void CNodePanel::ClearHeading() |
|
{ |
|
m_pHeadingSizer->RemoveAllMembers( true ); |
|
InvalidateEditorLayout(); |
|
} |
|
|
|
void CNodePanel::AddHeadingElement( Panel *pPanel, float flExpandFactor, int nPadding ) |
|
{ |
|
m_pHeadingSizer->AddPanel( pPanel, SizerAddArgs_t().Padding( nPadding ).Expand( flExpandFactor ) ); |
|
InvalidateEditorLayout(); |
|
} |
|
|
|
void CNodePanel::AddHeadingSpacer() |
|
{ |
|
m_pHeadingSizer->AddSpacer( SizerAddArgs_t().Padding( 0 ).Expand( 1.0f ) ); |
|
InvalidateEditorLayout(); |
|
} |
|
|
|
void CNodePanel::SetChildIndent( int nIndent ) |
|
{ |
|
m_pChildIndentSizer->SetElementArgs( 0, SizerAddArgs_t().MinSize( nIndent, 0 ).Padding( 0 ) ); |
|
InvalidateEditorLayout(); |
|
} |
|
|
|
void CNodePanel::ClearChildren() |
|
{ |
|
m_ChildPanels.RemoveAll(); |
|
m_pChildSizer->RemoveAllMembers( true ); |
|
InvalidateEditorLayout(); |
|
} |
|
|
|
void CNodePanel::AddChild( CNodePanel *pPanel, int nPadding ) |
|
{ |
|
m_ChildPanels.AddToTail( pPanel ); |
|
AddChild( ( Panel * )pPanel, nPadding ); |
|
} |
|
|
|
void CNodePanel::AddChild( Panel *pPanel, int nPadding ) |
|
{ |
|
m_pChildSizer->AddPanel( pPanel, SizerAddArgs_t().Padding( nPadding ) ); |
|
InvalidateEditorLayout(); |
|
} |
|
|
|
void CNodePanel::InsertChildData( int nIndex, KeyValues *pKeyValues ) |
|
{ |
|
KeyValues *pNodeKV = GetData(); |
|
pNodeKV->InsertSubKey( nIndex, pKeyValues ); |
|
RecreateControls(); |
|
} |
|
|
|
// Register new panel types here. There probably won't be that many kinds, |
|
// so there's no reason to have a general purpose factory function. |
|
CNodePanel *CNodePanel::CreateChild( KeyValues *pKey ) |
|
{ |
|
CNodePanel *pNodePanel = NULL; |
|
const char *pPanelType = pKey->GetName(); |
|
|
|
if ( Q_stricmp( pPanelType, "state" ) == 0 ) |
|
{ |
|
pNodePanel = new CStateNodePanel( this, "state_panel" ); |
|
} |
|
else if ( Q_stricmp( pPanelType, "rule_instance" ) == 0 ) |
|
{ |
|
pNodePanel = new CRuleInstanceNodePanel( this, "rule_instance_panel" ); |
|
} |
|
|
|
if ( pNodePanel == NULL ) |
|
{ |
|
Log_Warning( LOG_TilegenLayoutSystem, "Unrecognized node type (cannot create panel): %s.\n", pPanelType ); |
|
return NULL; |
|
} |
|
|
|
pNodePanel->SetEditor( m_pEditor ); |
|
pNodePanel->SetData( pKey ); |
|
|
|
return pNodePanel; |
|
} |
|
|
|
void CNodePanel::DeleteSelf() |
|
{ |
|
CNodePanel *pParent = dynamic_cast< CNodePanel * >( GetParent() ); |
|
Assert( pParent != NULL ); |
|
|
|
KeyValues *pParentKV = pParent->GetData(); |
|
Assert( pParentKV->ContainsSubKey( m_pNodeKV ) ); |
|
pParentKV->RemoveSubKey( m_pNodeKV ); |
|
m_pNodeKV->deleteThis(); |
|
m_pNodeKV = NULL; |
|
|
|
// Refresh parent's panel contents. |
|
pParent->RecreateControls(); |
|
} |
|
|
|
void CNodePanel::AddNewElementPanel( int nIndex, bool bAllowRules, bool bAllowStates ) |
|
{ |
|
CNewElementPanel *pNewElementPanel = new CNewElementPanel( this, "NewElement", nIndex ); |
|
if ( bAllowRules ) |
|
{ |
|
pNewElementPanel->AddButton( "Add Rule", "AddRule" ); |
|
} |
|
if ( bAllowStates ) |
|
{ |
|
pNewElementPanel->AddButton( "Add State", "AddState" ); |
|
} |
|
AddChild( pNewElementPanel, 5 ); |
|
} |
|
|
|
void CNodePanel::SetNodeName( const char *pNodeName ) |
|
{ |
|
KeyValues *pNodeKV = GetData(); |
|
if ( pNodeKV != NULL ) |
|
{ |
|
pNodeKV->SetString( "name", pNodeName ); |
|
} |
|
} |
|
|
|
CNewElementPanel::CNewElementPanel( Panel *pParent, const char *pName, int nIndex ) : |
|
BaseClass( pParent, pName ), |
|
m_nIndex( nIndex ) |
|
{ |
|
m_pHorizontalSizer = new CBoxSizer( ESLD_HORIZONTAL ); |
|
SetSizer( m_pHorizontalSizer ); |
|
} |
|
|
|
void CNewElementPanel::AddButton( const char *pButtonText, const char *pActionName ) |
|
{ |
|
Button *pButton = new Button( this, pActionName, pButtonText, GetParent(), pActionName ); |
|
|
|
KeyValues *pMessageKV = new KeyValues( pActionName ); |
|
KeyValues *pIndexKV = new KeyValues( "index" ); |
|
pIndexKV->SetInt( NULL, m_nIndex ); |
|
pMessageKV->AddSubKey( pIndexKV ); |
|
pButton->SetCommand( pMessageKV ); |
|
|
|
m_pHorizontalSizer->AddPanel( pButton, SizerAddArgs_t().MinSize( 50, 20 ).Padding( 0 ) ); |
|
InvalidateLayout(); |
|
} |