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.
500 lines
12 KiB
500 lines
12 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
// |
|
//=============================================================================// |
|
|
|
#include "dme_controls/AttributeTextEntry.h" |
|
#include "tier1/KeyValues.h" |
|
#include "vgui_controls/Menu.h" |
|
#include "datamodel/dmelement.h" |
|
#include "dme_controls/AttributeTextPanel.h" |
|
#include "vgui/MouseCode.h" |
|
#include "vgui/KeyCode.h" |
|
#include "vgui/IInput.h" |
|
#include "movieobjects/dmeeditortypedictionary.h" |
|
#include "dme_controls/inotifyui.h" |
|
|
|
using namespace vgui; |
|
|
|
// ---------------------------------------------------------------------------- |
|
// CAttributeTextEntry |
|
|
|
CAttributeTextEntry::CAttributeTextEntry( Panel *parent, const char *panelName ) : |
|
BaseClass( parent, panelName ), |
|
m_bValueStored( false ), |
|
m_flOriginalValue( 0.0f ) |
|
{ |
|
SetDragEnabled( true ); |
|
SetDropEnabled( true, 0.5f ); |
|
m_szOriginalText[ 0 ] = 0; |
|
AddActionSignalTarget( this ); |
|
} |
|
|
|
void CAttributeTextEntry::ApplySchemeSettings( IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
SetBorder(NULL); |
|
|
|
//HFont font = pScheme->GetFont( "DmePropertyVerySmall", IsProportional() ); |
|
//SetFont(font); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Returns the parent panel |
|
//----------------------------------------------------------------------------- |
|
inline CAttributeTextPanel *CAttributeTextEntry::GetParentAttributePanel() |
|
{ |
|
return static_cast< CAttributeTextPanel * >( GetParent() ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Drag + drop |
|
//----------------------------------------------------------------------------- |
|
bool CAttributeTextEntry::GetDropContextMenu( Menu *menu, CUtlVector< KeyValues * >& msglist ) |
|
{ |
|
menu->AddMenuItem( "Drop as Text", "#BxDropText", "droptext", this ); |
|
return true; |
|
} |
|
|
|
bool CAttributeTextEntry::IsDroppable( CUtlVector< KeyValues * >& msglist ) |
|
{ |
|
if ( !IsEnabled() ) |
|
return false; |
|
|
|
if ( msglist.Count() != 1 ) |
|
return false; |
|
|
|
KeyValues *msg = msglist[ 0 ]; |
|
|
|
Panel *draggedPanel = ( Panel * )msg->GetPtr( "panel", NULL ); |
|
if ( draggedPanel == GetParent() ) |
|
return false; |
|
|
|
CAttributeTextPanel *pPanel = GetParentAttributePanel(); |
|
if ( !pPanel ) |
|
return false; |
|
|
|
// If a specific text type is specified, then filter if it doesn't match |
|
const char *pTextType = pPanel->GetTextType(); |
|
if ( pTextType[0] ) |
|
{ |
|
const char *pMsgTextType = msg->GetString( "texttype" ); |
|
if ( Q_stricmp( pTextType, pMsgTextType ) ) |
|
return false; |
|
} |
|
|
|
DmAttributeType_t t = pPanel->GetAttributeType(); |
|
switch ( t ) |
|
{ |
|
default: |
|
break; |
|
case AT_ELEMENT: |
|
{ |
|
CDmElement *ptr = reinterpret_cast< CDmElement * >( g_pDataModel->GetElement( DmElementHandle_t( msg->GetInt( "root" ) ) ) ); |
|
if ( ptr ) |
|
{ |
|
return true; |
|
} |
|
return false; |
|
} |
|
break; |
|
|
|
case AT_ELEMENT_ARRAY: |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
void CAttributeTextEntry::OnPanelDropped( CUtlVector< KeyValues * >& msglist ) |
|
{ |
|
if ( msglist.Count() != 1 ) |
|
return; |
|
|
|
KeyValues *data = msglist[ 0 ]; |
|
Panel *draggedPanel = ( Panel * )data->GetPtr( "panel", NULL ); |
|
if ( draggedPanel == GetParent() ) |
|
return; |
|
|
|
CAttributeTextPanel *pPanel = GetParentAttributePanel(); |
|
if ( !pPanel ) |
|
return; |
|
|
|
// If a specific text type is specified, then filter if it doesn't match |
|
const char *pTextType = pPanel->GetTextType(); |
|
if ( pTextType[0] ) |
|
{ |
|
const char *pMsgTextType = data->GetString( "texttype" ); |
|
if ( Q_stricmp( pTextType, pMsgTextType ) ) |
|
return; |
|
} |
|
|
|
const char *cmd = data->GetString( "command" ); |
|
if ( !Q_stricmp( cmd, "droptext" ) || !Q_stricmp( cmd, "default" ) ) |
|
{ |
|
DmAttributeType_t t = pPanel->GetAttributeType(); |
|
switch ( t ) |
|
{ |
|
default: |
|
{ |
|
pPanel->SetDirty( true ); |
|
SetText( data->GetString( "text" ) ); |
|
if ( pPanel->IsAutoApply() ) |
|
{ |
|
pPanel->Apply(); |
|
} |
|
} |
|
break; |
|
|
|
case AT_ELEMENT: |
|
{ |
|
CDmElement *ptr = reinterpret_cast< CDmElement * >( g_pDataModel->GetElement( DmElementHandle_t( data->GetInt( "root" ) ) ) ); |
|
if ( !ptr ) |
|
{ |
|
break; |
|
} |
|
pPanel->SetDirty( true ); |
|
SetText( data->GetString( "text" ) ); |
|
if ( pPanel->IsAutoApply() ) |
|
{ |
|
pPanel->Apply(); |
|
} |
|
} |
|
break; |
|
case AT_ELEMENT_ARRAY: |
|
Assert( 0 ); |
|
break; |
|
} |
|
} |
|
|
|
StoreInitialValue( true ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Enter causes changes to be applied |
|
//----------------------------------------------------------------------------- |
|
void CAttributeTextEntry::OnKeyCodeTyped(KeyCode code) |
|
{ |
|
bool bCtrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL)); |
|
|
|
switch ( code ) |
|
{ |
|
case KEY_ENTER: |
|
{ |
|
CAttributeTextPanel *pPanel = GetParentAttributePanel(); |
|
if ( !pPanel->IsAutoApply() ) |
|
{ |
|
pPanel->Apply(); |
|
StoreInitialValue( true ); |
|
} |
|
else |
|
{ |
|
WriteValueToAttribute(); |
|
} |
|
} |
|
break; |
|
|
|
// Override the base class undo feature, it behaves poorly when typing in data |
|
case KEY_Z: |
|
if ( bCtrl ) |
|
{ |
|
WriteInitialValueToAttribute( ); |
|
break; |
|
} |
|
|
|
// NOTE: Fall through to default if it's not Ctrl-Z |
|
|
|
default: |
|
BaseClass::OnKeyCodeTyped(code); |
|
break; |
|
} |
|
} |
|
|
|
|
|
void CAttributeTextEntry::OnTextChanged( KeyValues *data ) |
|
{ |
|
m_bValueStored = true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// We'll only create an "undo" record if the values differ upon focus change |
|
//----------------------------------------------------------------------------- |
|
void CAttributeTextEntry::StoreInitialValue( bool bForce ) |
|
{ |
|
// Already storing value??? |
|
if ( m_bValueStored && !bForce ) |
|
return; |
|
|
|
m_bValueStored = true; |
|
|
|
CAttributeTextPanel *pPanel = GetParentAttributePanel(); |
|
Assert( pPanel ); |
|
|
|
switch ( pPanel->GetAttributeType() ) |
|
{ |
|
case AT_FLOAT: |
|
m_flOriginalValue = pPanel->GetAttributeValue<float>( ); |
|
break; |
|
case AT_INT: |
|
m_nOriginalValue = pPanel->GetAttributeValue<int>( ); |
|
break; |
|
case AT_BOOL: |
|
m_bOriginalValue = pPanel->GetAttributeValue<bool>( ); |
|
break; |
|
default: |
|
GetText( m_szOriginalText, sizeof( m_szOriginalText ) ); |
|
break; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Performs undo |
|
//----------------------------------------------------------------------------- |
|
void CAttributeTextEntry::WriteInitialValueToAttribute( ) |
|
{ |
|
// Already storing value??? |
|
if ( !m_bValueStored ) |
|
return; |
|
|
|
CDisableUndoScopeGuard guard; |
|
|
|
CAttributeTextPanel *pPanel = GetParentAttributePanel(); |
|
Assert( pPanel ); |
|
|
|
switch ( pPanel->GetAttributeType() ) |
|
{ |
|
case AT_FLOAT: |
|
pPanel->SetAttributeValue( m_flOriginalValue ); |
|
break; |
|
case AT_INT: |
|
pPanel->SetAttributeValue( m_nOriginalValue ); |
|
break; |
|
case AT_BOOL: |
|
pPanel->SetAttributeValue<bool>( m_bOriginalValue ); |
|
break; |
|
default: |
|
pPanel->SetAttributeValueFromString( m_szOriginalText ); |
|
break; |
|
} |
|
|
|
pPanel->SetDirty( false ); |
|
pPanel->Refresh(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// We'll only create an "undo" record if the values differ upon focus change |
|
//----------------------------------------------------------------------------- |
|
void CAttributeTextEntry::OnSetFocus() |
|
{ |
|
BaseClass::OnSetFocus(); |
|
StoreInitialValue(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Called when focus is lost |
|
//----------------------------------------------------------------------------- |
|
template<class T> |
|
void CAttributeTextEntry::ApplyMouseWheel( T newValue, T originalValue ) |
|
{ |
|
CAttributeTextPanel *pPanel = GetParentAttributePanel(); |
|
|
|
// Kind of an evil hack, but "undo" copies the "old value" off for doing undo, and that value is the new value because |
|
// we haven't been tracking undo while manipulating this. So we'll turn off undo and set the value to the original value. |
|
|
|
// In effect, all of the wheeling will drop out and it'll look just like we started at the original value and ended up at the |
|
// final value... |
|
{ |
|
CDisableUndoScopeGuard guard; |
|
pPanel->SetAttributeValue( originalValue ); |
|
} |
|
|
|
if ( pPanel->IsAutoApply() ) |
|
{ |
|
pPanel->Apply(); |
|
} |
|
else |
|
{ |
|
CElementTreeUndoScopeGuard guard( 0, pPanel->GetNotify(), "Set Attribute Value", "Set Attribute Value" ); |
|
pPanel->SetAttributeValue( newValue ); |
|
} |
|
} |
|
|
|
|
|
void CAttributeTextEntry::WriteValueToAttribute() |
|
{ |
|
if ( !m_bValueStored ) |
|
return; |
|
|
|
m_bValueStored = false; |
|
|
|
char newText[ MAX_TEXT_LENGTH ]; |
|
GetText( newText, sizeof( newText ) ); |
|
|
|
CAttributeTextPanel *pPanel = GetParentAttributePanel(); |
|
Assert( pPanel ); |
|
switch (pPanel->GetAttributeType() ) |
|
{ |
|
case AT_FLOAT: |
|
ApplyMouseWheel( (float)atof(newText), m_flOriginalValue ); |
|
break; |
|
case AT_INT: |
|
ApplyMouseWheel( atoi(newText), m_nOriginalValue ); |
|
break; |
|
case AT_BOOL: |
|
ApplyMouseWheel( atoi(newText) != 0, m_bOriginalValue ); |
|
break; |
|
default: |
|
if ( Q_strcmp( newText, m_szOriginalText ) ) |
|
{ |
|
pPanel->SetDirty( true ); |
|
if ( pPanel->IsAutoApply() ) |
|
{ |
|
pPanel->Apply(); |
|
StoreInitialValue( true ); |
|
} |
|
} |
|
else |
|
{ |
|
pPanel->SetDirty( false ); |
|
} |
|
break; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Called when focus is lost |
|
//----------------------------------------------------------------------------- |
|
void CAttributeTextEntry::OnKillFocus() |
|
{ |
|
BaseClass::OnKillFocus(); |
|
WriteValueToAttribute(); |
|
StoreInitialValue(); |
|
} |
|
|
|
void CAttributeTextEntry::OnMouseWheeled( int delta ) |
|
{ |
|
// Must have *keyboard* focus for it to work |
|
if ( !HasFocus() ) |
|
{ |
|
// Otherwise, let the base class scroll up + down |
|
BaseClass::OnMouseWheeled( delta ); |
|
return; |
|
} |
|
|
|
CAttributeTextPanel *pPanel = GetParentAttributePanel(); |
|
if ( pPanel->GetDirty() ) |
|
{ |
|
if ( pPanel->IsAutoApply() ) |
|
{ |
|
pPanel->Apply(); |
|
StoreInitialValue( true ); |
|
} |
|
else |
|
{ |
|
// FIXME: Make this work for non-auto-apply panels |
|
} |
|
} |
|
|
|
switch ( pPanel->GetAttributeType() ) |
|
{ |
|
case AT_FLOAT: |
|
{ |
|
float deltaFactor; |
|
if ( input()->IsKeyDown(KEY_LSHIFT) ) |
|
{ |
|
deltaFactor = ((float)delta) * 10.0f; |
|
} |
|
else if ( input()->IsKeyDown(KEY_LCONTROL) ) |
|
{ |
|
deltaFactor = ((float)delta) / 100.0; |
|
} |
|
else |
|
{ |
|
deltaFactor = ((float)delta) / 10.0; |
|
} |
|
|
|
float val = pPanel->GetAttributeValue<float>() + deltaFactor; |
|
|
|
if ( input()->IsKeyDown(KEY_LALT) ) |
|
{ |
|
//val = clamp(val, 0.0, 1.0); |
|
val = (val > 1) ? 1 : ((val < 0) ? 0 : val); |
|
} |
|
|
|
{ |
|
// Note, these calls to Set won't create Undo Records, |
|
// since we'll check the value in SetFocus/KillFocus so that we |
|
// don't gum up the undo system with hundreds of records... |
|
CDisableUndoScopeGuard guard; |
|
pPanel->SetAttributeValue( val ); |
|
} |
|
} |
|
break; |
|
|
|
case AT_INT: |
|
{ |
|
if ( input()->IsKeyDown(KEY_LSHIFT) ) |
|
{ |
|
delta *= 10; |
|
} |
|
|
|
int val = pPanel->GetAttributeValue<int>() + delta; |
|
|
|
{ |
|
// Note, these calls to Set won't create Undo Records, |
|
// since we'll check the value in SetFocus/KillFocus so that we |
|
// don't gum up the undo system with hundreds of records... |
|
CDisableUndoScopeGuard guard; |
|
pPanel->SetAttributeValue( val ); |
|
} |
|
} |
|
break; |
|
|
|
case AT_BOOL: |
|
{ |
|
bool val = !pPanel->GetAttributeValue<bool>(); |
|
|
|
{ |
|
// Note, these calls to Set won't create Undo Records, |
|
// since we'll check the value in SetFocus/KillFocus so that we |
|
// don't gum up the undo system with hundreds of records... |
|
CDisableUndoScopeGuard guard; |
|
pPanel->SetAttributeValue( val ); |
|
} |
|
} |
|
break; |
|
|
|
default: |
|
return; |
|
} |
|
|
|
pPanel->Refresh(); |
|
if ( pPanel->IsAutoApply() ) |
|
{ |
|
// NOTE: Don't call Apply since that generates an undo record |
|
CElementTreeNotifyScopeGuard notify( "CAttributeTextEntry::OnMouseWheeled", NOTIFY_CHANGE_ATTRIBUTE_VALUE | NOTIFY_SETDIRTYFLAG, pPanel->GetNotify() ); |
|
} |
|
else |
|
{ |
|
pPanel->SetDirty( true ); |
|
} |
|
|
|
//SetDirty(true); |
|
//UpdateTime( m_flLastMouseTime ); |
|
//UpdateZoom( -10.0f * delta ); |
|
//UpdateTransform(); |
|
} |
|
|
|
// ----------------------------------------------------------------------------
|
|
|