GEWindowWrapper.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  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/guied_resource.h"
  23. #include "../../renderer/tr_local.h"
  24. #include "../../ui/EditWindow.h"
  25. #include "../../ui/ListWindow.h"
  26. #include "../../ui/BindWindow.h"
  27. #include "../../ui/RenderWindow.h"
  28. #include "../../ui/ChoiceWindow.h"
  29. #include "GEApp.h"
  30. rvGEWindowWrapper::rvGEWindowWrapper( idWindow *window,EWindowType type ) {
  31. assert(window);
  32. mWindow = window;
  33. mFlippedHorz = false;
  34. mFlippedVert = false;
  35. mHidden = false;
  36. mDeleted = false;
  37. mSelected = false;
  38. mType = type;
  39. mExpanded = false;
  40. mOldVisible = false;
  41. mMoveable = true;
  42. if ( dynamic_cast< idEditWindow*>(window) ) {
  43. mType = WT_EDIT;
  44. } else if ( dynamic_cast< idListWindow*>(window) ) {
  45. mType = WT_LIST;
  46. } else if ( dynamic_cast< idBindWindow*>(window) ) {
  47. mType = WT_BIND;
  48. } else if ( dynamic_cast< idRenderWindow*>(window) ) {
  49. mType = WT_RENDER;
  50. } else if ( dynamic_cast< idChoiceWindow*>(window) ) {
  51. mType = WT_CHOICE;
  52. } else {
  53. mType = WT_NORMAL;
  54. }
  55. // Attach the wrapper to the window by adding a defined variable
  56. // with the wrappers pointer stuffed into an integer
  57. idWinInt *var = new idWinInt();
  58. int x = (int)this;
  59. *var = x;
  60. var->SetEval(false);
  61. var->SetName("guied_wrapper");
  62. mWindow->AddDefinedVar(var);
  63. SetStateKey("name", mWindow->GetName(), false);
  64. }
  65. /*
  66. ================
  67. rvGEWindowWrapper::GetWrapper
  68. Static method that returns the window wrapper for the given window class
  69. ================
  70. */
  71. rvGEWindowWrapper * rvGEWindowWrapper::GetWrapper( idWindow *window ) {
  72. idWinInt *var;
  73. var = dynamic_cast< idWinInt*>(window->GetWinVarByName("guied_wrapper"));
  74. return var ? ((rvGEWindowWrapper *) (int) (*var)) : NULL;
  75. }
  76. /*
  77. ================
  78. rvGEWindowWrapper::UpdateRect
  79. Updates the gui editor's representation of the window rectangle from the
  80. windows rectangle
  81. ================
  82. */
  83. void rvGEWindowWrapper::UpdateRect( void ) {
  84. idVec4 rect;
  85. idWinRectangle *winrect;
  86. winrect = dynamic_cast< idWinRectangle*>(mWindow->GetWinVarByName("rect"));
  87. assert(winrect);
  88. rect = winrect->ToVec4();
  89. mFlippedHorz = false;
  90. mFlippedVert = false;
  91. if ( rect[2] < 0 ) {
  92. mFlippedHorz = true;
  93. rect[2] *= -1;
  94. }
  95. if ( rect[3] < 0 ) {
  96. mFlippedVert = true;
  97. rect[3] *= -1;
  98. }
  99. mClientRect = rect;
  100. CalcScreenRect();
  101. const char *rstr = mState.GetString("rect", "0,0,0,0");
  102. mMoveable = !IsExpression(rstr);
  103. }
  104. /*
  105. ================
  106. rvGEWindowWrapper::CalcScreenRect
  107. Calculates the screen rectangle from the client rectangle by running through
  108. the parent windows and adding their offsets
  109. ================
  110. */
  111. void rvGEWindowWrapper::CalcScreenRect( void ) {
  112. idWindow *parent;
  113. mScreenRect = mClientRect;
  114. if ( NULL != (parent = mWindow->GetParent()) ) {
  115. rvGEWindowWrapper *wrapper = GetWrapper(parent);
  116. assert(wrapper);
  117. mScreenRect[0] += wrapper->GetScreenRect()[0];
  118. mScreenRect[1] += wrapper->GetScreenRect()[1];
  119. }
  120. // Since our screen rectangle has changed we need to tell all our our children to update
  121. // their screen rectangles as well.
  122. int i;
  123. int count;
  124. rvGEWindowWrapper *pwrapper;
  125. pwrapper = rvGEWindowWrapper::GetWrapper(mWindow);
  126. for ( count = pwrapper->GetChildCount(), i = 0; i < count; i ++ ) {
  127. rvGEWindowWrapper *wrapper;
  128. wrapper = rvGEWindowWrapper::GetWrapper(pwrapper->GetChild(i));
  129. // Usually we assert if there is no wrapper but since this method is called
  130. // when the wrappers are being attached to the windows there may be no wrappers
  131. // for any of the children.
  132. if ( !wrapper ) {
  133. continue;
  134. }
  135. wrapper->CalcScreenRect();
  136. }
  137. }
  138. /*
  139. ================
  140. rvGEWindowWrapper::SetRect
  141. Sets the wrapper's rectangle and the attached windows rectangle as well
  142. ================
  143. */
  144. void rvGEWindowWrapper::SetRect( idRectangle &rect ) {
  145. const char *s;
  146. mClientRect = rect;
  147. CalcScreenRect();
  148. s = va("%d,%d,%d,%d", (int) (rect.x + 0.5f), (int) (rect.y + 0.5f), (int) ((rect.w + 0.5f) * (mFlippedHorz ? -1 : 1)), (int) ((rect.h + 0.5f) * (mFlippedVert ? -1 : 1)));
  149. mState.Set("rect", s);
  150. UpdateWindowState();
  151. }
  152. /*
  153. ================
  154. rvGEWindowWrapper::SetHidden
  155. Sets the wrappers hidden state
  156. ================
  157. */
  158. void rvGEWindowWrapper::SetHidden( bool h ) {
  159. mHidden = h;
  160. UpdateWindowState();
  161. }
  162. /*
  163. ================
  164. rvGEWindowWrapper::SetDeleted
  165. Sets the deleted state of the wrapper which in turns sets whether or
  166. not the window is visible
  167. ================
  168. */
  169. void rvGEWindowWrapper::SetDeleted( bool del ) {
  170. mDeleted = del;
  171. UpdateWindowState();
  172. }
  173. /*
  174. ================
  175. rvGEWindowWrapper::SetState
  176. Sets the window state from the given dictionary
  177. ================
  178. */
  179. void rvGEWindowWrapper::SetState( const idDict &dict ) {
  180. mState.Clear();
  181. mState.Copy(dict);
  182. // Push the window state to the window itself
  183. UpdateWindowState();
  184. // Update the internal rectangle since it may have changed in the state
  185. UpdateRect();
  186. }
  187. /*
  188. ================
  189. rvGEWindowWrapper::SetStateKey
  190. Sets the given state key and updates the
  191. ================
  192. */
  193. void rvGEWindowWrapper::SetStateKey( const char *key,const char *value,bool update ) {
  194. mState.Set(key, value);
  195. if ( update ) {
  196. UpdateWindowState();
  197. // Make sure the rectangle gets updated if its changing
  198. if ( !idStr::Icmp(key, "rect") ) {
  199. UpdateRect();
  200. }
  201. }
  202. }
  203. /*
  204. ================
  205. rvGEWindowWrapper::DeleteStateKey
  206. Sets the given state key and updates the
  207. ================
  208. */
  209. void rvGEWindowWrapper::DeleteStateKey( const char *key ) {
  210. if ( !idStr::Icmp(key, "rect") || !idStr::Icmp(key, "name") ) {
  211. return;
  212. }
  213. mState.Delete(key);
  214. }
  215. /*
  216. ================
  217. rvGEWindowWrapper::UpdateWindowState
  218. Updates the windows real state with wrappers internal state. Visibility is
  219. handled specially
  220. ================
  221. */
  222. void rvGEWindowWrapper::UpdateWindowState( void ) {
  223. idStr realVisible;
  224. bool tempVisible;
  225. // int i;
  226. realVisible = mState.GetString("visible", "1");
  227. tempVisible = atoi(realVisible) ? true : false;
  228. if ( tempVisible != mOldVisible ) {
  229. mHidden = !tempVisible;
  230. mOldVisible = tempVisible;
  231. }
  232. tempVisible = !mDeleted && !mHidden;
  233. // Temporarily change the visible state so we can hide/unhide the window
  234. mState.Set("visible", tempVisible ? "1" : "0");
  235. mWindow->UpdateFromDictionary(mState);
  236. // Put the visible state back to the real value
  237. mState.Set("visible", realVisible);
  238. }
  239. /*
  240. ================
  241. rvGEWindowWrapper::WindowFromPoint
  242. Returns the topmost window under the given point
  243. ================
  244. */
  245. idWindow * rvGEWindowWrapper::WindowFromPoint( float x,float y,bool visibleOnly ) {
  246. int count;
  247. int i;
  248. rvGEWindowWrapper *pwrapper;
  249. // If the window isnt visible then skip it
  250. if ( visibleOnly && (mHidden || mDeleted) ) {
  251. return NULL;
  252. }
  253. // Now check our children next
  254. pwrapper = GetWrapper(mWindow);
  255. count = pwrapper->GetChildCount();
  256. for ( i = count - 1; i >= 0; i -- ) {
  257. rvGEWindowWrapper *wrapper;
  258. idWindow *child;
  259. child = pwrapper->GetChild(i);
  260. assert(child);
  261. wrapper = rvGEWindowWrapper::GetWrapper(child);
  262. if ( !wrapper ) {
  263. continue;
  264. }
  265. if ( child = wrapper->WindowFromPoint(x, y) ) {
  266. return child;
  267. }
  268. }
  269. // We have to check this last because a child could be out outside of the parents
  270. // rectangle and we still want it selectable.
  271. if ( !mScreenRect.Contains(x, y) ) {
  272. return NULL;
  273. }
  274. return mWindow;
  275. }
  276. /*
  277. ================
  278. rvGEWindowWrapper::StringToWindowType
  279. Converts the given string to a window type
  280. ================
  281. */
  282. rvGEWindowWrapper::EWindowType rvGEWindowWrapper::StringToWindowType( const char *string ) {
  283. if ( !idStr::Icmp(string, "windowDef") ) {
  284. return WT_NORMAL;
  285. } else if ( !idStr::Icmp(string, "editDef") ) {
  286. return WT_EDIT;
  287. } else if ( !idStr::Icmp(string, "choiceDef") ) {
  288. return WT_CHOICE;
  289. } else if ( !idStr::Icmp(string, "sliderDef") ) {
  290. return WT_SLIDER;
  291. } else if ( !idStr::Icmp(string, "bindDef") ) {
  292. return WT_BIND;
  293. } else if ( !idStr::Icmp(string, "listDef") ) {
  294. return WT_LIST;
  295. } else if ( !idStr::Icmp(string, "renderDef") ) {
  296. return WT_RENDER;
  297. } else if ( !idStr::Icmp(string, "htmlDef") ) {
  298. return WT_HTML;
  299. }
  300. return WT_UNKNOWN;
  301. }
  302. /*
  303. ================
  304. rvGEWindowWrapper::WindowTypeToString
  305. Converts the given window type to a string
  306. ================
  307. */
  308. const char * rvGEWindowWrapper::WindowTypeToString( EWindowType type ) {
  309. static const char *typeNames[] = {
  310. "Unknown", "windowDef", "editDef", "htmlDef", "choiceDef", "sliderDef", "bindDef", "listDef", "renderDef"
  311. };
  312. return typeNames[(int) type];
  313. }
  314. /*
  315. ================
  316. rvGEWindowWrapper::GetChildCount
  317. Returns the number of children the window being wrapped has
  318. ================
  319. */
  320. int rvGEWindowWrapper::GetChildCount( void ) {
  321. if ( !CanHaveChildren() ) {
  322. return 0;
  323. }
  324. return mWindow->GetChildCount();
  325. }
  326. /*
  327. ================
  328. rvGEWindowWrapper::EnumChildren
  329. Enumerates over the child windows while properly ignoring any that
  330. are not wrapped.
  331. ================
  332. */
  333. bool rvGEWindowWrapper::EnumChildren( PFNENUMCHILDRENPROC proc,void *data ) {
  334. int count;
  335. int i;
  336. if ( !CanHaveChildren() ) {
  337. return false;
  338. }
  339. for ( count = GetChildCount(), i = 0; i < count; i ++ ) {
  340. if ( !proc(rvGEWindowWrapper::GetWrapper(GetChild(i)), data) ) {
  341. return false;
  342. }
  343. }
  344. return true;
  345. }
  346. /*
  347. ================
  348. rvGEWindowWrapper::CanHaveChildren
  349. Returns true if the window is allowed to have child windows
  350. ================
  351. */
  352. bool rvGEWindowWrapper::CanHaveChildren( void ) {
  353. if ( mType == WT_HTML || mType == WT_LIST ) {
  354. return false;
  355. }
  356. return true;
  357. }
  358. /*
  359. ================
  360. rvGEWindowWrapper::GetDepth
  361. Returns the depth of the wrapped window
  362. ================
  363. */
  364. int rvGEWindowWrapper::GetDepth( void ) {
  365. idWindow *parent;
  366. int depth;
  367. for ( depth = 0, parent = mWindow->GetParent(); parent; parent = parent->GetParent(), depth++ )
  368. ;
  369. return depth;
  370. }
  371. /*
  372. ================
  373. rvGEWindowWrapper::Expand
  374. Expand the window in the navigator and all of its parents too
  375. ================
  376. */
  377. bool rvGEWindowWrapper::Expand( void ) {
  378. bool result;
  379. if ( mWindow->GetParent() ) {
  380. result = rvGEWindowWrapper::GetWrapper(mWindow->GetParent())->Expand();
  381. } else {
  382. result = false;
  383. }
  384. if ( mExpanded || !CanHaveChildren() || !GetChildCount() ) {
  385. return result;
  386. }
  387. mExpanded = true;
  388. return true;
  389. }
  390. /*
  391. ================
  392. rvGEWindowWrapper::Collapse
  393. Returns the depth of the wrapped window
  394. ================
  395. */
  396. bool rvGEWindowWrapper::Collapse( void ) {
  397. bool result;
  398. if ( mWindow->GetParent() ) {
  399. result = rvGEWindowWrapper::GetWrapper(mWindow->GetParent())->Expand();
  400. } else {
  401. result = false;
  402. }
  403. if ( !mExpanded ) {
  404. return result;
  405. }
  406. mExpanded = false;
  407. return true;
  408. }
  409. /*
  410. ================
  411. rvGEWindowWrapper::Finish
  412. After a the windwo wrapper is attached to a window and the window is parsed
  413. the finish method is called to finish up any last details
  414. ================
  415. */
  416. void rvGEWindowWrapper::Finish( void ) {
  417. mOldVisible = ((bool) * dynamic_cast< idWinBool*>(mWindow->GetWinVarByName("visible")));
  418. mHidden = mOldVisible ? false : true;
  419. UpdateRect();
  420. }
  421. /*
  422. ================
  423. rvGEWindowWrapper::Finish
  424. After a the windwo wrapper is attached to a window and the window is parsed
  425. the finish method is called to finish up any last details
  426. ================
  427. */
  428. bool rvGEWindowWrapper::VerfiyStateKey( const char *name,const char *value,idStr *result ) {
  429. idStr old;
  430. bool failed;
  431. idParser src(value, strlen(value), "", LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT);
  432. // Save the current value
  433. old = mState.GetString(name);
  434. failed = false;
  435. // Try to parse in the value
  436. try {
  437. if ( !mWindow->ParseInternalVar(name, &src) ) {
  438. // Kill the old register since the parse reg entry will add a new one
  439. if ( !mWindow->ParseRegEntry(name, &src) ) {
  440. failed = true;
  441. }
  442. }
  443. } catch ( idException &) {
  444. failed = true;
  445. }
  446. // Restore the old value
  447. idParser src2(old, old.Length(), "", LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT);
  448. if ( !mWindow->ParseInternalVar(name, &src2) ) {
  449. if ( !mWindow->ParseRegEntry(name, &src2) ) {
  450. }
  451. }
  452. // Check to see if the old value matches the new value
  453. idStr before;
  454. idStr after;
  455. before = value;
  456. before.StripTrailingWhitespace();
  457. src.GetStringFromMarker(after);
  458. after.StripTrailingWhitespace();
  459. if ( result ) {
  460. *result = after;
  461. }
  462. if ( failed || before.Cmp(after) ) {
  463. return false;
  464. }
  465. return true;
  466. }