Team Fortress 2 Source Code as on 22/4/2020
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

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "dme_controls/AttributeTextEntry.h"
  9. #include "tier1/KeyValues.h"
  10. #include "vgui_controls/Menu.h"
  11. #include "datamodel/dmelement.h"
  12. #include "dme_controls/AttributeTextPanel.h"
  13. #include "vgui/MouseCode.h"
  14. #include "vgui/KeyCode.h"
  15. #include "vgui/IInput.h"
  16. #include "movieobjects/dmeeditortypedictionary.h"
  17. #include "dme_controls/inotifyui.h"
  18. using namespace vgui;
  19. // ----------------------------------------------------------------------------
  20. // CAttributeTextEntry
  21. CAttributeTextEntry::CAttributeTextEntry( Panel *parent, const char *panelName ) :
  22. BaseClass( parent, panelName ),
  23. m_bValueStored( false ),
  24. m_flOriginalValue( 0.0f )
  25. {
  26. SetDragEnabled( true );
  27. SetDropEnabled( true, 0.5f );
  28. m_szOriginalText[ 0 ] = 0;
  29. AddActionSignalTarget( this );
  30. }
  31. void CAttributeTextEntry::ApplySchemeSettings( IScheme *pScheme )
  32. {
  33. BaseClass::ApplySchemeSettings( pScheme );
  34. SetBorder(NULL);
  35. //HFont font = pScheme->GetFont( "DmePropertyVerySmall", IsProportional() );
  36. //SetFont(font);
  37. }
  38. //-----------------------------------------------------------------------------
  39. // Returns the parent panel
  40. //-----------------------------------------------------------------------------
  41. inline CAttributeTextPanel *CAttributeTextEntry::GetParentAttributePanel()
  42. {
  43. return static_cast< CAttributeTextPanel * >( GetParent() );
  44. }
  45. //-----------------------------------------------------------------------------
  46. // Drag + drop
  47. //-----------------------------------------------------------------------------
  48. bool CAttributeTextEntry::GetDropContextMenu( Menu *menu, CUtlVector< KeyValues * >& msglist )
  49. {
  50. menu->AddMenuItem( "Drop as Text", "#BxDropText", "droptext", this );
  51. return true;
  52. }
  53. bool CAttributeTextEntry::IsDroppable( CUtlVector< KeyValues * >& msglist )
  54. {
  55. if ( !IsEnabled() )
  56. return false;
  57. if ( msglist.Count() != 1 )
  58. return false;
  59. KeyValues *msg = msglist[ 0 ];
  60. Panel *draggedPanel = ( Panel * )msg->GetPtr( "panel", NULL );
  61. if ( draggedPanel == GetParent() )
  62. return false;
  63. CAttributeTextPanel *pPanel = GetParentAttributePanel();
  64. if ( !pPanel )
  65. return false;
  66. // If a specific text type is specified, then filter if it doesn't match
  67. const char *pTextType = pPanel->GetTextType();
  68. if ( pTextType[0] )
  69. {
  70. const char *pMsgTextType = msg->GetString( "texttype" );
  71. if ( Q_stricmp( pTextType, pMsgTextType ) )
  72. return false;
  73. }
  74. DmAttributeType_t t = pPanel->GetAttributeType();
  75. switch ( t )
  76. {
  77. default:
  78. break;
  79. case AT_ELEMENT:
  80. {
  81. CDmElement *ptr = reinterpret_cast< CDmElement * >( g_pDataModel->GetElement( DmElementHandle_t( msg->GetInt( "root" ) ) ) );
  82. if ( ptr )
  83. {
  84. return true;
  85. }
  86. return false;
  87. }
  88. break;
  89. case AT_ELEMENT_ARRAY:
  90. return false;
  91. }
  92. return true;
  93. }
  94. void CAttributeTextEntry::OnPanelDropped( CUtlVector< KeyValues * >& msglist )
  95. {
  96. if ( msglist.Count() != 1 )
  97. return;
  98. KeyValues *data = msglist[ 0 ];
  99. Panel *draggedPanel = ( Panel * )data->GetPtr( "panel", NULL );
  100. if ( draggedPanel == GetParent() )
  101. return;
  102. CAttributeTextPanel *pPanel = GetParentAttributePanel();
  103. if ( !pPanel )
  104. return;
  105. // If a specific text type is specified, then filter if it doesn't match
  106. const char *pTextType = pPanel->GetTextType();
  107. if ( pTextType[0] )
  108. {
  109. const char *pMsgTextType = data->GetString( "texttype" );
  110. if ( Q_stricmp( pTextType, pMsgTextType ) )
  111. return;
  112. }
  113. const char *cmd = data->GetString( "command" );
  114. if ( !Q_stricmp( cmd, "droptext" ) || !Q_stricmp( cmd, "default" ) )
  115. {
  116. DmAttributeType_t t = pPanel->GetAttributeType();
  117. switch ( t )
  118. {
  119. default:
  120. {
  121. pPanel->SetDirty( true );
  122. SetText( data->GetString( "text" ) );
  123. if ( pPanel->IsAutoApply() )
  124. {
  125. pPanel->Apply();
  126. }
  127. }
  128. break;
  129. case AT_ELEMENT:
  130. {
  131. CDmElement *ptr = reinterpret_cast< CDmElement * >( g_pDataModel->GetElement( DmElementHandle_t( data->GetInt( "root" ) ) ) );
  132. if ( !ptr )
  133. {
  134. break;
  135. }
  136. pPanel->SetDirty( true );
  137. SetText( data->GetString( "text" ) );
  138. if ( pPanel->IsAutoApply() )
  139. {
  140. pPanel->Apply();
  141. }
  142. }
  143. break;
  144. case AT_ELEMENT_ARRAY:
  145. Assert( 0 );
  146. break;
  147. }
  148. }
  149. StoreInitialValue( true );
  150. }
  151. //-----------------------------------------------------------------------------
  152. // Enter causes changes to be applied
  153. //-----------------------------------------------------------------------------
  154. void CAttributeTextEntry::OnKeyCodeTyped(KeyCode code)
  155. {
  156. bool bCtrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL));
  157. switch ( code )
  158. {
  159. case KEY_ENTER:
  160. {
  161. CAttributeTextPanel *pPanel = GetParentAttributePanel();
  162. if ( !pPanel->IsAutoApply() )
  163. {
  164. pPanel->Apply();
  165. StoreInitialValue( true );
  166. }
  167. else
  168. {
  169. WriteValueToAttribute();
  170. }
  171. }
  172. break;
  173. // Override the base class undo feature, it behaves poorly when typing in data
  174. case KEY_Z:
  175. if ( bCtrl )
  176. {
  177. WriteInitialValueToAttribute( );
  178. break;
  179. }
  180. // NOTE: Fall through to default if it's not Ctrl-Z
  181. default:
  182. BaseClass::OnKeyCodeTyped(code);
  183. break;
  184. }
  185. }
  186. void CAttributeTextEntry::OnTextChanged( KeyValues *data )
  187. {
  188. m_bValueStored = true;
  189. }
  190. //-----------------------------------------------------------------------------
  191. // We'll only create an "undo" record if the values differ upon focus change
  192. //-----------------------------------------------------------------------------
  193. void CAttributeTextEntry::StoreInitialValue( bool bForce )
  194. {
  195. // Already storing value???
  196. if ( m_bValueStored && !bForce )
  197. return;
  198. m_bValueStored = true;
  199. CAttributeTextPanel *pPanel = GetParentAttributePanel();
  200. Assert( pPanel );
  201. switch ( pPanel->GetAttributeType() )
  202. {
  203. case AT_FLOAT:
  204. m_flOriginalValue = pPanel->GetAttributeValue<float>( );
  205. break;
  206. case AT_INT:
  207. m_nOriginalValue = pPanel->GetAttributeValue<int>( );
  208. break;
  209. case AT_BOOL:
  210. m_bOriginalValue = pPanel->GetAttributeValue<bool>( );
  211. break;
  212. default:
  213. GetText( m_szOriginalText, sizeof( m_szOriginalText ) );
  214. break;
  215. }
  216. }
  217. //-----------------------------------------------------------------------------
  218. // Performs undo
  219. //-----------------------------------------------------------------------------
  220. void CAttributeTextEntry::WriteInitialValueToAttribute( )
  221. {
  222. // Already storing value???
  223. if ( !m_bValueStored )
  224. return;
  225. CDisableUndoScopeGuard guard;
  226. CAttributeTextPanel *pPanel = GetParentAttributePanel();
  227. Assert( pPanel );
  228. switch ( pPanel->GetAttributeType() )
  229. {
  230. case AT_FLOAT:
  231. pPanel->SetAttributeValue( m_flOriginalValue );
  232. break;
  233. case AT_INT:
  234. pPanel->SetAttributeValue( m_nOriginalValue );
  235. break;
  236. case AT_BOOL:
  237. pPanel->SetAttributeValue<bool>( m_bOriginalValue );
  238. break;
  239. default:
  240. pPanel->SetAttributeValueFromString( m_szOriginalText );
  241. break;
  242. }
  243. pPanel->SetDirty( false );
  244. pPanel->Refresh();
  245. }
  246. //-----------------------------------------------------------------------------
  247. // We'll only create an "undo" record if the values differ upon focus change
  248. //-----------------------------------------------------------------------------
  249. void CAttributeTextEntry::OnSetFocus()
  250. {
  251. BaseClass::OnSetFocus();
  252. StoreInitialValue();
  253. }
  254. //-----------------------------------------------------------------------------
  255. // Called when focus is lost
  256. //-----------------------------------------------------------------------------
  257. template<class T>
  258. void CAttributeTextEntry::ApplyMouseWheel( T newValue, T originalValue )
  259. {
  260. CAttributeTextPanel *pPanel = GetParentAttributePanel();
  261. // Kind of an evil hack, but "undo" copies the "old value" off for doing undo, and that value is the new value because
  262. // we haven't been tracking undo while manipulating this. So we'll turn off undo and set the value to the original value.
  263. // 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
  264. // final value...
  265. {
  266. CDisableUndoScopeGuard guard;
  267. pPanel->SetAttributeValue( originalValue );
  268. }
  269. if ( pPanel->IsAutoApply() )
  270. {
  271. pPanel->Apply();
  272. }
  273. else
  274. {
  275. CElementTreeUndoScopeGuard guard( 0, pPanel->GetNotify(), "Set Attribute Value", "Set Attribute Value" );
  276. pPanel->SetAttributeValue( newValue );
  277. }
  278. }
  279. void CAttributeTextEntry::WriteValueToAttribute()
  280. {
  281. if ( !m_bValueStored )
  282. return;
  283. m_bValueStored = false;
  284. char newText[ MAX_TEXT_LENGTH ];
  285. GetText( newText, sizeof( newText ) );
  286. CAttributeTextPanel *pPanel = GetParentAttributePanel();
  287. Assert( pPanel );
  288. switch (pPanel->GetAttributeType() )
  289. {
  290. case AT_FLOAT:
  291. ApplyMouseWheel( (float)atof(newText), m_flOriginalValue );
  292. break;
  293. case AT_INT:
  294. ApplyMouseWheel( atoi(newText), m_nOriginalValue );
  295. break;
  296. case AT_BOOL:
  297. ApplyMouseWheel( atoi(newText) != 0, m_bOriginalValue );
  298. break;
  299. default:
  300. if ( Q_strcmp( newText, m_szOriginalText ) )
  301. {
  302. pPanel->SetDirty( true );
  303. if ( pPanel->IsAutoApply() )
  304. {
  305. pPanel->Apply();
  306. StoreInitialValue( true );
  307. }
  308. }
  309. else
  310. {
  311. pPanel->SetDirty( false );
  312. }
  313. break;
  314. }
  315. }
  316. //-----------------------------------------------------------------------------
  317. // Called when focus is lost
  318. //-----------------------------------------------------------------------------
  319. void CAttributeTextEntry::OnKillFocus()
  320. {
  321. BaseClass::OnKillFocus();
  322. WriteValueToAttribute();
  323. StoreInitialValue();
  324. }
  325. void CAttributeTextEntry::OnMouseWheeled( int delta )
  326. {
  327. // Must have *keyboard* focus for it to work
  328. if ( !HasFocus() )
  329. {
  330. // Otherwise, let the base class scroll up + down
  331. BaseClass::OnMouseWheeled( delta );
  332. return;
  333. }
  334. CAttributeTextPanel *pPanel = GetParentAttributePanel();
  335. if ( pPanel->GetDirty() )
  336. {
  337. if ( pPanel->IsAutoApply() )
  338. {
  339. pPanel->Apply();
  340. StoreInitialValue( true );
  341. }
  342. else
  343. {
  344. // FIXME: Make this work for non-auto-apply panels
  345. }
  346. }
  347. switch ( pPanel->GetAttributeType() )
  348. {
  349. case AT_FLOAT:
  350. {
  351. float deltaFactor;
  352. if ( input()->IsKeyDown(KEY_LSHIFT) )
  353. {
  354. deltaFactor = ((float)delta) * 10.0f;
  355. }
  356. else if ( input()->IsKeyDown(KEY_LCONTROL) )
  357. {
  358. deltaFactor = ((float)delta) / 100.0;
  359. }
  360. else
  361. {
  362. deltaFactor = ((float)delta) / 10.0;
  363. }
  364. float val = pPanel->GetAttributeValue<float>() + deltaFactor;
  365. if ( input()->IsKeyDown(KEY_LALT) )
  366. {
  367. //val = clamp(val, 0.0, 1.0);
  368. val = (val > 1) ? 1 : ((val < 0) ? 0 : val);
  369. }
  370. {
  371. // Note, these calls to Set won't create Undo Records,
  372. // since we'll check the value in SetFocus/KillFocus so that we
  373. // don't gum up the undo system with hundreds of records...
  374. CDisableUndoScopeGuard guard;
  375. pPanel->SetAttributeValue( val );
  376. }
  377. }
  378. break;
  379. case AT_INT:
  380. {
  381. if ( input()->IsKeyDown(KEY_LSHIFT) )
  382. {
  383. delta *= 10;
  384. }
  385. int val = pPanel->GetAttributeValue<int>() + delta;
  386. {
  387. // Note, these calls to Set won't create Undo Records,
  388. // since we'll check the value in SetFocus/KillFocus so that we
  389. // don't gum up the undo system with hundreds of records...
  390. CDisableUndoScopeGuard guard;
  391. pPanel->SetAttributeValue( val );
  392. }
  393. }
  394. break;
  395. case AT_BOOL:
  396. {
  397. bool val = !pPanel->GetAttributeValue<bool>();
  398. {
  399. // Note, these calls to Set won't create Undo Records,
  400. // since we'll check the value in SetFocus/KillFocus so that we
  401. // don't gum up the undo system with hundreds of records...
  402. CDisableUndoScopeGuard guard;
  403. pPanel->SetAttributeValue( val );
  404. }
  405. }
  406. break;
  407. default:
  408. return;
  409. }
  410. pPanel->Refresh();
  411. if ( pPanel->IsAutoApply() )
  412. {
  413. // NOTE: Don't call Apply since that generates an undo record
  414. CElementTreeNotifyScopeGuard notify( "CAttributeTextEntry::OnMouseWheeled", NOTIFY_CHANGE_ATTRIBUTE_VALUE | NOTIFY_SETDIRTYFLAG, pPanel->GetNotify() );
  415. }
  416. else
  417. {
  418. pPanel->SetDirty( true );
  419. }
  420. //SetDirty(true);
  421. //UpdateTime( m_flLastMouseTime );
  422. //UpdateZoom( -10.0f * delta );
  423. //UpdateTransform();
  424. }
  425. // ----------------------------------------------------------------------------