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.

318 lines
9.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "filesystem.h"
  7. #include "matsys_controls/picker.h"
  8. #include "tier1/KeyValues.h"
  9. #include "vgui_controls/ListPanel.h"
  10. #include "vgui_controls/TextEntry.h"
  11. #include "vgui_controls/Button.h"
  12. #include "vgui/ISurface.h"
  13. #include "vgui/IInput.h"
  14. using namespace vgui;
  15. //-----------------------------------------------------------------------------
  16. //
  17. // Base asset Picker
  18. //
  19. //-----------------------------------------------------------------------------
  20. //-----------------------------------------------------------------------------
  21. // Sort by asset name
  22. //-----------------------------------------------------------------------------
  23. static int __cdecl PickerBrowserSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
  24. {
  25. const char *string1 = item1.kv->GetString("choice");
  26. const char *string2 = item2.kv->GetString("choice");
  27. return stricmp( string1, string2 );
  28. }
  29. //-----------------------------------------------------------------------------
  30. // Purpose: Constructor
  31. //-----------------------------------------------------------------------------
  32. CPicker::CPicker( vgui::Panel *pParent, const char *pColumnHeader, const char *pTextType ) :
  33. BaseClass( pParent, "Picker" )
  34. {
  35. m_pPickerType = pColumnHeader;
  36. m_pPickerTextType = pTextType;
  37. // FIXME: Make this an image browser
  38. m_pPickerBrowser = new vgui::ListPanel( this, "Browser" );
  39. m_pPickerBrowser->AddColumnHeader( 0, "choice", m_pPickerType, 52, 0 );
  40. m_pPickerBrowser->SetSelectIndividualCells( true );
  41. m_pPickerBrowser->SetEmptyListText( "Nothing to pick" );
  42. m_pPickerBrowser->SetDragEnabled( true );
  43. m_pPickerBrowser->AddActionSignalTarget( this );
  44. m_pPickerBrowser->SetSortFunc( 0, PickerBrowserSortFunc );
  45. m_pPickerBrowser->SetSortColumn( 0 );
  46. // filter selection
  47. m_pFilterList = new TextEntry( this, "FilterList" );
  48. m_pFilterList->AddActionSignalTarget( this );
  49. m_pFilterList->RequestFocus();
  50. LoadControlSettingsAndUserConfig( "resource/picker.res" );
  51. }
  52. //-----------------------------------------------------------------------------
  53. // Purpose: Destructor
  54. //-----------------------------------------------------------------------------
  55. CPicker::~CPicker()
  56. {
  57. }
  58. //-----------------------------------------------------------------------------
  59. // Purpose:
  60. //-----------------------------------------------------------------------------
  61. void CPicker::OnKeyCodePressed( KeyCode code )
  62. {
  63. if (( code == KEY_UP ) || ( code == KEY_DOWN ) || ( code == KEY_PAGEUP ) || ( code == KEY_PAGEDOWN ))
  64. {
  65. KeyValues *pMsg = new KeyValues("KeyCodePressed", "code", code);
  66. vgui::ipanel()->SendMessage( m_pPickerBrowser->GetVPanel(), pMsg, GetVPanel());
  67. pMsg->deleteThis();
  68. }
  69. else
  70. {
  71. BaseClass::OnKeyCodePressed( code );
  72. }
  73. }
  74. //-----------------------------------------------------------------------------
  75. // Purpose: refreshes the asset list
  76. //-----------------------------------------------------------------------------
  77. void CPicker::SetStringList( const PickerList_t &list )
  78. {
  79. m_Type = list.m_Type;
  80. m_pPickerBrowser->RemoveAll();
  81. int nCount = list.Count();
  82. for ( int i = 0; i < nCount; ++i )
  83. {
  84. const char *pPickerName = list[i].m_pChoiceString;
  85. KeyValues *kv = new KeyValues( "node", "choice", pPickerName );
  86. if ( m_Type == PICKER_CHOICE_STRING )
  87. {
  88. kv->SetString( "value", list[i].m_pChoiceValue );
  89. }
  90. else
  91. {
  92. kv->SetPtr( "value", list[i].m_pChoiceValuePtr );
  93. }
  94. int nItemID = m_pPickerBrowser->AddItem( kv, 0, false, false );
  95. if ( m_Type == PICKER_CHOICE_STRING )
  96. {
  97. KeyValues *pDrag = new KeyValues( "drag", "text", list[i].m_pChoiceValue );
  98. if ( m_pPickerTextType )
  99. {
  100. pDrag->SetString( "texttype", m_pPickerTextType );
  101. }
  102. m_pPickerBrowser->SetItemDragData( nItemID, pDrag );
  103. }
  104. }
  105. RefreshChoiceList();
  106. }
  107. //-----------------------------------------------------------------------------
  108. // Purpose: refreshes the choice list
  109. //-----------------------------------------------------------------------------
  110. void CPicker::RefreshChoiceList( )
  111. {
  112. // Check the filter matches
  113. int nMatchingCount = 0;
  114. int nTotalCount = 0;
  115. for ( int nItemID = m_pPickerBrowser->FirstItem(); nItemID != m_pPickerBrowser->InvalidItemID(); nItemID = m_pPickerBrowser->NextItem( nItemID ) )
  116. {
  117. KeyValues *kv = m_pPickerBrowser->GetItem( nItemID );
  118. const char *pPickerName = kv->GetString( "choice" );
  119. bool bVisible = !m_Filter.Length() || Q_stristr( pPickerName, m_Filter.Get() );
  120. m_pPickerBrowser->SetItemVisible( nItemID, bVisible );
  121. if ( bVisible )
  122. {
  123. ++nMatchingCount;
  124. }
  125. ++nTotalCount;
  126. }
  127. char pColumnTitle[512];
  128. Q_snprintf( pColumnTitle, sizeof(pColumnTitle), "%s (%d/%d)",
  129. m_pPickerType, nMatchingCount, nTotalCount );
  130. m_pPickerBrowser->SetColumnHeaderText( 0, pColumnTitle );
  131. m_pPickerBrowser->SortList();
  132. if ( ( m_pPickerBrowser->GetSelectedItemsCount() == 0 ) && ( m_pPickerBrowser->GetItemCount() > 0 ) )
  133. {
  134. int nItemID = m_pPickerBrowser->GetItemIDFromRow( 0 );
  135. m_pPickerBrowser->SetSelectedCell( nItemID, 0 );
  136. }
  137. }
  138. //-----------------------------------------------------------------------------
  139. // Purpose: refreshes dialog on text changing
  140. //-----------------------------------------------------------------------------
  141. void CPicker::OnTextChanged( )
  142. {
  143. int nLength = m_pFilterList->GetTextLength();
  144. m_Filter.SetLength( nLength );
  145. if ( nLength > 0 )
  146. {
  147. m_pFilterList->GetText( m_Filter.GetForModify(), nLength+1 );
  148. }
  149. RefreshChoiceList();
  150. }
  151. //-----------------------------------------------------------------------------
  152. // Returns the selected string
  153. //-----------------------------------------------------------------------------
  154. PickerChoiceType_t CPicker::GetSelectionType() const
  155. {
  156. return m_Type;
  157. }
  158. const char *CPicker::GetSelectedString( ) const
  159. {
  160. if ( m_pPickerBrowser->GetSelectedItemsCount() == 0 )
  161. return NULL;
  162. if ( m_Type != PICKER_CHOICE_STRING )
  163. return NULL;
  164. int nIndex = m_pPickerBrowser->GetSelectedItem( 0 );
  165. KeyValues *pItemKeyValues = m_pPickerBrowser->GetItem( nIndex );
  166. return pItemKeyValues->GetString( "value" );
  167. }
  168. void *CPicker::GetSelectedPtr( ) const
  169. {
  170. if ( m_pPickerBrowser->GetSelectedItemsCount() == 0 )
  171. return NULL;
  172. if ( m_Type != PICKER_CHOICE_PTR )
  173. return NULL;
  174. int nIndex = m_pPickerBrowser->GetSelectedItem( 0 );
  175. KeyValues *pItemKeyValues = m_pPickerBrowser->GetItem( nIndex );
  176. return pItemKeyValues->GetPtr( "value" );
  177. }
  178. //-----------------------------------------------------------------------------
  179. // Returns the index of the selected string
  180. //-----------------------------------------------------------------------------
  181. int CPicker::GetSelectedIndex()
  182. {
  183. if ( m_pPickerBrowser->GetSelectedItemsCount() == 0 )
  184. return -1;
  185. return m_pPickerBrowser->GetSelectedItem( 0 );
  186. }
  187. //-----------------------------------------------------------------------------
  188. //
  189. // Purpose: Modal picker frame
  190. //
  191. //-----------------------------------------------------------------------------
  192. CPickerFrame::CPickerFrame( vgui::Panel *pParent, const char *pTitle, const char *pPickerType, const char *pTextType ) :
  193. BaseClass( pParent, "PickerFrame" )
  194. {
  195. m_pContextKeyValues = NULL;
  196. SetDeleteSelfOnClose( true );
  197. m_pPicker = new CPicker( this, pPickerType, pTextType );
  198. m_pPicker->AddActionSignalTarget( this );
  199. m_pOpenButton = new Button( this, "OpenButton", "#FileOpenDialog_Open", this, "Open" );
  200. m_pCancelButton = new Button( this, "CancelButton", "#FileOpenDialog_Cancel", this, "Cancel" );
  201. SetBlockDragChaining( true );
  202. LoadControlSettingsAndUserConfig( "resource/pickerframe.res" );
  203. SetTitle( pTitle, false );
  204. }
  205. CPickerFrame::~CPickerFrame()
  206. {
  207. CleanUpMessage();
  208. }
  209. //-----------------------------------------------------------------------------
  210. // Deletes the message
  211. //-----------------------------------------------------------------------------
  212. void CPickerFrame::CleanUpMessage()
  213. {
  214. if ( m_pContextKeyValues )
  215. {
  216. m_pContextKeyValues->deleteThis();
  217. m_pContextKeyValues = NULL;
  218. }
  219. }
  220. //-----------------------------------------------------------------------------
  221. // Purpose: Activate the dialog
  222. //-----------------------------------------------------------------------------
  223. void CPickerFrame::DoModal( const PickerList_t &list, KeyValues *pContextKeyValues )
  224. {
  225. CleanUpMessage();
  226. m_pContextKeyValues = pContextKeyValues;
  227. m_pPicker->SetStringList( list );
  228. BaseClass::DoModal();
  229. }
  230. //-----------------------------------------------------------------------------
  231. // On command
  232. //-----------------------------------------------------------------------------
  233. void CPickerFrame::OnCommand( const char *pCommand )
  234. {
  235. if ( !Q_stricmp( pCommand, "Open" ) )
  236. {
  237. KeyValues *pActionKeys = new KeyValues( "Picked" );
  238. pActionKeys->SetInt( "choiceIndex", m_pPicker->GetSelectedIndex( ) );
  239. if ( m_pPicker->GetSelectionType() == PICKER_CHOICE_STRING )
  240. {
  241. const char *pPickerName = m_pPicker->GetSelectedString( );
  242. pActionKeys->SetString( "choice", pPickerName );
  243. }
  244. else
  245. {
  246. void *pPickerPtr = m_pPicker->GetSelectedPtr( );
  247. pActionKeys->SetPtr( "choice", pPickerPtr );
  248. }
  249. if ( m_pContextKeyValues )
  250. {
  251. pActionKeys->AddSubKey( m_pContextKeyValues );
  252. m_pContextKeyValues = NULL;
  253. }
  254. PostActionSignal( pActionKeys );
  255. CloseModal();
  256. return;
  257. }
  258. if ( !Q_stricmp( pCommand, "Cancel" ) )
  259. {
  260. CloseModal();
  261. return;
  262. }
  263. BaseClass::OnCommand( pCommand );
  264. }