|
|
//====== Copyright � 1996-2005, 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(); StoreInitialValue( true ); } } 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(); if ( !IsEnabled() ) return; // don't bother writing data if this attribute is read-only or being driven by a channel
WriteValueToAttribute(); StoreInitialValue(); }
void CAttributeTextEntry::OnMouseWheeled( int delta ) { // Must have *keyboard* focus for it to work, and alse be writeable and not driven by a channel
if ( !HasFocus() || !IsEnabled() ) { // 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();
}
// ----------------------------------------------------------------------------
|