source-engine/hammer/targetnamecombo.cpp

200 lines
5.3 KiB
C++
Raw Permalink Normal View History

2020-04-23 00:56:21 +08:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implements an autoselection combo box that color codes the text
// based on whether the current selection represents a single entity,
// multiple entities, or an unresolved entity targetname.
//
// The fonts are as follows:
//
// Single entity black, normal weight
// Multiple entities black, bold
// Unresolved red, normal weight
//
//=============================================================================//
#include "stdafx.h"
#include "MapEntity.h"
#include "TargetNameCombo.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
#pragma warning( disable : 4355 )
BEGIN_MESSAGE_MAP(CTargetNameComboBox, CFilteredComboBox)
//{{AFX_MSG_MAP(CTargetNameComboBox)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTargetNameComboBox::CTargetNameComboBox( CFilteredComboBox::ICallbacks *pPassThru ) :
BaseClass( this )
{
m_pEntityList = NULL;
m_pPassThru = pPassThru;
}
//-----------------------------------------------------------------------------
// Purpose: Frees allocated memory.
//-----------------------------------------------------------------------------
CTargetNameComboBox::~CTargetNameComboBox(void)
{
FreeSubLists();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTargetNameComboBox::FreeSubLists(void)
{
POSITION pos = m_SubLists.GetHeadPosition();
while (pos != NULL)
{
CMapEntityList *pList = m_SubLists.GetNext(pos);
delete pList;
}
m_SubLists.RemoveAll();
}
void CTargetNameComboBox::CreateFonts()
{
//
// Create a normal and bold font.
//
if (!m_BoldFont.m_hObject)
{
CFont &nf = GetNormalFont();
if ( nf.m_hObject )
{
LOGFONT LogFont;
nf.GetLogFont(&LogFont);
LogFont.lfWeight = FW_BOLD;
m_BoldFont.CreateFontIndirect(&LogFont);
}
}
}
CTargetNameComboBox* CTargetNameComboBox::Create( CFilteredComboBox::ICallbacks *pCallbacks, DWORD dwStyle, RECT rect, CWnd *pParentWnd, UINT nID )
{
CTargetNameComboBox *pRet = new CTargetNameComboBox( pCallbacks );
pRet->BaseClass::Create( dwStyle, rect, pParentWnd, nID );
return pRet;
}
//-----------------------------------------------------------------------------
// Purpose: Attaches an entity list to the combo box. This list will be used
// for matching targetnames to entities in the world.
// Input : pEntityList - The beauty of Hungarian notation and meaningful naming
// makes this comment utterly unnecessary.
//-----------------------------------------------------------------------------
void CTargetNameComboBox::SetEntityList(const CMapEntityList *pEntityList)
{
// We want all notifications, even if the current text doesn't match an exact entity name.
SetOnlyProvideSuggestions( false );
// Setup the list.
m_pEntityList = pEntityList;
FreeSubLists();
m_EntityLists.RemoveAll();
if (m_pEntityList != NULL)
{
FOR_EACH_OBJ( *m_pEntityList, pos )
{
CMapEntity *pEntity = m_pEntityList->Element(pos);
const char *pszTargetName = pEntity->GetKeyValue("targetname");
if (pszTargetName != NULL)
{
//
// If the targetname is not in the combo box, add it to the combo as the
// first entry in an entity list. The list is necessary because there
// may be several entities in the map with the same targetname.
//
int nIndex = m_EntityLists.Find( pszTargetName );
if (nIndex == m_EntityLists.InvalidIndex())
{
CMapEntityList *pList = new CMapEntityList;
pList->AddToTail(pEntity);
m_EntityLists.Insert( pszTargetName, pList );
//
// Keep track of all the sub lists so we can delete them later.
//
m_SubLists.AddTail(pList);
}
//
// Else append the entity to the given targetname's list.
//
else
{
CMapEntityList *pList = m_EntityLists[nIndex];
pList->AddToTail(pEntity);
}
}
}
}
// Setup the suggestions.
CUtlVector<CString> suggestions;
for ( int i=m_EntityLists.First(); i != m_EntityLists.InvalidIndex(); i=m_EntityLists.Next( i ) )
{
suggestions.AddToTail( m_EntityLists.GetElementName( i ) );
}
SetSuggestions( suggestions );
}
CMapEntityList* CTargetNameComboBox::GetSubEntityList( const char *pName )
{
int testIndex = m_EntityLists.Find( pName );
if ( testIndex != m_EntityLists.InvalidIndex() )
{
return m_EntityLists[testIndex];
}
return NULL;
}
void CTargetNameComboBox::OnTextChanged( const char *pText )
{
// Make sure our fonts are created.
CreateFonts();
// Update the fonts.
int nCount = 0;
CMapEntityList *pList = GetSubEntityList( pText );
if ( pList )
nCount = pList->Count();
// Figure out the font and color that we want.
CFont *pWantedFont = &m_BoldFont;
if ( (nCount == 0) || (nCount == 1) )
pWantedFont = &GetNormalFont();
COLORREF clrWanted = RGB(255,0,0);
if ( nCount > 0 )
clrWanted = RGB(0,0,0);
SetEditControlFont( *pWantedFont );
SetEditControlTextColor( clrWanted );
// Pass it through to the owner if they want notification.
if ( m_pPassThru )
m_pPassThru->OnTextChanged( pText );
}