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.

747 lines
22 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Implements a dialog for showing the input connections of an entity
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "stdafx.h"
  8. #include "GlobalFunctions.h"
  9. #include "MapDoc.h"
  10. #include "MapEntity.h"
  11. #include "MapWorld.h"
  12. #include "ObjectProperties.h"
  13. #include "OP_Input.h"
  14. #include "MainFrm.h"
  15. #include "Selection.h"
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include <tier0/memdbgon.h>
  18. //
  19. // Column indices for the list control.
  20. //
  21. const int ICON_COLUMN = 0;
  22. const int SOURCE_NAME_COLUMN = 1;
  23. const int OUTPUT_NAME_COLUMN = 2;
  24. const int INPUT_NAME_COLUMN = 3;
  25. const int PARAMETER_COLUMN = 4;
  26. const int DELAY_COLUMN = 5;
  27. const int ONLY_ONCE_COLUMN = 6;
  28. #define ICON_CONN_BAD 0
  29. #define ICON_CONN_GOOD 1
  30. #define ICON_CONN_BAD_GREY 2
  31. #define ICON_CONN_GOOD_GREY 3
  32. IMPLEMENT_DYNCREATE(COP_Input, CObjectPage)
  33. BEGIN_MESSAGE_MAP(COP_Input, CObjectPage)
  34. //{{AFX_MSG_MAP(COP_Input)
  35. ON_BN_CLICKED(IDC_MARK, OnMark)
  36. ON_WM_SIZE()
  37. ON_WM_DESTROY()
  38. //}}AFX_MSG_MAP
  39. END_MESSAGE_MAP()
  40. //-----------------------------------------------------------------------------
  41. // Static vars
  42. //-----------------------------------------------------------------------------
  43. CImageList* COP_Input::m_pImageList = NULL;
  44. //-----------------------------------------------------------------------------
  45. // Purpose: Constructor.
  46. //-----------------------------------------------------------------------------
  47. COP_Input::COP_Input(void)
  48. : CObjectPage(COP_Input::IDD)
  49. {
  50. m_pObjectList = NULL;
  51. m_pEntityList = new CMapEntityList;
  52. m_pEditObjectRuntimeClass = RUNTIME_CLASS(editCMapClass);
  53. m_nSortColumn = OUTPUT_NAME_COLUMN;
  54. //
  55. // All columns initially sort in ascending order.
  56. //
  57. for (int i = 0; i < OUTPUT_LIST_NUM_COLUMNS; i++)
  58. {
  59. m_eSortDirection[i] = Sort_Ascending;
  60. }
  61. }
  62. //-----------------------------------------------------------------------------
  63. // Purpose: Destructor.
  64. //-----------------------------------------------------------------------------
  65. COP_Input::~COP_Input(void)
  66. {
  67. // Delete my list
  68. delete m_pEntityList;
  69. }
  70. //-----------------------------------------------------------------------------
  71. // Purpose: Compares by delays. Used as a secondary sort by all other columns.
  72. //-----------------------------------------------------------------------------
  73. static int CALLBACK InputCompareDelaysSecondary(CInputConnection *pInputConn1, CInputConnection *pInputConn2, SortDirection_t eDirection)
  74. {
  75. CEntityConnection *pConn1 = pInputConn1->m_pConnection;
  76. CEntityConnection *pConn2 = pInputConn2->m_pConnection;
  77. return(CEntityConnection::CompareDelaysSecondary(pConn1,pConn2,eDirection));
  78. }
  79. //-----------------------------------------------------------------------------
  80. // Purpose: Compares by delays, does a secondary compare by output name.
  81. //-----------------------------------------------------------------------------
  82. static int CALLBACK InputCompareDelays(CInputConnection *pInputConn1, CInputConnection *pInputConn2, SortDirection_t eDirection)
  83. {
  84. CEntityConnection *pConn1 = pInputConn1->m_pConnection;
  85. CEntityConnection *pConn2 = pInputConn2->m_pConnection;
  86. return(CEntityConnection::CompareDelays(pConn1, pConn2,eDirection));
  87. }
  88. //-----------------------------------------------------------------------------
  89. // Purpose: Compares by output name, does a secondary compare by delay.
  90. //-----------------------------------------------------------------------------
  91. static int CALLBACK InputCompareOutputNames(CInputConnection *pInputConn1, CInputConnection *pInputConn2, SortDirection_t eDirection)
  92. {
  93. CEntityConnection *pConn1 = pInputConn1->m_pConnection;
  94. CEntityConnection *pConn2 = pInputConn2->m_pConnection;
  95. return(CEntityConnection::CompareOutputNames(pConn1,pConn2,eDirection));
  96. }
  97. //-----------------------------------------------------------------------------
  98. // Purpose: Compares by input name, does a secondary compare by delay.
  99. //-----------------------------------------------------------------------------
  100. static int CALLBACK InputCompareInputNames(CInputConnection *pInputConn1, CInputConnection *pInputConn2, SortDirection_t eDirection)
  101. {
  102. CEntityConnection *pConn1 = pInputConn1->m_pConnection;
  103. CEntityConnection *pConn2 = pInputConn2->m_pConnection;
  104. return(CEntityConnection::CompareInputNames(pConn1,pConn2,eDirection));
  105. }
  106. //-----------------------------------------------------------------------------
  107. // Purpose: Compares by source name, does a secondary compare by delay.
  108. //-----------------------------------------------------------------------------
  109. static int CALLBACK InputCompareSourceNames(CInputConnection *pInputConn1, CInputConnection *pInputConn2, SortDirection_t eDirection)
  110. {
  111. CEntityConnection *pConn1 = pInputConn1->m_pConnection;
  112. CEntityConnection *pConn2 = pInputConn2->m_pConnection;
  113. return(CEntityConnection::CompareSourceNames(pConn1,pConn2,eDirection));
  114. }
  115. //-----------------------------------------------------------------------------
  116. // Purpose: Compares by target name, does a secondary compare by delay.
  117. //-----------------------------------------------------------------------------
  118. static int CALLBACK InputCompareTargetNames(CInputConnection *pInputConn1, CInputConnection *pInputConn2, SortDirection_t eDirection)
  119. {
  120. CEntityConnection *pConn1 = pInputConn1->m_pConnection;
  121. CEntityConnection *pConn2 = pInputConn2->m_pConnection;
  122. return(CEntityConnection::CompareTargetNames(pConn1,pConn2,eDirection));
  123. }
  124. //------------------------------------------------------------------------------
  125. // Purpose : Returns true if given item number from list control is a valid
  126. // connection type
  127. // Input :
  128. // Output :
  129. //------------------------------------------------------------------------------
  130. bool COP_Input::ValidateConnections(int nItem)
  131. {
  132. CInputConnection *pInputConn = (CInputConnection *)m_ListCtrl.GetItemData(nItem);
  133. // Early out
  134. if (!pInputConn)
  135. {
  136. return false;
  137. }
  138. CEntityConnection *pConnection = pInputConn->m_pConnection;
  139. if (pConnection != NULL)
  140. {
  141. // Validate input
  142. if (!MapEntityList_HasInput(m_pEntityList, pConnection->GetInputName()))
  143. {
  144. return false;
  145. }
  146. // Validate output
  147. CMapEntity *pEntity = pInputConn->m_pEntity;
  148. if (!CEntityConnection::ValidateOutput(pEntity,pConnection->GetOutputName()))
  149. {
  150. return false;
  151. }
  152. }
  153. return true;
  154. }
  155. //------------------------------------------------------------------------------
  156. // Purpose : Updates the validity flag on the given item in the list control
  157. // Input :
  158. // Output :
  159. //------------------------------------------------------------------------------
  160. void COP_Input::UpdateItemValidity(int nItem)
  161. {
  162. int nIcon;
  163. if (ValidateConnections(nItem))
  164. {
  165. nIcon = (m_bMultipleTargetNames ? ICON_CONN_GOOD_GREY : ICON_CONN_GOOD);
  166. }
  167. else
  168. {
  169. nIcon = (m_bMultipleTargetNames ? ICON_CONN_BAD_GREY : ICON_CONN_BAD);
  170. }
  171. m_ListCtrl.SetItem(nItem,0,LVIF_IMAGE, 0, nIcon, 0, 0, 0 );
  172. }
  173. //-----------------------------------------------------------------------------
  174. // Purpose:
  175. // Input : pEntity -
  176. // bFirst -
  177. //-----------------------------------------------------------------------------
  178. void COP_Input::AddEntityConnections(const char *pTargetName, CMapEntity *pTestEntity)
  179. {
  180. int nConnCount = pTestEntity->Connections_GetCount();
  181. if (nConnCount != 0)
  182. {
  183. int nItemCount = m_ListCtrl.GetItemCount();
  184. m_ListCtrl.SetItemCount(nItemCount + nConnCount);
  185. for (int i = 0; i < nConnCount; i++)
  186. {
  187. CEntityConnection *pConnection = pTestEntity->Connections_Get(i);
  188. if (pConnection != NULL && !CompareEntityNames(pConnection->GetTargetName(), pTargetName))
  189. {
  190. // Update source name for correct sorting
  191. const char *pszTestName = pTestEntity->GetKeyValue("targetname");
  192. if (pszTestName == NULL)
  193. {
  194. pszTestName = pTestEntity->GetClassName();
  195. }
  196. pConnection->SetSourceName(pszTestName);
  197. m_ListCtrl.InsertItem(LVIF_IMAGE, nItemCount, "", 0, 0, ICON_CONN_GOOD, 0);
  198. m_ListCtrl.SetItemText(nItemCount, OUTPUT_NAME_COLUMN, pConnection->GetOutputName());
  199. m_ListCtrl.SetItemText(nItemCount, SOURCE_NAME_COLUMN, pConnection->GetSourceName());
  200. m_ListCtrl.SetItemText(nItemCount, INPUT_NAME_COLUMN, pConnection->GetInputName());
  201. // Build the string for the delay.
  202. float fDelay = pConnection->GetDelay();
  203. char szTemp[MAX_PATH];
  204. sprintf(szTemp, "%.2f", fDelay);
  205. m_ListCtrl.SetItemText(nItemCount, DELAY_COLUMN, szTemp);
  206. m_ListCtrl.SetItemText(nItemCount, ONLY_ONCE_COLUMN, (pConnection->GetTimesToFire() == EVENT_FIRE_ALWAYS) ? "No" : "Yes");
  207. m_ListCtrl.SetItemText(nItemCount, PARAMETER_COLUMN, pConnection->GetParam());
  208. // Set list ctrl data
  209. CInputConnection *pInputConn = new CInputConnection;
  210. pInputConn->m_pConnection = pConnection;
  211. pInputConn->m_pEntity = pTestEntity;
  212. m_ListCtrl.SetItemData(nItemCount, (DWORD)pInputConn);
  213. nItemCount++;
  214. }
  215. }
  216. }
  217. }
  218. //-----------------------------------------------------------------------------
  219. // Purpose:
  220. // Input : pDX -
  221. //-----------------------------------------------------------------------------
  222. void COP_Input::DoDataExchange(CDataExchange *pDX)
  223. {
  224. CObjectPage::DoDataExchange(pDX);
  225. //{{AFX_DATA_MAP(COP_Input)
  226. DDX_Control(pDX, IDC_LIST, m_ListCtrl);
  227. //}}AFX_DATA_MAP
  228. }
  229. //------------------------------------------------------------------------------
  230. // Purpose : Take the user to the output page of the selected entity that
  231. // targets me.
  232. // Input :
  233. // Output :
  234. //------------------------------------------------------------------------------
  235. void COP_Input::OnMark(void)
  236. {
  237. // This should always be 1 as dialog is set up to be single select
  238. if (m_ListCtrl.GetSelectedCount() == 1)
  239. {
  240. int nCount = m_ListCtrl.GetItemCount();
  241. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  242. if (nCount > 0 && pDoc)
  243. {
  244. for (int nItem = nCount - 1; nItem >= 0; nItem--)
  245. {
  246. if (m_ListCtrl.GetItemState(nItem, LVIS_SELECTED) & LVIS_SELECTED)
  247. {
  248. CInputConnection *pInputConn = (CInputConnection *)m_ListCtrl.GetItemData(nItem);
  249. CMapEntity *pEntity = pInputConn->m_pEntity;
  250. CEntityConnection *pConnection = pInputConn->m_pConnection;
  251. // Shouldn't happen but just in case
  252. if (!pEntity || !pConnection)
  253. {
  254. return;
  255. }
  256. // Switch to object selection mode so we only select the entity.
  257. pDoc->GetSelection()->SetMode(selectObjects);
  258. // Now switch to the output page with the selected connection
  259. CMapObjectList Select;
  260. Select.AddToTail(pEntity);
  261. pDoc->SelectObjectList(&Select);
  262. // (a bit squirly way of doing this)
  263. GetMainWnd()->pObjectProperties->SetPageToOutput(pConnection);
  264. pDoc->Center2DViewsOnSelection();
  265. return;
  266. }
  267. }
  268. }
  269. }
  270. }
  271. //-----------------------------------------------------------------------------
  272. // Purpose: Sets up the list view columns, initial sort column.
  273. //-----------------------------------------------------------------------------
  274. BOOL COP_Input::OnInitDialog(void)
  275. {
  276. CObjectPage::OnInitDialog();
  277. m_ListCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP);
  278. m_ListCtrl.InsertColumn(ICON_COLUMN, "", LVCFMT_CENTER, 20);
  279. m_ListCtrl.InsertColumn(SOURCE_NAME_COLUMN, "Source", LVCFMT_LEFT, 70);
  280. m_ListCtrl.InsertColumn(OUTPUT_NAME_COLUMN, "Output", LVCFMT_LEFT, 70);
  281. m_ListCtrl.InsertColumn(INPUT_NAME_COLUMN, "My Input", LVCFMT_LEFT, 70);
  282. m_ListCtrl.InsertColumn(DELAY_COLUMN, "Delay", LVCFMT_LEFT, 70);
  283. m_ListCtrl.InsertColumn(ONLY_ONCE_COLUMN, "Once", LVCFMT_LEFT, 70);
  284. m_ListCtrl.InsertColumn(PARAMETER_COLUMN, "Parameter", LVCFMT_LEFT, 70);
  285. UpdateConnectionList();
  286. SetSortColumn(m_nSortColumn, m_eSortDirection[m_nSortColumn]);
  287. // Force an update of the column header text so that the sort indicator is shown.
  288. UpdateColumnHeaderText(m_nSortColumn, true, m_eSortDirection[m_nSortColumn]);
  289. if (m_ListCtrl.GetItemCount() > 0)
  290. {
  291. m_ListCtrl.SetColumnWidth(OUTPUT_NAME_COLUMN, LVSCW_AUTOSIZE);
  292. m_ListCtrl.SetColumnWidth(SOURCE_NAME_COLUMN, LVSCW_AUTOSIZE);
  293. m_ListCtrl.SetColumnWidth(INPUT_NAME_COLUMN, LVSCW_AUTOSIZE);
  294. m_ListCtrl.SetColumnWidth(DELAY_COLUMN, LVSCW_AUTOSIZE_USEHEADER);
  295. m_ListCtrl.SetColumnWidth(ONLY_ONCE_COLUMN, LVSCW_AUTOSIZE_USEHEADER);
  296. m_ListCtrl.SetColumnWidth(PARAMETER_COLUMN, LVSCW_AUTOSIZE);
  297. }
  298. // Create image list. Is deleted automatically when listctrl is deleted
  299. if (!m_pImageList)
  300. {
  301. CWinApp *pApp = AfxGetApp();
  302. m_pImageList = new CImageList();
  303. Assert(m_pImageList != NULL); // serious allocation failure checking
  304. m_pImageList->Create(16, 16, TRUE, 1, 0);
  305. m_pImageList->Add(pApp->LoadIcon( IDI_INPUTBAD ));
  306. m_pImageList->Add(pApp->LoadIcon( IDI_INPUT ));
  307. m_pImageList->Add(pApp->LoadIcon( IDI_INPUTBAD_GREY ));
  308. m_pImageList->Add(pApp->LoadIcon( IDI_INPUT_GREY ));
  309. }
  310. m_ListCtrl.SetImageList(m_pImageList, LVSIL_SMALL );
  311. CAnchorDef anchorDefs[] =
  312. {
  313. CAnchorDef( IDC_LIST, k_eSimpleAnchorAllSides ),
  314. CAnchorDef( IDC_MARK, k_eSimpleAnchorBottomSide ),
  315. CAnchorDef( IDC_INFO_TEXT, k_eSimpleAnchorBottomSide )
  316. };
  317. m_AnchorMgr.Init( GetSafeHwnd(), anchorDefs, ARRAYSIZE( anchorDefs ) );
  318. return(TRUE);
  319. }
  320. //-----------------------------------------------------------------------------
  321. // Purpose:
  322. // Input : wParam -
  323. // lParam -
  324. // pResult -
  325. // Output : Returns TRUE on success, FALSE on failure.
  326. //-----------------------------------------------------------------------------
  327. BOOL COP_Input::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT *pResult)
  328. {
  329. NMHDR *pnmh = (NMHDR *)lParam;
  330. if (pnmh->idFrom == IDC_LIST)
  331. {
  332. switch (pnmh->code)
  333. {
  334. case LVN_COLUMNCLICK:
  335. {
  336. NMLISTVIEW *pnmv = (NMLISTVIEW *)lParam;
  337. if (pnmv->iSubItem < OUTPUT_LIST_NUM_COLUMNS)
  338. {
  339. SortDirection_t eSortDirection = m_eSortDirection[pnmv->iSubItem];
  340. //
  341. // If they clicked on the current sort column, reverse the sort direction.
  342. //
  343. if (pnmv->iSubItem == m_nSortColumn)
  344. {
  345. if (m_eSortDirection[m_nSortColumn] == Sort_Ascending)
  346. {
  347. eSortDirection = Sort_Descending;
  348. }
  349. else
  350. {
  351. eSortDirection = Sort_Ascending;
  352. }
  353. }
  354. //
  355. // Update the sort column and sort the list.
  356. //
  357. SetSortColumn(pnmv->iSubItem, eSortDirection);
  358. }
  359. return(TRUE);
  360. }
  361. case NM_DBLCLK:
  362. {
  363. OnMark();
  364. return(TRUE);
  365. }
  366. }
  367. }
  368. return(CObjectPage::OnNotify(wParam, lParam, pResult));
  369. }
  370. //-----------------------------------------------------------------------------
  371. // Purpose: Empties the contents of the connections list control, freeing the
  372. // connection list hanging off of each row.
  373. //-----------------------------------------------------------------------------
  374. void COP_Input::RemoveAllEntityConnections(void)
  375. {
  376. int nCount = m_ListCtrl.GetItemCount();
  377. if (nCount > 0)
  378. {
  379. for (int nItem = nCount - 1; nItem >= 0; nItem--)
  380. {
  381. CInputConnection *pInputConnection = (CInputConnection *)m_ListCtrl.GetItemData(nItem);
  382. m_ListCtrl.DeleteItem(nItem);
  383. delete pInputConnection;
  384. }
  385. }
  386. }
  387. //-----------------------------------------------------------------------------
  388. // Purpose:
  389. // Input : Mode -
  390. // pData -
  391. //-----------------------------------------------------------------------------
  392. void COP_Input::UpdateData( int Mode, PVOID pData, bool bCanEdit )
  393. {
  394. __super::UpdateData( Mode, pData, bCanEdit );
  395. if (!IsWindow(m_hWnd))
  396. {
  397. return;
  398. }
  399. switch (Mode)
  400. {
  401. case LoadFirstData:
  402. {
  403. // m_ListCtrl.DeleteAllItems();
  404. // UpdateConnectionList();
  405. break;
  406. }
  407. case LoadData:
  408. {
  409. // m_ListCtrl.DeleteAllItems();
  410. // UpdateConnectionList();
  411. break;
  412. }
  413. case LoadFinished:
  414. {
  415. m_ListCtrl.DeleteAllItems();
  416. UpdateConnectionList();
  417. SortListByColumn(m_nSortColumn, m_eSortDirection[m_nSortColumn]);
  418. }
  419. }
  420. }
  421. //-----------------------------------------------------------------------------
  422. // Purpose:
  423. // Input : nColumn -
  424. // eDirection -
  425. //-----------------------------------------------------------------------------
  426. void COP_Input::SetSortColumn(int nColumn, SortDirection_t eDirection)
  427. {
  428. Assert(nColumn < OUTPUT_LIST_NUM_COLUMNS);
  429. //
  430. // If the sort column changed, update the old sort column header text.
  431. //
  432. if (m_nSortColumn != nColumn)
  433. {
  434. UpdateColumnHeaderText(m_nSortColumn, false, eDirection);
  435. }
  436. //
  437. // If the sort column or direction changed, update the new sort column header text.
  438. //
  439. if ((m_nSortColumn != nColumn) || (m_eSortDirection[m_nSortColumn] != eDirection))
  440. {
  441. UpdateColumnHeaderText(nColumn, true, eDirection);
  442. }
  443. m_nSortColumn = nColumn;
  444. m_eSortDirection[m_nSortColumn] = eDirection;
  445. SortListByColumn(m_nSortColumn, m_eSortDirection[m_nSortColumn]);
  446. }
  447. //-----------------------------------------------------------------------------
  448. // Purpose: Sorts the outputs list by column.
  449. // Input : nColumn - Index of column by which to sort.
  450. //-----------------------------------------------------------------------------
  451. void COP_Input::SortListByColumn(int nColumn, SortDirection_t eDirection)
  452. {
  453. PFNLVCOMPARE pfnSort = NULL;
  454. switch (nColumn)
  455. {
  456. case ONLY_ONCE_COLUMN:
  457. {
  458. // No sort
  459. break;
  460. }
  461. case PARAMETER_COLUMN:
  462. {
  463. // No sort
  464. break;
  465. }
  466. case OUTPUT_NAME_COLUMN:
  467. {
  468. pfnSort = (PFNLVCOMPARE)InputCompareOutputNames;
  469. break;
  470. }
  471. case SOURCE_NAME_COLUMN:
  472. {
  473. pfnSort = (PFNLVCOMPARE)InputCompareSourceNames;
  474. break;
  475. }
  476. case INPUT_NAME_COLUMN:
  477. {
  478. pfnSort = (PFNLVCOMPARE)InputCompareInputNames;
  479. break;
  480. }
  481. case DELAY_COLUMN:
  482. {
  483. pfnSort = (PFNLVCOMPARE)InputCompareDelays;
  484. break;
  485. }
  486. default:
  487. {
  488. Assert(FALSE);
  489. break;
  490. }
  491. }
  492. if (pfnSort != NULL)
  493. {
  494. m_ListCtrl.SortItems(pfnSort, (DWORD)eDirection);
  495. }
  496. }
  497. //------------------------------------------------------------------------------
  498. // Purpose : Generates list of map entites that are being edited from the
  499. // m_pObject list
  500. // Input :
  501. // Output :
  502. //------------------------------------------------------------------------------
  503. void COP_Input::UpdateEntityList()
  504. {
  505. // Clear old entity list
  506. m_pEntityList->RemoveAll();
  507. if (m_pObjectList != NULL)
  508. {
  509. FOR_EACH_OBJ( *m_pObjectList, pos )
  510. {
  511. CMapClass *pObject = m_pObjectList->Element(pos);
  512. if ((pObject != NULL) && (pObject->IsMapClass(MAPCLASS_TYPE(CMapEntity))))
  513. {
  514. CMapEntity *pEntity = (CMapEntity *)pObject;
  515. m_pEntityList->AddToTail(pEntity);
  516. }
  517. }
  518. }
  519. }
  520. //-----------------------------------------------------------------------------
  521. // Purpose:
  522. //-----------------------------------------------------------------------------
  523. void COP_Input::UpdateConnectionList(void)
  524. {
  525. UpdateEntityList();
  526. RemoveAllEntityConnections();
  527. m_bMultipleTargetNames = false;
  528. const char *pszTargetName = NULL;
  529. FOR_EACH_OBJ( *m_pEntityList, pos )
  530. {
  531. CMapEntity *pInEntity = m_pEntityList->Element(pos);
  532. if (!pszTargetName)
  533. {
  534. pszTargetName = pInEntity->GetKeyValue("targetname");
  535. }
  536. else if (pszTargetName != pInEntity->GetKeyValue("targetname"))
  537. {
  538. pszTargetName = pInEntity->GetKeyValue("targetname");
  539. m_bMultipleTargetNames = true;
  540. }
  541. if (pszTargetName)
  542. {
  543. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  544. CMapWorld *pWorld = pDoc->GetMapWorld();
  545. const CMapEntityList *pEntityList = pWorld->EntityList_GetList();
  546. FOR_EACH_OBJ( *pEntityList, pos2 )
  547. {
  548. CMapEntity *pTestEntity = pEntityList->Element(pos2);
  549. if (pTestEntity != NULL)
  550. {
  551. AddEntityConnections(pszTargetName, pTestEntity);
  552. }
  553. }
  554. }
  555. }
  556. // Update validity flag on all items
  557. for (int nItem = 0; nItem < m_ListCtrl.GetItemCount(); nItem++)
  558. {
  559. UpdateItemValidity(nItem);
  560. }
  561. m_ListCtrl.EnableWindow(true);
  562. }
  563. //-----------------------------------------------------------------------------
  564. // Purpose: Adds or removes the little 'V' or '^' sort indicator as appropriate.
  565. // Input : nColumn - Index of column to update.
  566. // bSortColumn - true if this column is the sort column, false if not.
  567. // eDirection - Direction of sort, Sort_Ascending or Sort_Descending.
  568. //-----------------------------------------------------------------------------
  569. void COP_Input::UpdateColumnHeaderText(int nColumn, bool bIsSortColumn, SortDirection_t eDirection)
  570. {
  571. char szHeaderText[MAX_PATH];
  572. LVCOLUMN Column;
  573. memset(&Column, 0, sizeof(Column));
  574. Column.mask = LVCF_TEXT;
  575. Column.pszText = szHeaderText;
  576. Column.cchTextMax = sizeof(szHeaderText);
  577. m_ListCtrl.GetColumn(nColumn, &Column);
  578. int nMarker = 0;
  579. if (szHeaderText[0] != '\0')
  580. {
  581. nMarker = strlen(szHeaderText) - 1;
  582. char chMarker = szHeaderText[nMarker];
  583. if ((chMarker == '>') || (chMarker == '<'))
  584. {
  585. nMarker -= 2;
  586. }
  587. else
  588. {
  589. nMarker++;
  590. }
  591. }
  592. if (bIsSortColumn)
  593. {
  594. if (nMarker != 0)
  595. {
  596. szHeaderText[nMarker++] = ' ';
  597. szHeaderText[nMarker++] = ' ';
  598. }
  599. szHeaderText[nMarker++] = (eDirection == Sort_Ascending) ? '>' : '<';
  600. }
  601. szHeaderText[nMarker] = '\0';
  602. m_ListCtrl.SetColumn(nColumn, &Column);
  603. }
  604. //-----------------------------------------------------------------------------
  605. // Purpose: Called when our window is being destroyed.
  606. //-----------------------------------------------------------------------------
  607. void COP_Input::OnDestroy(void)
  608. {
  609. RemoveAllEntityConnections();
  610. }
  611. //------------------------------------------------------------------------------
  612. // Purpose: Set the selected item in the listbox
  613. // Input : pConnection
  614. //------------------------------------------------------------------------------
  615. void COP_Input::SetSelectedConnection(CEntityConnection *pConnection)
  616. {
  617. m_ListCtrl.SetRedraw(FALSE);
  618. // Set selected item to be active and all others to false
  619. int nItemCount = m_ListCtrl.GetItemCount();
  620. for (int nItem = 0; nItem < nItemCount; nItem++)
  621. {
  622. CInputConnection *pOutputConn = (CInputConnection *)m_ListCtrl.GetItemData(nItem);
  623. if ( pOutputConn->m_pConnection == pConnection)
  624. {
  625. m_ListCtrl.SetItemState(nItem,LVIS_SELECTED,LVIS_SELECTED);
  626. }
  627. else
  628. {
  629. m_ListCtrl.SetItemState(nItem, (unsigned int)~LVIS_SELECTED, (unsigned int)LVIS_SELECTED);
  630. }
  631. }
  632. m_ListCtrl.SetRedraw(TRUE);
  633. }
  634. void COP_Input::OnSize( UINT nType, int cx, int cy )
  635. {
  636. m_AnchorMgr.OnSize();
  637. }