textwindow.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program 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. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Combat *
  23. * *
  24. * $Archive:: /Commando/Code/Combat/textwindow.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 11/06/01 11:05a $*
  29. * *
  30. * $Revision:: 19 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "textwindow.h"
  36. #include "render2dsentence.h"
  37. #include "assetmgr.h"
  38. #include "texture.h"
  39. #include "font3d.h"
  40. #include "objectives.h"
  41. #include "translatedb.h"
  42. #include "wwaudio.h"
  43. #include "globalsettings.h"
  44. #include "scene.h"
  45. #include "rendobj.h"
  46. #include "stylemgr.h"
  47. ////////////////////////////////////////////////////////////////
  48. // Static member initialization
  49. ////////////////////////////////////////////////////////////////
  50. SceneClass *TextWindowClass::Scene = NULL;
  51. ////////////////////////////////////////////////////////////////
  52. // Local constants
  53. ////////////////////////////////////////////////////////////////
  54. static const char * FONT_NAME = "Arial MT";
  55. ////////////////////////////////////////////////////////////////
  56. //
  57. // TextWindowClass
  58. //
  59. ////////////////////////////////////////////////////////////////
  60. TextWindowClass::TextWindowClass (void) :
  61. FirstLineIndex (0),
  62. CurrentDisplayCount (0),
  63. IsDisplayed (false),
  64. AreColumnsDisplayed (false),
  65. IsViewDirty (true),
  66. TextRect (0, 0, 0, 0),
  67. ColumnHeight (0),
  68. LineSpacing (0)
  69. {
  70. TextRenderers[0] = NULL;
  71. TextRenderers[1] = NULL;
  72. return ;
  73. }
  74. ////////////////////////////////////////////////////////////////
  75. //
  76. // ~TextWindowClass
  77. //
  78. ////////////////////////////////////////////////////////////////
  79. TextWindowClass::~TextWindowClass (void)
  80. {
  81. Free_Backdrop ();
  82. Free_Contents ();
  83. return ;
  84. }
  85. ////////////////////////////////////////////////////////////////
  86. //
  87. // Initialize
  88. //
  89. ////////////////////////////////////////////////////////////////
  90. void
  91. TextWindowClass::Initialize (SceneClass *scene)
  92. {
  93. REF_PTR_SET (Scene, scene);
  94. return ;
  95. }
  96. ////////////////////////////////////////////////////////////////
  97. //
  98. // Shutdown
  99. //
  100. ////////////////////////////////////////////////////////////////
  101. void
  102. TextWindowClass::Shutdown (void)
  103. {
  104. REF_PTR_RELEASE (Scene);
  105. return ;
  106. }
  107. ////////////////////////////////////////////////////////////////
  108. //
  109. // Free_Backdrop
  110. //
  111. ////////////////////////////////////////////////////////////////
  112. void
  113. TextWindowClass::Free_Backdrop (void)
  114. {
  115. //
  116. // Reset the rest of the data that is dependent on the backdrop
  117. //
  118. FirstLineIndex = 0;
  119. IsDisplayed = false;
  120. return ;
  121. }
  122. ////////////////////////////////////////////////////////////////
  123. //
  124. // Free_Contents
  125. //
  126. ////////////////////////////////////////////////////////////////
  127. void
  128. TextWindowClass::Free_Contents (void)
  129. {
  130. //
  131. // Free each row of renderer's
  132. //
  133. Delete_All_Columns ();
  134. Free_Renderers ();
  135. //
  136. // Reset the rest of the data that is dependent on the contents
  137. //
  138. FirstLineIndex = 0;
  139. IsDisplayed = false;
  140. return ;
  141. }
  142. ////////////////////////////////////////////////////////////////
  143. //
  144. // Free_Renderers
  145. //
  146. ////////////////////////////////////////////////////////////////
  147. void
  148. TextWindowClass::Free_Renderers (void)
  149. {
  150. //
  151. // Free each text renderer object
  152. //
  153. delete TextRenderers[0];
  154. delete TextRenderers[1];
  155. TextRenderers[0] = NULL;
  156. TextRenderers[1] = NULL;
  157. return ;
  158. }
  159. ////////////////////////////////////////////////////////////////
  160. //
  161. // Set_Backdrop
  162. //
  163. ////////////////////////////////////////////////////////////////
  164. void
  165. TextWindowClass::Set_Backdrop
  166. (
  167. const char * texture_name,
  168. const RectClass & screen_rect,
  169. const Vector2 & texture_size,
  170. const RectClass & endcap_rect,
  171. const RectClass & fadeout_rect,
  172. const RectClass & textback_rect
  173. )
  174. {
  175. Free_Backdrop ();
  176. //
  177. // Load the backdrop texture
  178. //
  179. TextureClass *texture = WW3DAssetManager::Get_Instance()->Get_Texture (texture_name, TextureClass::MIP_LEVELS_1);
  180. if (texture != NULL) {
  181. //
  182. // Pass the texture onto the renderer
  183. //
  184. Backdrop.Reset ();
  185. Backdrop.Set_Texture (texture);
  186. //
  187. // Configure the renderer
  188. //
  189. Backdrop.Set_Coordinate_Range (Render2DClass::Get_Screen_Resolution ());
  190. //
  191. // Calculate the width and height of the sections
  192. //
  193. int endcap_width = endcap_rect.Width ();
  194. int fadeout_width = fadeout_rect.Width ();
  195. int textback_width = screen_rect.Width () - ((endcap_width + fadeout_width) * 2);
  196. int endcap_height = endcap_rect.Height ();
  197. int fadeout_height = fadeout_rect.Height ();
  198. int textback_height = textback_rect.Height ();
  199. //
  200. // Calculate the UV coordinates for each section
  201. //
  202. RectClass endcap_uvs1 (endcap_rect);
  203. RectClass endcap_uvs2 (endcap_rect);
  204. RectClass fadeout_uvs1 (fadeout_rect);
  205. RectClass fadeout_uvs2 (fadeout_rect);
  206. RectClass textback_uvs (textback_rect);
  207. endcap_uvs1.Inverse_Scale (texture_size);
  208. endcap_uvs2.Inverse_Scale (texture_size);
  209. fadeout_uvs1.Inverse_Scale (texture_size);
  210. fadeout_uvs2.Inverse_Scale (texture_size);
  211. textback_uvs.Inverse_Scale (texture_size);
  212. //
  213. // Reverse the UVs of the endcap and fadeaways on the right
  214. //
  215. float temp_float = endcap_uvs2.Left;
  216. endcap_uvs2.Left = endcap_uvs2.Right;
  217. endcap_uvs2.Right = temp_float;
  218. temp_float = fadeout_uvs2.Left;
  219. fadeout_uvs2.Left = fadeout_uvs2.Right;
  220. fadeout_uvs2.Right = temp_float;
  221. //
  222. // Calculate the screen rectangle (in pixels) for each of the sections
  223. //
  224. RectClass endcap_screen_rect1 (0, 0, endcap_width, endcap_height);
  225. RectClass fadeout_screen_rect1 (0, 0, fadeout_width, fadeout_height);
  226. RectClass textback_screen_rect (0, 0, textback_width, textback_height);
  227. RectClass fadeout_screen_rect2 (0, 0, fadeout_width, fadeout_height);
  228. RectClass endcap_screen_rect2 (0, 0, endcap_width, endcap_height);
  229. endcap_screen_rect1 += screen_rect.Upper_Left ();
  230. fadeout_screen_rect1 += endcap_screen_rect1.Upper_Right ();
  231. textback_screen_rect += fadeout_screen_rect1.Upper_Right ();
  232. fadeout_screen_rect2 += textback_screen_rect.Upper_Right ();
  233. endcap_screen_rect2 += fadeout_screen_rect2.Upper_Right ();
  234. //
  235. // Determine what area we have to draw the text into
  236. //
  237. const float border_size = 10.0F;
  238. TextRect = textback_screen_rect;
  239. TextRect.Inflate (Vector2 (-border_size, -border_size));
  240. //
  241. // Calculate how many times we should vertically tile the text backdrop
  242. //
  243. int largest_height = min (endcap_height, fadeout_height);
  244. largest_height = min (largest_height, textback_height);
  245. int section_count = (screen_rect.Height () / largest_height);
  246. //
  247. // Tile the text backdrop sections
  248. //
  249. for (int index = 0; index < section_count; index ++) {
  250. //
  251. // Submit the geometry
  252. //
  253. Backdrop.Add_Quad (fadeout_screen_rect1, fadeout_uvs1);
  254. Backdrop.Add_Quad (fadeout_screen_rect2, fadeout_uvs2);
  255. Backdrop.Add_Quad (textback_screen_rect, textback_uvs);
  256. fadeout_screen_rect1 += Vector2 (0, fadeout_height);
  257. fadeout_screen_rect2 += Vector2 (0, fadeout_height);
  258. textback_screen_rect += Vector2 (0, textback_height);
  259. }
  260. //
  261. // Add a chopped off section of an endcap onto the end (if necessary)
  262. //
  263. float percent = (screen_rect.Height () / largest_height) - section_count;
  264. if (percent > 0) {
  265. textback_uvs.Bottom = textback_uvs.Top + (textback_uvs.Height () * percent);
  266. fadeout_uvs1.Bottom = fadeout_uvs1.Top + (fadeout_uvs1.Height () * percent);
  267. fadeout_uvs2.Bottom = fadeout_uvs2.Top + (fadeout_uvs2.Height () * percent);
  268. textback_screen_rect.Bottom = textback_screen_rect.Top + (textback_screen_rect.Height () * percent);
  269. fadeout_screen_rect1.Bottom = fadeout_screen_rect1.Top + (fadeout_screen_rect1.Height () * percent);
  270. fadeout_screen_rect2.Bottom = fadeout_screen_rect2.Top + (fadeout_screen_rect2.Height () * percent);
  271. //
  272. // Submit the geometry
  273. //
  274. Backdrop.Add_Quad (fadeout_screen_rect1, fadeout_uvs1);
  275. Backdrop.Add_Quad (fadeout_screen_rect2, fadeout_uvs2);
  276. Backdrop.Add_Quad (textback_screen_rect, textback_uvs);
  277. }
  278. //
  279. // Tile the endcaps appropriately
  280. //
  281. section_count = screen_rect.Height () / endcap_height;
  282. for (index = 0; index < section_count; index ++) {
  283. //
  284. // Submit the geometry
  285. //
  286. Backdrop.Add_Quad (endcap_screen_rect1, endcap_uvs1);
  287. Backdrop.Add_Quad (endcap_screen_rect2, endcap_uvs2);
  288. endcap_screen_rect1 += Vector2 (0, endcap_height);
  289. endcap_screen_rect2 += Vector2 (0, endcap_height);
  290. }
  291. //
  292. // Add a chopped off section of an endcap onto the end (if necessary)
  293. //
  294. percent = (screen_rect.Height () / endcap_height) - section_count;
  295. if (percent > 0) {
  296. endcap_uvs1.Bottom = endcap_uvs1.Top + (endcap_uvs1.Height () * percent);
  297. endcap_uvs2.Bottom = endcap_uvs2.Top + (endcap_uvs2.Height () * percent);
  298. endcap_screen_rect1.Bottom = endcap_screen_rect1.Top + (endcap_screen_rect1.Height () * percent);
  299. endcap_screen_rect2.Bottom = endcap_screen_rect2.Top + (endcap_screen_rect2.Height () * percent);
  300. //
  301. // Submit the geometry
  302. //
  303. Backdrop.Add_Quad (endcap_screen_rect1, endcap_uvs1);
  304. Backdrop.Add_Quad (endcap_screen_rect2, endcap_uvs2);
  305. }
  306. //
  307. // Release our hold on the texture
  308. //
  309. REF_PTR_RELEASE(texture);
  310. }
  311. return ;
  312. }
  313. ////////////////////////////////////////////////////////////////
  314. //
  315. // On_Frame_Update
  316. //
  317. ////////////////////////////////////////////////////////////////
  318. void
  319. TextWindowClass::On_Frame_Update (void)
  320. {
  321. return ;
  322. }
  323. ////////////////////////////////////////////////////////////////
  324. //
  325. // Add_Column
  326. //
  327. ////////////////////////////////////////////////////////////////
  328. void
  329. TextWindowClass::Add_Column (const WCHAR *column_name, float width, const Vector3 &color)
  330. {
  331. //
  332. // Create a new column and add it to the list
  333. //
  334. TextColumnClass *column = new TextColumnClass;
  335. column->Set_Name (column_name);
  336. column->Set_Width (width);
  337. column->Set_Color (color);
  338. Columns.Add (column);
  339. IsViewDirty = true;
  340. return ;
  341. }
  342. ////////////////////////////////////////////////////////////////
  343. //
  344. // Remove_Column
  345. //
  346. ////////////////////////////////////////////////////////////////
  347. bool
  348. TextWindowClass::Remove_Column (int index)
  349. {
  350. if (index < 0 || index >= Columns.Count ()) {
  351. return false;
  352. }
  353. //
  354. // Free the column
  355. //
  356. TextColumnClass *column = Columns[index];
  357. delete column;
  358. //
  359. // Remove the column from the list
  360. //
  361. Columns.Delete (index);
  362. IsViewDirty = true;
  363. return true;
  364. }
  365. ////////////////////////////////////////////////////////////////
  366. //
  367. // Delete_All_Columns
  368. //
  369. ////////////////////////////////////////////////////////////////
  370. void
  371. TextWindowClass::Delete_All_Columns (void)
  372. {
  373. for (int index = 0; index < Columns.Count (); index ++) {
  374. TextColumnClass *column = Columns[index];
  375. delete column;
  376. }
  377. Columns.Delete_All ();
  378. IsViewDirty = true;
  379. return ;
  380. }
  381. ////////////////////////////////////////////////////////////////
  382. //
  383. // Get_Item_Count
  384. //
  385. ////////////////////////////////////////////////////////////////
  386. int
  387. TextWindowClass::Get_Item_Count (void) const
  388. {
  389. return Columns[0]->Get_Item_Count ();
  390. }
  391. ////////////////////////////////////////////////////////////////
  392. //
  393. // Get_Display_Count
  394. //
  395. ////////////////////////////////////////////////////////////////
  396. int
  397. TextWindowClass::Get_Display_Count (void)
  398. {
  399. if (IsViewDirty) {
  400. Update_View ();
  401. }
  402. return CurrentDisplayCount;
  403. }
  404. ////////////////////////////////////////////////////////////////
  405. //
  406. // Delete_Item
  407. //
  408. ////////////////////////////////////////////////////////////////
  409. bool
  410. TextWindowClass::Delete_Item (int index)
  411. {
  412. bool retval = true;
  413. for (int col_index = 0; col_index < Columns.Count (); col_index ++) {
  414. retval &= Columns[col_index]->Delete_Item (index);
  415. }
  416. IsViewDirty = true;
  417. return retval;
  418. }
  419. ////////////////////////////////////////////////////////////////
  420. //
  421. // Insert_Item
  422. //
  423. ////////////////////////////////////////////////////////////////
  424. int
  425. TextWindowClass::Insert_Item (int index, const WCHAR *text)
  426. {
  427. if (Columns.Count () <= 0) {
  428. return -1;
  429. }
  430. //
  431. // Insert a new entry in the first column with the given text
  432. //
  433. index = Columns[0]->Insert_Item (index, text);
  434. //
  435. // Add blank entries to all the other columns
  436. //
  437. for (int col_index = 1; col_index < Columns.Count (); col_index ++) {
  438. TextColumnClass *column = Columns[col_index];
  439. column->Insert_Item (index, L"");
  440. }
  441. IsViewDirty = true;
  442. return index;
  443. }
  444. ////////////////////////////////////////////////////////////////
  445. //
  446. // Set_Item_Text
  447. //
  448. ////////////////////////////////////////////////////////////////
  449. bool
  450. TextWindowClass::Set_Item_Text (int index, int col_index, const WCHAR *text)
  451. {
  452. if (col_index < 0 || col_index >= Columns.Count ()) {
  453. return false;
  454. }
  455. //
  456. // Change the text entry in this cell
  457. //
  458. Columns[col_index]->Set_Item_Text (index, text);
  459. IsViewDirty = true;
  460. return true;
  461. }
  462. ////////////////////////////////////////////////////////////////
  463. //
  464. // Set_Item_Color
  465. //
  466. ////////////////////////////////////////////////////////////////
  467. bool
  468. TextWindowClass::Set_Item_Color (int index, int col_index, const Vector3 &color)
  469. {
  470. if (col_index < 0 || col_index >= Columns.Count ()) {
  471. return false;
  472. }
  473. //
  474. // Change the color for the item in this cell
  475. //
  476. Columns[col_index]->Set_Item_Color (index, color);
  477. IsViewDirty = true;
  478. return true;
  479. }
  480. ////////////////////////////////////////////////////////////////
  481. //
  482. // Set_Item_Data
  483. //
  484. ////////////////////////////////////////////////////////////////
  485. bool
  486. TextWindowClass::Set_Item_Data (int index, uint32 user_data)
  487. {
  488. //
  489. // Store the user data in the first column
  490. //
  491. Columns[0]->Set_Item_Data (index, user_data);
  492. return true;
  493. }
  494. ////////////////////////////////////////////////////////////////
  495. //
  496. // Get_Item_Data
  497. //
  498. ////////////////////////////////////////////////////////////////
  499. uint32
  500. TextWindowClass::Get_Item_Data (int index)
  501. {
  502. //
  503. // Lookup the user data (its stored in the first column)
  504. //
  505. return Columns[0]->Get_Item_Data (index);
  506. }
  507. ////////////////////////////////////////////////////////////////
  508. //
  509. // Delete_All_Items
  510. //
  511. ////////////////////////////////////////////////////////////////
  512. void
  513. TextWindowClass::Delete_All_Items (void)
  514. {
  515. for (int index = 0; index < Columns.Count (); index ++) {
  516. Columns[index]->Delete_All_Items ();
  517. }
  518. IsViewDirty = true;
  519. return ;
  520. }
  521. ////////////////////////////////////////////////////////////////
  522. //
  523. // Build_View
  524. //
  525. ////////////////////////////////////////////////////////////////
  526. void
  527. TextWindowClass::Build_View (void)
  528. {
  529. //
  530. // Start fresh
  531. //
  532. Free_Renderers ();
  533. //const RectClass &screen_rect = Render2DClass::Get_Screen_Resolution ();
  534. //
  535. // Create the fonts
  536. //
  537. FontCharsClass *header_font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_HEADER_TXT );
  538. FontCharsClass *font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_TXT );
  539. //
  540. // Load the font we'll use for the column headers
  541. //
  542. if (header_font != NULL) {
  543. ColumnHeight = (header_font->Get_Char_Height () * 1.5F);
  544. }
  545. //
  546. // Create the header and body text renderers
  547. //
  548. TextRenderers[0] = new Render2DSentenceClass;
  549. TextRenderers[1] = new Render2DSentenceClass;
  550. TextRenderers[0]->Set_Font (header_font);
  551. TextRenderers[1]->Set_Font (font);
  552. return ;
  553. }
  554. ////////////////////////////////////////////////////////////////
  555. //
  556. // Update_View
  557. //
  558. ////////////////////////////////////////////////////////////////
  559. void
  560. TextWindowClass::Update_View (float *total_height, bool info_only)
  561. {
  562. //
  563. // Ensure the view has been created before we try to update it
  564. //
  565. if (TextRenderers[0] == NULL || TextRenderers[1] == NULL) {
  566. Build_View ();
  567. }
  568. TextRenderers[0]->Reset ();
  569. TextRenderers[1]->Reset ();
  570. //
  571. // Update the column headers
  572. //
  573. if (AreColumnsDisplayed) {
  574. float x_pos = TextRect.Left;
  575. for (int col_index = 0; col_index < Columns.Count (); col_index ++) {
  576. const Vector3 &color = Columns[col_index]->Get_Color ();
  577. TextRenderers[0]->Build_Sentence (Columns[col_index]->Get_Name ());
  578. TextRenderers[0]->Set_Location (Vector2 (x_pos, TextRect.Top));
  579. TextRenderers[0]->Draw_Sentence (VRGB_TO_INT32(color));
  580. x_pos += Columns[col_index]->Get_Width () * (TextRect.Right - TextRect.Left);
  581. }
  582. }
  583. //
  584. // Move past the column headers
  585. //
  586. float y_pos = TextRect.Top;
  587. if (AreColumnsDisplayed) {
  588. y_pos += ColumnHeight;
  589. }
  590. //
  591. // Update the contents
  592. //
  593. CurrentDisplayCount = 0;
  594. int item_count = Columns[0]->Get_Item_Count ();
  595. for (int item_index = FirstLineIndex; item_index < item_count; item_index ++) {
  596. //
  597. // Update this row of information
  598. //
  599. float row_height = 0;
  600. Update_Row (item_index, y_pos, &row_height);
  601. CurrentDisplayCount ++;
  602. //
  603. // Check to see if we've gone outside the client area of the text window
  604. //
  605. if ((y_pos + row_height) > TextRect.Right && info_only == false) {
  606. break;
  607. }
  608. //
  609. // Move down one row
  610. //
  611. y_pos += int(row_height + LineSpacing);
  612. }
  613. if (info_only == false) {
  614. IsViewDirty = false;
  615. }
  616. //
  617. // Return the height to the caller (if necessary)
  618. //
  619. if (total_height != NULL) {
  620. (*total_height) = (y_pos - TextRect.Top);
  621. }
  622. return ;
  623. }
  624. ////////////////////////////////////////////////////////////////
  625. //
  626. // Get_Total_Display_Height
  627. //
  628. ////////////////////////////////////////////////////////////////
  629. float
  630. TextWindowClass::Get_Total_Display_Height (void)
  631. {
  632. float total_height = 0;
  633. Update_View (&total_height, true);
  634. return total_height;
  635. }
  636. ////////////////////////////////////////////////////////////////
  637. //
  638. // Update_Row
  639. //
  640. ////////////////////////////////////////////////////////////////
  641. void
  642. TextWindowClass::Update_Row
  643. (
  644. int item_index,
  645. float y_pos,
  646. float * row_height
  647. )
  648. {
  649. float x_pos = int (TextRect.Left);
  650. //
  651. // Loop over all the columns
  652. //
  653. for (int col_index = 0; col_index < Columns.Count (); col_index ++) {
  654. //
  655. // Alias some variables for readability
  656. //
  657. TextColumnClass *column = Columns[col_index];
  658. //
  659. // Determine what text we should display
  660. //
  661. const WCHAR *text = L"";
  662. Vector3 color (0 ,0, 0);
  663. text = column->Get_Item_Text (item_index);
  664. color = column->Get_Item_Color (item_index);
  665. //
  666. // Determine how wide the column should be
  667. //
  668. float col_width = column->Get_Width () * (TextRect.Right - TextRect.Left);
  669. if (col_index + 1 >= Columns.Count ()) {
  670. col_width = TextRect.Right - x_pos;
  671. }
  672. TextRenderers[1]->Set_Wrapping_Width (col_width - 5);
  673. //
  674. // Update the text and color of this renderer
  675. //
  676. TextRenderers[1]->Build_Sentence (text);
  677. TextRenderers[1]->Set_Location (Vector2 (int(x_pos), int(y_pos)));
  678. TextRenderers[1]->Draw_Sentence (VRGB_TO_INT32(color));
  679. //
  680. // See if this is the 'tallest' column so far
  681. //
  682. RectClass extents = TextRenderers[1]->Get_Draw_Extents ();
  683. (*row_height) = max ((*row_height), extents.Height ());
  684. //
  685. // Move to the next column
  686. //
  687. x_pos += int (column->Get_Width () * (TextRect.Right - TextRect.Left));
  688. }
  689. return ;
  690. }
  691. ////////////////////////////////////////////////////////////////
  692. //
  693. // Display
  694. //
  695. ////////////////////////////////////////////////////////////////
  696. void
  697. TextWindowClass::Display (bool onoff)
  698. {
  699. if (onoff != IsDisplayed) {
  700. FirstLineIndex = 0;
  701. CurrentDisplayCount = 0;
  702. IsDisplayed = onoff;
  703. IsViewDirty = onoff;
  704. Backdrop.Set_Hidden (!onoff);
  705. }
  706. return ;
  707. }
  708. ////////////////////////////////////////////////////////////////
  709. //
  710. // Page_Down
  711. //
  712. ////////////////////////////////////////////////////////////////
  713. void
  714. TextWindowClass::Page_Down (void)
  715. {
  716. FirstLineIndex += CurrentDisplayCount;
  717. Update_View ();
  718. return ;
  719. }
  720. ////////////////////////////////////////////////////////////////
  721. //
  722. // Page_Up
  723. //
  724. ////////////////////////////////////////////////////////////////
  725. void
  726. TextWindowClass::Page_Up (void)
  727. {
  728. FirstLineIndex -= CurrentDisplayCount;
  729. FirstLineIndex = max (0, FirstLineIndex);
  730. Update_View ();
  731. return ;
  732. }
  733. ////////////////////////////////////////////////////////////////
  734. //
  735. // Scroll_To_Top
  736. //
  737. ////////////////////////////////////////////////////////////////
  738. void
  739. TextWindowClass::Scroll_To_Top (void)
  740. {
  741. FirstLineIndex = 0;
  742. Update_View ();
  743. return ;
  744. }
  745. ////////////////////////////////////////////////////////////////
  746. //
  747. // Render
  748. //
  749. ////////////////////////////////////////////////////////////////
  750. void
  751. TextWindowClass::Render (void)
  752. {
  753. if (IsDisplayed == false) {
  754. return ;
  755. }
  756. if (IsViewDirty || TextRenderers[0] == NULL) {
  757. Update_View ();
  758. }
  759. //
  760. // Render the backdrop
  761. //
  762. Backdrop.Render ();
  763. //
  764. // Render each piece of text
  765. //
  766. TextRenderers[0]->Render();
  767. TextRenderers[1]->Render();
  768. return ;
  769. }
  770. //********************************************************************************//
  771. //
  772. // Start of TextColumnClass
  773. //
  774. //********************************************************************************//
  775. ////////////////////////////////////////////////////////////////
  776. //
  777. // Free_Data
  778. //
  779. ////////////////////////////////////////////////////////////////
  780. void
  781. TextColumnClass::Free_Data (void)
  782. {
  783. Delete_All_Items ();
  784. return ;
  785. }
  786. ////////////////////////////////////////////////////////////////
  787. //
  788. // Reset_Contents
  789. //
  790. ////////////////////////////////////////////////////////////////
  791. void
  792. TextColumnClass::Reset_Contents (void)
  793. {
  794. //
  795. // Remove all the entries
  796. //
  797. Free_Data ();
  798. return ;
  799. }
  800. ////////////////////////////////////////////////////////////////
  801. //
  802. // Insert_Item
  803. //
  804. ////////////////////////////////////////////////////////////////
  805. int
  806. TextColumnClass::Insert_Item (int index, const WCHAR *item_name)
  807. {
  808. TextItemClass *item = new TextItemClass (item_name);
  809. //
  810. // Should we insert this item in the list or add it to the end?
  811. //
  812. if (index < Items.Count ()) {
  813. Items.Insert (index + 1, item);
  814. } else {
  815. Items.Add (item);
  816. index = (Items.Count () - 1);
  817. }
  818. return index;
  819. }
  820. ////////////////////////////////////////////////////////////////
  821. //
  822. // Delete_Item
  823. //
  824. ////////////////////////////////////////////////////////////////
  825. bool
  826. TextColumnClass::Delete_Item (int index)
  827. {
  828. bool retval = false;
  829. //
  830. // Delete the item if we can find it in our list
  831. //
  832. if (index >= 0 && index < Items.Count ()) {
  833. delete Items[index];
  834. Items.Delete (index);
  835. }
  836. return retval;
  837. }
  838. ////////////////////////////////////////////////////////////////
  839. //
  840. // Delete_All_Items
  841. //
  842. ////////////////////////////////////////////////////////////////
  843. void
  844. TextColumnClass::Delete_All_Items (void)
  845. {
  846. //
  847. // Free each of the items in the list
  848. //
  849. for (int index = 0; index < Items.Count (); index ++) {
  850. delete Items[index];
  851. }
  852. Items.Reset_Active();
  853. return ;
  854. }