DialogEntityDefEditor.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "../../sys/win32/rc/Common_resource.h"
  23. #include "../../sys/win32/rc/DeclEditor_resource.h"
  24. #include "../comafx/CPathTreeCtrl.h"
  25. #include "DialogDeclBrowser.h"
  26. #include "DialogDeclEditor.h"
  27. #include "DialogEntityDefEditor.h"
  28. #ifdef ID_DEBUG_MEMORY
  29. #undef new
  30. #undef DEBUG_NEW
  31. #define DEBUG_NEW new
  32. #endif
  33. // DialogEntityDefEditor dialog
  34. toolTip_t DialogEntityDefEditor::toolTips[] = {
  35. { IDC_DECLEDITOR_BUTTON_TEST, "Test Decl" },
  36. { IDOK, "Save Decl" },
  37. { IDCANCEL, "Cancel" },
  38. { 0, NULL }
  39. };
  40. IMPLEMENT_DYNAMIC(DialogEntityDefEditor, CDialog)
  41. /*
  42. ================
  43. DialogEntityDefEditor::DialogEntityDefEditor
  44. ================
  45. */
  46. DialogEntityDefEditor::DialogEntityDefEditor( CWnd* pParent /*=NULL*/ )
  47. : CDialog(DialogEntityDefEditor::IDD, pParent)
  48. , decl(NULL)
  49. , firstLine(0)
  50. {
  51. }
  52. /*
  53. ================
  54. DialogEntityDefEditor::~DialogEntityDefEditor
  55. ================
  56. */
  57. DialogEntityDefEditor::~DialogEntityDefEditor() {
  58. }
  59. /*
  60. ================
  61. DialogEntityDefEditor::DoDataExchange
  62. ================
  63. */
  64. void DialogEntityDefEditor::DoDataExchange(CDataExchange* pDX) {
  65. CDialog::DoDataExchange(pDX);
  66. //{{AFX_DATA_MAP(DialogEntityDefEditor)
  67. DDX_Control(pDX, IDC_ENTITYDEFEDITOR_EDIT_DECLNAME, declNameEdit);
  68. DDX_Control(pDX, IDC_ENTITYDEFEDITOR_COMBO_INHERIT, inheritCombo);
  69. DDX_Control(pDX, IDC_ENTITYDEFEDITOR_COMBO_SPAWNCLASS, spawnclassCombo);
  70. DDX_Control(pDX, IDC_ENTITYDEFEDITOR_LIST_KEYVALS, keyValsList);
  71. DDX_Control(pDX, IDC_ENTITYDEFEDITOR_STATIC_KEY, keyLabel);
  72. DDX_Control(pDX, IDC_ENTITYDEFEDITOR_EDIT_KEY, keyEdit);
  73. DDX_Control(pDX, IDC_ENTITYDEFEDITOR_BUTTON_ADD, addButton);
  74. DDX_Control(pDX, IDC_ENTITYDEFEDITOR_BUTTON_DELETE, delButton);
  75. DDX_Control(pDX, IDC_ENTITYDEFEDITOR_LINE, line);
  76. DDX_Control(pDX, IDC_DECLEDITOR_BUTTON_TEST, testButton);
  77. DDX_Control(pDX, IDOK, okButton);
  78. DDX_Control(pDX, IDCANCEL, cancelButton);
  79. //}}AFX_DATA_MAP
  80. }
  81. /*
  82. ================
  83. DialogEntityDefEditor::PreTranslateMessage
  84. ================
  85. */
  86. BOOL DialogEntityDefEditor::PreTranslateMessage( MSG* pMsg ) {
  87. if ( WM_KEYFIRST <= pMsg->message && pMsg->message <= WM_KEYLAST ) {
  88. if ( m_hAccel && ::TranslateAccelerator( m_hWnd, m_hAccel, pMsg ) ) {
  89. return TRUE;
  90. }
  91. }
  92. return CWnd::PreTranslateMessage(pMsg);
  93. }
  94. /*
  95. ================
  96. DialogEntityDefEditor::TestDecl
  97. ================
  98. */
  99. bool DialogEntityDefEditor::TestDecl( const idStr &declText ) {
  100. idLexer src( LEXFL_NOSTRINGCONCAT );
  101. idToken token;
  102. int indent;
  103. src.LoadMemory( declText, declText.Length(), "decl text" );
  104. indent = 0;
  105. while( src.ReadToken( &token ) ) {
  106. if ( token == "{" ) {
  107. indent++;
  108. } else if ( token == "}" ) {
  109. indent--;
  110. }
  111. }
  112. if ( indent < 0 ) {
  113. MessageBox( "Missing opening brace!", va( "Error saving %s", decl->GetFileName() ), MB_OK | MB_ICONERROR );
  114. return false;
  115. }
  116. if ( indent > 0 ) {
  117. MessageBox( "Missing closing brace!", va( "Error saving %s", decl->GetFileName() ), MB_OK | MB_ICONERROR );
  118. return false;
  119. }
  120. return true;
  121. }
  122. /*
  123. ================
  124. DialogEntityDefEditor::UpdateStatusBar
  125. ================
  126. */
  127. void DialogEntityDefEditor::UpdateStatusBar( void ) {
  128. if ( decl ) {
  129. statusBar.SetWindowText( "Editing decl" );
  130. }
  131. }
  132. /*
  133. ================
  134. DialogEntityDefEditor::LoadDecl
  135. ================
  136. */
  137. void DialogEntityDefEditor::LoadDecl( idDeclEntityDef *decl ) {
  138. int numLines = 0;
  139. CRect rect;
  140. this->decl = decl;
  141. // Fill up the spawnclass box with all spawn classes
  142. /*
  143. idTypeInfo *c = idClass::GetClass("idClass");
  144. for (; c; c = c->next) {
  145. spawnclassCombo.AddString(c->classname);
  146. }
  147. */
  148. // Fill up the inherit box with all entitydefs
  149. int numDecls = declManager->GetNumDecls(DECL_ENTITYDEF);
  150. for (int i=0; i<numDecls; i++) {
  151. const idDecl *d = declManager->DeclByIndex(DECL_ENTITYDEF, i, false);
  152. if (d) {
  153. inheritCombo.AddString(d->GetName());
  154. }
  155. }
  156. firstLine = decl->GetLineNum();
  157. char *declText = (char *)_alloca( ( decl->GetTextLength() + 1 ) * sizeof( char ) );
  158. decl->GetText( declText );
  159. PopulateLists( declText );
  160. SetWindowText( va( "EntityDef Editor (%s, line %d)", decl->GetFileName(), decl->GetLineNum() ) );
  161. // Hack to get it to reflow the window
  162. GetWindowRect( rect );
  163. rect.bottom++;
  164. MoveWindow( rect );
  165. testButton.EnableWindow( FALSE );
  166. okButton.EnableWindow( FALSE );
  167. UpdateStatusBar();
  168. }
  169. /*
  170. =================
  171. DialogEntityDefEditor::PopulateLists
  172. =================
  173. */
  174. void DialogEntityDefEditor::PopulateLists( const char *declText, const int textLength )
  175. {
  176. idLexer src;
  177. idToken token, token2;
  178. idDict dict;
  179. src.LoadMemory( declText, textLength, decl->GetFileName(), firstLine);
  180. src.SetFlags( DECL_LEXER_FLAGS );
  181. src.SkipUntilString( "{" );
  182. while (1) {
  183. if ( !src.ReadToken( &token ) ) {
  184. break;
  185. }
  186. if ( !token.Icmp( "}" ) ) {
  187. break;
  188. }
  189. if ( token.type != TT_STRING ) {
  190. src.Warning( "Expected quoted string, but found '%s'", token.c_str() );
  191. break;
  192. }
  193. if ( !src.ReadToken( &token2 ) ) {
  194. src.Warning( "Unexpected end of file" );
  195. break;
  196. }
  197. if ( dict.FindKey( token ) ) {
  198. src.Warning( "'%s' already defined", token.c_str() );
  199. }
  200. dict.Set( token, token2 );
  201. }
  202. // Get the parent, and remove the 'inherit' key so it doesn't show up in the list
  203. // We currently don't support multiple inheritence properly, but nothing uses it anyway
  204. idStr inherit;
  205. const idKeyValue *inheritKeyVal = dict.FindKey("inherit");
  206. if (inheritKeyVal) {
  207. inherit = inheritKeyVal->GetValue();
  208. dict.Delete(inheritKeyVal->GetKey());
  209. }
  210. idStr spawnclass = dict.GetString("spawnclass", "");
  211. dict.Delete("spawnclass");
  212. keyValsList.ResetContent();
  213. // Fill up the list with all the main info
  214. size_t numPairs = dict.Size();
  215. for (unsigned int i=0; i<numPairs; i++) {
  216. const idKeyValue *keyVal = dict.GetKeyVal(i);
  217. if (keyVal) {
  218. keyValsList.AddPropItem(new CPropertyItem(keyVal->GetKey().c_str(), keyVal->GetValue().c_str(), PIT_EDIT, ""));
  219. }
  220. }
  221. //inheritCombo.SelectString(0, inherit);
  222. SetInherit(inherit);
  223. inheritCombo.SelectString(0, inherit);
  224. declNameEdit.SetWindowText(decl->GetName());
  225. int index = spawnclassCombo.FindString(0, spawnclass);
  226. if (index == CB_ERR) {
  227. index = spawnclassCombo.AddString(spawnclass);
  228. }
  229. spawnclassCombo.SetCurSel(index);
  230. }
  231. /*
  232. =================
  233. DialogEntityDefEditor::SetInherit
  234. =================
  235. */
  236. void DialogEntityDefEditor::SetInherit(idStr &inherit)
  237. {
  238. CWaitCursor wc;
  239. for (int i=0; i<keyValsList.GetCount(); i++) {
  240. CPropertyItem* pItem = (CPropertyItem*)keyValsList.GetItemDataPtr(i);
  241. if (pItem) {
  242. if (pItem->m_propName[0] == '*') {
  243. delete pItem;
  244. keyValsList.DeleteString(i);
  245. i--;
  246. }
  247. }
  248. }
  249. CString spawnclass;
  250. // Fill up the rest of the box with inherited info
  251. if (!inherit.IsEmpty()) {
  252. const idDecl *temp = declManager->FindType(DECL_ENTITYDEF, inherit, false);
  253. const idDeclEntityDef *parent = static_cast<const idDeclEntityDef *>(temp);
  254. if (parent) {
  255. size_t numPairs = parent->dict.Size();
  256. for (unsigned int i=0; i<numPairs; i++) {
  257. const idKeyValue *keyVal = parent->dict.GetKeyVal(i);
  258. if (keyVal) {
  259. if (spawnclass.IsEmpty() && keyVal->GetKey() == "spawnclass") {
  260. spawnclass = keyVal->GetValue();
  261. }
  262. else {
  263. CString key = keyVal->GetKey();
  264. key = "*" + key;
  265. keyValsList.AddPropItem(new CPropertyItem(key, keyVal->GetValue().c_str(), PIT_EDIT, ""));
  266. }
  267. }
  268. }
  269. }
  270. }
  271. }
  272. /*
  273. ================
  274. DialogEntityDefEditor::OnInitDialog
  275. ================
  276. */
  277. BOOL DialogEntityDefEditor::OnInitDialog() {
  278. com_editors |= EDITOR_ENTITYDEF;
  279. CDialog::OnInitDialog();
  280. // load accelerator table
  281. m_hAccel = ::LoadAccelerators( AfxGetResourceHandle(), MAKEINTRESOURCE( IDR_ACCELERATOR_DECLEDITOR ) );
  282. // create status bar
  283. statusBar.CreateEx( SBARS_SIZEGRIP, WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, initialRect, this, AFX_IDW_STATUS_BAR );
  284. GetClientRect( initialRect );
  285. EnableToolTips( TRUE );
  286. testButton.EnableWindow( FALSE );
  287. okButton.EnableWindow( FALSE );
  288. UpdateStatusBar();
  289. return FALSE; // return TRUE unless you set the focus to a control
  290. // EXCEPTION: OCX Property Pages should return FALSE
  291. }
  292. BEGIN_MESSAGE_MAP(DialogEntityDefEditor, CDialog)
  293. ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
  294. ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
  295. ON_WM_DESTROY()
  296. ON_WM_ACTIVATE()
  297. ON_WM_MOVE()
  298. ON_WM_SIZE()
  299. ON_WM_SIZING()
  300. ON_WM_SETFOCUS()
  301. ON_CBN_EDITCHANGE(IDC_ENTITYDEFEDITOR_COMBO_INHERIT, OnInheritChange)
  302. ON_CBN_SELCHANGE(IDC_ENTITYDEFEDITOR_COMBO_INHERIT, OnInheritChange)
  303. ON_CBN_EDITCHANGE(IDC_ENTITYDEFEDITOR_COMBO_SPAWNCLASS, OnEditChange)
  304. ON_EN_CHANGE(IDC_ENTITYDEFEDITOR_EDIT_DECLNAME, OnEditChange)
  305. ON_NOTIFY(EN_MSGFILTER, IDC_DECLEDITOR_EDIT_TEXT, OnEnInputEdit)
  306. ON_LBN_SELCHANGE(IDC_ENTITYDEFEDITOR_LIST_KEYVALS, OnKeyValChange)
  307. ON_BN_CLICKED(IDC_ENTITYDEFEDITOR_BUTTON_ADD, OnBnClickedAdd)
  308. ON_BN_CLICKED(IDC_ENTITYDEFEDITOR_BUTTON_DELETE, OnBnClickedDelete)
  309. ON_BN_CLICKED(IDC_DECLEDITOR_BUTTON_TEST, OnBnClickedTest)
  310. ON_BN_CLICKED(IDOK, OnBnClickedOk)
  311. ON_BN_CLICKED(IDCANCEL, OnBnClickedCancel)
  312. END_MESSAGE_MAP()
  313. // DialogEntityDefEditor message handlers
  314. /*
  315. ================
  316. DialogEntityDefEditor::OnActivate
  317. ================
  318. */
  319. void DialogEntityDefEditor::OnActivate( UINT nState, CWnd *pWndOther, BOOL bMinimized ) {
  320. CDialog::OnActivate( nState, pWndOther, bMinimized );
  321. }
  322. /*
  323. ================
  324. DialogEntityDefEditor::OnToolTipNotify
  325. ================
  326. */
  327. BOOL DialogEntityDefEditor::OnToolTipNotify( UINT id, NMHDR *pNMHDR, LRESULT *pResult ) {
  328. return DefaultOnToolTipNotify( toolTips, id, pNMHDR, pResult );
  329. }
  330. /*
  331. ================
  332. DialogEntityDefEditor::OnSetFocus
  333. ================
  334. */
  335. void DialogEntityDefEditor::OnSetFocus( CWnd *pOldWnd ) {
  336. CDialog::OnSetFocus( pOldWnd );
  337. }
  338. /*
  339. ================
  340. DialogEntityDefEditor::OnDestroy
  341. ================
  342. */
  343. void DialogEntityDefEditor::OnDestroy() {
  344. return CDialog::OnDestroy();
  345. }
  346. /*
  347. ================
  348. DialogEntityDefEditor::OnMove
  349. ================
  350. */
  351. void DialogEntityDefEditor::OnMove( int x, int y ) {
  352. if ( GetSafeHwnd() ) {
  353. CRect rct;
  354. GetWindowRect( rct );
  355. // FIXME: save position
  356. }
  357. CDialog::OnMove( x, y );
  358. }
  359. /*
  360. ================
  361. DialogEntityDefEditor::OnSize
  362. ================
  363. */
  364. #define BORDER_SIZE 4
  365. #define BUTTON_SPACE 4
  366. #define CONTROL_HEIGHT 24
  367. #define TOOLBAR_HEIGHT 24
  368. void DialogEntityDefEditor::OnSize( UINT nType, int cx, int cy ) {
  369. CRect clientRect, rect;
  370. LockWindowUpdate();
  371. CDialog::OnSize( nType, cx, cy );
  372. GetClientRect( clientRect );
  373. if ( keyValsList.GetSafeHwnd() ) {
  374. keyValsList.GetClientRect( rect );
  375. rect.left = BORDER_SIZE;
  376. rect.right = clientRect.right - BORDER_SIZE;
  377. rect.top = (TOOLBAR_HEIGHT * 2) + (BUTTON_SPACE * 3);
  378. rect.bottom = clientRect.bottom - (TOOLBAR_HEIGHT * 4) - BUTTON_SPACE;
  379. keyValsList.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
  380. }
  381. int keyRowTop = clientRect.Height() - TOOLBAR_HEIGHT * 3 - CONTROL_HEIGHT;
  382. int keyRowBottom = keyRowTop + CONTROL_HEIGHT;
  383. int lineTop = clientRect.Height() - TOOLBAR_HEIGHT * 3 + (CONTROL_HEIGHT / 2);
  384. int buttonRowTop = clientRect.Height() - TOOLBAR_HEIGHT - CONTROL_HEIGHT;
  385. int buttonRowBottom = buttonRowTop + CONTROL_HEIGHT;
  386. if ( keyLabel.GetSafeHwnd() ) {
  387. keyLabel.GetClientRect( rect );
  388. int width = rect.Width();
  389. rect.left = BORDER_SIZE;
  390. rect.right = BORDER_SIZE + width;
  391. rect.top = keyRowTop + 8;
  392. rect.bottom = keyRowBottom;
  393. keyLabel.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
  394. }
  395. if ( keyEdit.GetSafeHwnd() ) {
  396. keyEdit.GetClientRect( rect );
  397. rect.left = 40;
  398. rect.right = 40 + 200;
  399. rect.top = keyRowTop;
  400. rect.bottom = keyRowBottom;
  401. keyEdit.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
  402. }
  403. if ( addButton.GetSafeHwnd() ) {
  404. addButton.GetClientRect( rect );
  405. int width = rect.Width();
  406. rect.left = clientRect.Width() - BORDER_SIZE - BUTTON_SPACE - 2 * width;
  407. rect.right = clientRect.Width() - BORDER_SIZE - BUTTON_SPACE - width;
  408. rect.top = keyRowTop;
  409. rect.bottom = keyRowBottom;
  410. addButton.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
  411. }
  412. if ( delButton.GetSafeHwnd() ) {
  413. delButton.GetClientRect( rect );
  414. int width = rect.Width();
  415. rect.left = clientRect.Width() - BORDER_SIZE - width;
  416. rect.right = clientRect.Width() - BORDER_SIZE;
  417. rect.top = keyRowTop;
  418. rect.bottom = keyRowBottom;
  419. delButton.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
  420. }
  421. if ( line.GetSafeHwnd() ) {
  422. line.GetClientRect( rect );
  423. int height = rect.Height();
  424. rect.left = BORDER_SIZE;
  425. rect.right = clientRect.Width() - BORDER_SIZE;
  426. rect.top = lineTop;
  427. rect.bottom = lineTop + 3;
  428. line.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
  429. }
  430. if ( testButton.GetSafeHwnd() ) {
  431. testButton.GetClientRect( rect );
  432. int width = rect.Width();
  433. rect.left = BORDER_SIZE;
  434. rect.right = BORDER_SIZE + width;
  435. rect.top = buttonRowTop;
  436. rect.bottom = buttonRowBottom;
  437. testButton.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
  438. }
  439. if ( okButton.GetSafeHwnd() ) {
  440. okButton.GetClientRect( rect );
  441. int width = rect.Width();
  442. rect.left = clientRect.Width() - BORDER_SIZE - BUTTON_SPACE - 2 * width;
  443. rect.right = clientRect.Width() - BORDER_SIZE - BUTTON_SPACE - width;
  444. rect.top = buttonRowTop;
  445. rect.bottom = buttonRowBottom;
  446. okButton.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
  447. }
  448. if ( cancelButton.GetSafeHwnd() ) {
  449. cancelButton.GetClientRect( rect );
  450. int width = rect.Width();
  451. rect.left = clientRect.Width() - BORDER_SIZE - width;
  452. rect.right = clientRect.Width() - BORDER_SIZE;
  453. rect.top = buttonRowTop;
  454. rect.bottom = buttonRowBottom;
  455. cancelButton.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
  456. }
  457. if ( statusBar.GetSafeHwnd() ) {
  458. rect.left = clientRect.Width() - 2;
  459. rect.top = clientRect.Height() - 2;
  460. rect.right = clientRect.Width() - 2;
  461. rect.bottom = clientRect.Height() - 2;
  462. statusBar.MoveWindow( rect.left, rect.top, rect.Width(), rect.Height() );
  463. }
  464. UnlockWindowUpdate();
  465. }
  466. /*
  467. ================
  468. DialogEntityDefEditor::OnSizing
  469. ================
  470. */
  471. void DialogEntityDefEditor::OnSizing( UINT nSide, LPRECT lpRect ) {
  472. /*
  473. 1 = left
  474. 2 = right
  475. 3 = top
  476. 4 = left - top
  477. 5 = right - top
  478. 6 = bottom
  479. 7 = left - bottom
  480. 8 = right - bottom
  481. */
  482. CDialog::OnSizing( nSide, lpRect );
  483. if ( ( nSide - 1 ) % 3 == 0 ) {
  484. if ( lpRect->right - lpRect->left < initialRect.Width() ) {
  485. lpRect->left = lpRect->right - initialRect.Width();
  486. }
  487. } else if ( ( nSide - 2 ) % 3 == 0 ) {
  488. if ( lpRect->right - lpRect->left < initialRect.Width() ) {
  489. lpRect->right = lpRect->left + initialRect.Width();
  490. }
  491. }
  492. if ( nSide >= 3 && nSide <= 5 ) {
  493. if ( lpRect->bottom - lpRect->top < initialRect.Height() ) {
  494. lpRect->top = lpRect->bottom - initialRect.Height();
  495. }
  496. } else if ( nSide >= 6 && nSide <= 9 ) {
  497. if ( lpRect->bottom - lpRect->top < initialRect.Height() ) {
  498. lpRect->bottom = lpRect->top + initialRect.Height();
  499. }
  500. }
  501. }
  502. /*
  503. ================
  504. DialogEntityDefEditor::OnEditChange
  505. ================
  506. */
  507. void DialogEntityDefEditor::OnEditChange( ) {
  508. testButton.EnableWindow( TRUE );
  509. okButton.EnableWindow( TRUE );
  510. }
  511. /*
  512. ================
  513. DialogEntityDefEditor::OnInheritChange
  514. ================
  515. */
  516. void DialogEntityDefEditor::OnInheritChange( ) {
  517. testButton.EnableWindow( TRUE );
  518. okButton.EnableWindow( TRUE );
  519. idStr inherit = "";
  520. int sel = inheritCombo.GetCurSel();
  521. if ( sel == CB_ERR ) {
  522. CString temp;
  523. inheritCombo.GetWindowText( temp );
  524. inherit = temp;
  525. } else {
  526. CString temp;
  527. inheritCombo.GetLBText( sel, temp );
  528. inherit = temp;
  529. }
  530. SetInherit(inherit);
  531. }
  532. /*
  533. ================
  534. DialogEntityDefEditor::OnEnInputEdit
  535. ================
  536. */
  537. void DialogEntityDefEditor::OnEnInputEdit( NMHDR *pNMHDR, LRESULT *pResult ) {
  538. MSGFILTER *msgFilter = (MSGFILTER *)pNMHDR;
  539. if ( msgFilter->msg != 512 && msgFilter->msg != 33 ) {
  540. UpdateStatusBar();
  541. }
  542. *pResult = 0;
  543. }
  544. /*
  545. ================
  546. DialogEntityDefEditor::BuildDeclText
  547. ================
  548. */
  549. void DialogEntityDefEditor::BuildDeclText( idStr &declText )
  550. {
  551. CString declName;
  552. declNameEdit.GetWindowText(declName);
  553. CString inherit;
  554. inheritCombo.GetWindowText(inherit);
  555. CString spawnclass;
  556. spawnclassCombo.GetWindowText(spawnclass);
  557. declText = "entityDef " + declName + "\r{\r";
  558. declText += "\"inherit\"\t\t\t\"" + inherit + "\"\r";
  559. declText += "\"spawnclass\"\t\t\t\"" + spawnclass + "\"\r";
  560. for (int i=0; i<keyValsList.GetCount(); i++) {
  561. CPropertyItem* pItem = (CPropertyItem*)keyValsList.GetItemDataPtr(i);
  562. if (pItem) {
  563. // Items with a * in front are inherited and shouldn't be written out
  564. if (pItem->m_propName[0] == '*') {
  565. break;
  566. }
  567. declText += "\"" + pItem->m_propName + "\"\t\t\t\"" + pItem->m_curValue + "\"\r";
  568. }
  569. }
  570. declText += "}\r";
  571. declText.Replace( "\r", "\r\n" );
  572. declText.Insert( "\r\n\r\n", 0 );
  573. declText.StripTrailing( "\r\n" );
  574. }
  575. /*
  576. ================
  577. DialogEntityDefEditor::OnBnClickedTest
  578. ================
  579. */
  580. void DialogEntityDefEditor::OnBnClickedTest() {
  581. idStr declText, oldDeclText;
  582. if ( decl ) {
  583. BuildDeclText(declText);
  584. if ( !TestDecl( declText ) ) {
  585. return;
  586. }
  587. char *oldDeclText = (char *)_alloca( ( decl->GetTextLength() + 1 ) * sizeof( char ) );
  588. decl->GetText( oldDeclText );
  589. decl->SetText( declText );
  590. decl->Invalidate();
  591. declManager->DeclByIndex( decl->GetType(), decl->Index(), true );
  592. decl->SetText( oldDeclText );
  593. decl->Invalidate();
  594. common->Printf( "tested %s\n", decl->GetName() );
  595. testButton.EnableWindow( FALSE );
  596. }
  597. }
  598. /*
  599. ================
  600. DialogEntityDefEditor::OnBnClickedOk
  601. ================
  602. */
  603. void DialogEntityDefEditor::OnBnClickedOk() {
  604. if ( decl ) {
  605. idStr declText;
  606. BuildDeclText(declText);
  607. if ( !TestDecl( declText ) ) {
  608. return;
  609. }
  610. if ( decl->SourceFileChanged() ) {
  611. if ( MessageBox( va( "Declaration file %s has been modified outside of the editor.\r\nReload declarations and save?", decl->GetFileName() ),
  612. va( "Warning saving: %s", decl->GetFileName() ), MB_OKCANCEL | MB_ICONERROR ) != IDOK ) {
  613. return;
  614. }
  615. declManager->Reload( false );
  616. DeclBrowserReloadDeclarations();
  617. }
  618. decl->SetText( declText );
  619. if ( !decl->ReplaceSourceFileText() ) {
  620. MessageBox( va( "Couldn't save: %s.\r\nMake sure the declaration file is not read-only.", decl->GetFileName() ),
  621. va( "Error saving: %s", decl->GetFileName() ), MB_OK | MB_ICONERROR );
  622. return;
  623. }
  624. decl->Invalidate();
  625. }
  626. okButton.EnableWindow( FALSE );
  627. }
  628. /*
  629. ================
  630. DialogEntityDefEditor::OnBnClickedCancel
  631. ================
  632. */
  633. void DialogEntityDefEditor::OnBnClickedCancel() {
  634. if ( okButton.IsWindowEnabled() ) {
  635. if ( MessageBox( "Cancel changes?", "Cancel", MB_YESNO | MB_ICONQUESTION ) != IDYES ) {
  636. return;
  637. }
  638. }
  639. OnCancel();
  640. }
  641. /*
  642. ================
  643. DialogEntityDefEditor::OnKeyValChange
  644. ================
  645. */
  646. void DialogEntityDefEditor::OnKeyValChange() {
  647. int sel = keyValsList.GetCurSel();
  648. if (sel >= 0) {
  649. CPropertyItem *pItem = (CPropertyItem *)keyValsList.GetItemDataPtr(sel);
  650. keyEdit.SetWindowText(pItem->m_propName);
  651. }
  652. }
  653. /*
  654. ================
  655. DialogEntityDefEditor::OnBnClickedAdd
  656. ================
  657. */
  658. void DialogEntityDefEditor::OnBnClickedAdd() {
  659. CString newKey;
  660. keyEdit.GetWindowText(newKey);
  661. int matchedInherit = -1;
  662. int matchedKey = -1;
  663. // See if this key already exists
  664. for (int i=0; i<keyValsList.GetCount(); i++) {
  665. CPropertyItem* pItem = (CPropertyItem*)keyValsList.GetItemDataPtr(i);
  666. if (pItem) {
  667. // Items with a * in front are inherited and shouldn't be written out
  668. if (pItem->m_propName[0] == '*') {
  669. if (newKey = pItem->m_propName.Mid(1)) {
  670. matchedInherit = i;
  671. }
  672. }
  673. else if (pItem->m_propName == newKey) {
  674. matchedKey = i;
  675. break;
  676. }
  677. }
  678. }
  679. if (matchedKey >= 0) {
  680. MessageBox("Key " + newKey + " already defined");
  681. return;
  682. }
  683. if (matchedInherit >= 0) {
  684. delete keyValsList.GetItemDataPtr(matchedInherit);
  685. keyValsList.DeleteString(matchedInherit);
  686. }
  687. keyValsList.AddPropItem(new CPropertyItem(newKey, "", PIT_EDIT, ""));
  688. }
  689. /*
  690. ================
  691. DialogEntityDefEditor::OnBnClickedDelete
  692. ================
  693. */
  694. void DialogEntityDefEditor::OnBnClickedDelete() {
  695. CString delKey;
  696. keyEdit.GetWindowText(delKey);
  697. int matchedInherit = -1;
  698. int matchedKey = -1;
  699. // See if this key already exists
  700. for (int i=0; i<keyValsList.GetCount(); i++) {
  701. CPropertyItem* pItem = (CPropertyItem*)keyValsList.GetItemDataPtr(i);
  702. if (pItem) {
  703. // Items with a * in front are inherited and shouldn't be written out
  704. if (pItem->m_propName[0] == '*') {
  705. if (delKey = pItem->m_propName.Mid(1)) {
  706. matchedInherit = i;
  707. }
  708. }
  709. else if (pItem->m_propName == delKey) {
  710. matchedKey = i;
  711. break;
  712. }
  713. }
  714. }
  715. if (matchedKey >= 0) {
  716. delete keyValsList.GetItemDataPtr(matchedKey);
  717. keyValsList.DeleteString(matchedKey);
  718. }
  719. else if (matchedInherit) {
  720. MessageBox("Cannot delete an inherited value");
  721. }
  722. }