MaterialTreeView.cpp 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927
  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 "MaterialTreeView.h"
  23. #define IMAGE_FOLDER 0
  24. #define IMAGE_FILE 1
  25. #define IMAGE_MATERIAL 2
  26. #define IMAGE_MATERIAL_FOLDER 3
  27. #define IMAGE_FILE_MOD 4
  28. #define IMAGE_MATERIAL_MOD 5
  29. #define IMAGE_MATERIAL_MOD_APPLY 6
  30. #define HOVER_EXPAND_DELAY 500
  31. #define MSG_RENAME_FOLDER_COMPLETE (WM_USER + 1000)
  32. #define MSG_RENAME_MATERIAL_COMPLETE (WM_USER + 1001)
  33. IMPLEMENT_DYNCREATE(MaterialTreeView, CTreeView)
  34. BEGIN_MESSAGE_MAP(MaterialTreeView, CTreeView)
  35. ON_WM_CREATE()
  36. ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnTvnSelchanged)
  37. ON_NOTIFY_REFLECT(TVN_BEGINLABELEDIT, OnTvnBeginlabeledit)
  38. ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnTvnEndlabeledit)
  39. ON_WM_CONTEXTMENU()
  40. ON_NOTIFY_REFLECT(NM_RCLICK, OnNMRclick)
  41. ON_WM_CHAR()
  42. ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnTvnBegindrag)
  43. ON_WM_MOUSEMOVE()
  44. ON_WM_LBUTTONUP()
  45. ON_COMMAND(ID_POPUP_APPLYMATERIAL, OnApplyMaterial)
  46. ON_COMMAND(ID_POPUP_APPLYFILE, OnApplyFile)
  47. ON_COMMAND(ID_POPUP_APPLYALL, OnApplyAll)
  48. ON_COMMAND(ID_POPUP_SAVEMATERIAL, OnSaveMaterial)
  49. ON_COMMAND(ID_POPUP_SAVEFILE, OnSaveFile)
  50. ON_COMMAND(ID_POPUP_SAVEALL, OnSaveAll)
  51. ON_COMMAND(ID_POPUP_RENAMEMATERIAL, OnRenameMaterial)
  52. ON_COMMAND(ID_POPUP_ADDMATERIAL, OnAddMaterial)
  53. ON_COMMAND(ID_POPUP_ADDFOLDER, OnAddFolder)
  54. ON_COMMAND(ID_POPUP_DELETEMATERIAL, OnDeleteMaterial)
  55. ON_COMMAND(ID_POPUP_RELOADFILE, OnReloadFile)
  56. ON_COMMAND(ID_POPUP_CUT, OnCut)
  57. ON_COMMAND(ID_POPUP_COPY, OnCopy)
  58. ON_COMMAND(ID_POPUP_PASTE, OnPaste)
  59. ON_MESSAGE(MSG_RENAME_FOLDER_COMPLETE, OnRenameFolderComplete)
  60. ON_MESSAGE(MSG_RENAME_MATERIAL_COMPLETE, OnRenameMaterialComplete)
  61. END_MESSAGE_MAP()
  62. /**
  63. * Constructor for MaterialTreeView
  64. */
  65. MaterialTreeView::MaterialTreeView() {
  66. treeWithFile = false;
  67. bDragging = false;
  68. hoverItem = NULL;
  69. internalChange = false;
  70. }
  71. /**
  72. * Destructor for MaterialTreeView
  73. */
  74. MaterialTreeView::~MaterialTreeView() {
  75. }
  76. /**
  77. * Clears the tree and rebuilds it.
  78. * @param includeFile Should the list include the filename
  79. * @param filename The file to load or NULL to load all files.
  80. */
  81. void MaterialTreeView::InitializeMaterialList(bool includeFile, const char* filename) {
  82. treeWithFile = includeFile;
  83. CTreeCtrl& tree = GetTreeCtrl();
  84. tree.DeleteAllItems();
  85. quickTree.Clear();
  86. materialToTree.Clear();
  87. fileToTree.Clear();
  88. BuildMaterialList(includeFile, filename);
  89. }
  90. /**
  91. * Builds the tree of materials.
  92. * @param includeFile Should the list include the filename
  93. * @param filename The file to load or NULL to load all files.
  94. */
  95. void MaterialTreeView::BuildMaterialList(bool includeFile, const char* filename) {
  96. CTreeCtrl& tree = GetTreeCtrl();
  97. idStrList list(1024);
  98. int count = declManager->GetNumDecls( DECL_MATERIAL );
  99. if (count > 0) {
  100. for (int i = 0; i < count; i++) {
  101. const idMaterial *mat = declManager->MaterialByIndex(i, false);
  102. if(filename && strcmp(filename, mat->GetFileName())) {
  103. continue;
  104. }
  105. idStr temp;
  106. //Do Not Include Implicit File Definitions
  107. idStr filename = mat->GetFileName();
  108. if(!filename.Icmp("<implicit file>")) {
  109. continue;
  110. }
  111. if(filename.Find("def") != -1) {
  112. int x = 0;
  113. }
  114. if(includeFile) {
  115. filename.StripPath();
  116. temp = idStr(mat->GetFileName()) + "/" + idStr(mat->GetName()) + "|" + filename;
  117. } else {
  118. temp = mat->GetName();
  119. }
  120. list.Append(temp);
  121. }
  122. AddStrList(NULL, &list, includeFile);
  123. }
  124. }
  125. /**
  126. * Called when the material has changed but not applied.
  127. * @param pMaterial The selected material.
  128. */
  129. void MaterialTreeView::MV_OnMaterialChange(MaterialDoc* pMaterial) {
  130. CTreeCtrl& tree = GetTreeCtrl();
  131. //When a material changes place an asterik next to the material and the file
  132. HTREEITEM* materialItem = NULL;
  133. materialToTree.Get(pMaterial->name, &materialItem);
  134. if(!materialItem)
  135. return;
  136. tree.SetItemImage(*materialItem, IMAGE_MATERIAL_MOD_APPLY, IMAGE_MATERIAL_MOD_APPLY);
  137. if(treeWithFile) {
  138. HTREEITEM* fileItem = NULL;
  139. idStr file = pMaterial->renderMaterial->GetFileName();
  140. //common->Printf("Filename = %s\n", file.c_str());
  141. if(fileToTree.Get(file, &fileItem)){
  142. //common->Printf("Found: %d\n", *fileItem);
  143. tree.SetItemImage(*fileItem, IMAGE_FILE_MOD, IMAGE_FILE_MOD);
  144. }
  145. }
  146. }
  147. /**
  148. * Called when the material changes have been applied.
  149. * @param pMaterial The selected material.
  150. */
  151. void MaterialTreeView::MV_OnMaterialApply(MaterialDoc* pMaterial) {
  152. CTreeCtrl& tree = GetTreeCtrl();
  153. //When a material is applied then just change the image to material modified
  154. HTREEITEM* materialItem = NULL;
  155. materialToTree.Get(pMaterial->name, &materialItem);
  156. if(!materialItem)
  157. return;
  158. tree.SetItemImage(*materialItem, IMAGE_MATERIAL_MOD, IMAGE_MATERIAL_MOD);
  159. }
  160. /**
  161. * Called when the material changes have been saved.
  162. * @param pMaterial The saved material.
  163. */
  164. void MaterialTreeView::MV_OnMaterialSaved(MaterialDoc* pMaterial) {
  165. CTreeCtrl& tree = GetTreeCtrl();
  166. //Remove the asterik
  167. HTREEITEM* materialItem = NULL;
  168. materialToTree.Get(pMaterial->name, &materialItem);
  169. //We will get this message for a delete file so the material will not be in the tree
  170. if(materialItem) {
  171. tree.SetItemImage(*materialItem, IMAGE_MATERIAL, IMAGE_MATERIAL);
  172. }
  173. //Check if the file is completely saved
  174. if(treeWithFile) {
  175. if(!materialDocManager->IsFileModified(pMaterial->renderMaterial->GetFileName())) {
  176. HTREEITEM* fileItem = NULL;
  177. idStr file = pMaterial->renderMaterial->GetFileName();
  178. if(fileToTree.Get(file, &fileItem)) {
  179. tree.SetItemImage(*fileItem, IMAGE_FILE, IMAGE_FILE);
  180. }
  181. }
  182. }
  183. }
  184. /**
  185. * Called when a material is added
  186. * @param pMaterial The material that was added.
  187. */
  188. void MaterialTreeView::MV_OnMaterialAdd(MaterialDoc* pMaterial) {
  189. idStrList list(1024);
  190. idMaterial *mat = pMaterial->renderMaterial;
  191. idStr temp;
  192. if(treeWithFile) {
  193. idStr filename = mat->GetFileName();
  194. filename.StripPath();
  195. temp = idStr(mat->GetFileName()) + "/" + idStr(mat->GetName()) + "|" + filename;
  196. } else {
  197. temp = mat->GetName();
  198. }
  199. list.Append(temp);
  200. AddStrList(NULL, &list, treeWithFile);
  201. //Keep the items sorted
  202. HTREEITEM* item = NULL;
  203. materialToTree.Get(pMaterial->name, &item);
  204. if(*item) {
  205. CTreeCtrl& tree = GetTreeCtrl();
  206. HTREEITEM parent = tree.GetParentItem(*item);
  207. tree.SortChildren(parent);
  208. }
  209. MV_OnMaterialChange(pMaterial);
  210. }
  211. /**
  212. * Called when a material is deleted
  213. * @param pMaterial The material that was deleted.
  214. */
  215. void MaterialTreeView::MV_OnMaterialDelete(MaterialDoc* pMaterial) {
  216. //Our doc told us a material has been deleted. Lets find and remove the item from our tree
  217. HTREEITEM* materialItem = NULL;
  218. materialToTree.Get(pMaterial->name, &materialItem);
  219. CTreeCtrl& tree = GetTreeCtrl();
  220. tree.DeleteItem(*materialItem);
  221. //Remove our old quick lookup value
  222. materialToTree.Remove(pMaterial->name.c_str());
  223. }
  224. /**
  225. * Called when the material name has changed
  226. * @param pMaterial The material that was deleted.
  227. * @param oldName The old name of the material.
  228. */
  229. void MaterialTreeView::MV_OnMaterialNameChanged(MaterialDoc* pMaterial, const char* oldName) {
  230. CTreeCtrl& tree = GetTreeCtrl();
  231. if(!internalChange) {
  232. //Delete the old tree item
  233. HTREEITEM* item = NULL;
  234. materialToTree.Get(oldName, &item);
  235. CTreeCtrl& tree = GetTreeCtrl();
  236. HTREEITEM tempItem = *item;
  237. CleanLookupTrees(tempItem);
  238. tree.DeleteItem(tempItem);
  239. //Now add it back
  240. idStrList list(1024);
  241. idMaterial *mat = pMaterial->renderMaterial;
  242. idStr temp;
  243. if(treeWithFile) {
  244. idStr filename = mat->GetFileName();
  245. filename.StripPath();
  246. temp = idStr(mat->GetFileName()) + "/" + idStr(mat->GetName()) + "|" + filename;
  247. } else {
  248. temp = mat->GetName();
  249. }
  250. list.Append(temp);
  251. AddStrList(NULL, &list, treeWithFile);
  252. //Keep the items sorted
  253. //item = NULL;
  254. materialToTree.Get(pMaterial->name.c_str(), &item);
  255. if(*item) {
  256. CTreeCtrl& tree = GetTreeCtrl();
  257. HTREEITEM parent = tree.GetParentItem(*item);
  258. tree.SortChildren(parent);
  259. }
  260. MV_OnMaterialChange(pMaterial);
  261. }
  262. }
  263. /**
  264. * Called when a file has been reloaded
  265. * @param filename The file that was reloaded.
  266. */
  267. void MaterialTreeView::MV_OnFileReload(const char* filename) {
  268. HTREEITEM* fileItem = NULL;
  269. fileToTree.Get(filename, &fileItem);
  270. HTREEITEM item = *fileItem;
  271. CTreeCtrl& tree = GetTreeCtrl();
  272. CleanLookupTrees(item);
  273. tree.DeleteItem(item);
  274. BuildMaterialList(treeWithFile, filename);
  275. //Resort the parent to make sure the file is back where it was
  276. HTREEITEM* newItem = NULL;
  277. fileToTree.Get(filename, &newItem);
  278. if(*newItem) {
  279. CTreeCtrl& tree = GetTreeCtrl();
  280. HTREEITEM parent = tree.GetParentItem(*newItem);
  281. tree.SortChildren(parent);
  282. }
  283. }
  284. /**
  285. * Returns true if the user can copy the selected item.
  286. */
  287. bool MaterialTreeView::CanCopy() {
  288. CTreeCtrl& tree = GetTreeCtrl();
  289. HTREEITEM item = tree.GetSelectedItem();
  290. DWORD itemType = tree.GetItemData(item);
  291. if(item && itemType == TYPE_MATERIAL) {
  292. return true;
  293. } else {
  294. return false;
  295. }
  296. }
  297. /**
  298. * Returns true if the user can paste an item in the copy buffer.
  299. */
  300. bool MaterialTreeView::CanPaste() {
  301. return materialDocManager->IsCopyMaterial();
  302. }
  303. /**
  304. * Returns true if the user can cut the selected item.
  305. */
  306. bool MaterialTreeView::CanCut() {
  307. CTreeCtrl& tree = GetTreeCtrl();
  308. HTREEITEM item = tree.GetSelectedItem();
  309. DWORD itemType = tree.GetItemData(item);
  310. if(item && itemType == TYPE_MATERIAL) {
  311. return true;
  312. } else {
  313. return false;
  314. }
  315. }
  316. /**
  317. * Returns true if the user can delete the selected item.
  318. */
  319. bool MaterialTreeView::CanDelete() {
  320. CTreeCtrl& tree = GetTreeCtrl();
  321. HTREEITEM item = tree.GetSelectedItem();
  322. DWORD itemType = tree.GetItemData(item);
  323. if(itemType == TYPE_MATERIAL_FOLDER || itemType == TYPE_MATERIAL) {
  324. return true;
  325. }
  326. return false;
  327. }
  328. /**
  329. * Returns true if the user can rename the selected item.
  330. */
  331. bool MaterialTreeView::CanRename() {
  332. CTreeCtrl& tree = GetTreeCtrl();
  333. HTREEITEM item = tree.GetSelectedItem();
  334. DWORD itemType = tree.GetItemData(item);
  335. if(itemType == TYPE_MATERIAL_FOLDER || itemType == TYPE_MATERIAL) {
  336. return true;
  337. }
  338. return false;
  339. }
  340. /**
  341. * Returns true if the currently selected file needs to be saved.
  342. */
  343. bool MaterialTreeView::CanSaveFile() {
  344. CTreeCtrl& tree = GetTreeCtrl();
  345. HTREEITEM item = tree.GetSelectedItem();
  346. idStr filename;
  347. if(item && GetFileName(item, filename)) {
  348. if(materialDocManager->IsFileModified(filename.c_str()))
  349. return true;
  350. else
  351. return false;
  352. } else {
  353. return false;
  354. }
  355. }
  356. /**
  357. * Returns the filename of currently selected file.
  358. */
  359. idStr MaterialTreeView::GetSaveFilename() {
  360. CTreeCtrl& tree = GetTreeCtrl();
  361. HTREEITEM item = tree.GetSelectedItem();
  362. idStr filename = "";
  363. if(item) {
  364. if(!GetFileName(item, filename)) {
  365. filename = "";
  366. }
  367. }
  368. return filename;
  369. }
  370. /**
  371. * Searches for a material given the supplied search parameters.
  372. * @param searchData The parameters to use for the search.
  373. */
  374. bool MaterialTreeView::FindNextMaterial(MaterialSearchData_t* searchData) {
  375. CTreeCtrl& tree = GetTreeCtrl();
  376. HTREEITEM selected = tree.GetSelectedItem();
  377. if(!selected) {
  378. selected = tree.GetRootItem();
  379. if(!selected) {
  380. return false;
  381. }
  382. }
  383. //Make sure we are in a file
  384. if(searchData->searchScope == 0) {
  385. DWORD type = tree.GetItemData(selected);
  386. if(type == TYPE_FOLDER || type == TYPE_ROOT)
  387. return false;
  388. }
  389. HTREEITEM search =selected;
  390. while((search = GetNextSeachItem(search, (searchData->searchScope == 0))) != NULL) {
  391. HTREEITEM found = FindNextMaterial(search, searchData);
  392. if(found) {
  393. tree.SelectItem(found);
  394. return true;
  395. }
  396. }
  397. return false;
  398. }
  399. /**
  400. * Searches for a material given the supplied search parameters. Returns the tree item where
  401. * the item was found or NULL if no material was found.
  402. * @param item The tree item from where to start the search.
  403. * @param searchData The parameters to use for the search.
  404. */
  405. HTREEITEM MaterialTreeView::FindNextMaterial(HTREEITEM item, MaterialSearchData_t* searchData) {
  406. CTreeCtrl& tree = GetTreeCtrl();
  407. DWORD type = tree.GetItemData(item);
  408. if(type == TYPE_MATERIAL) {
  409. //check the tree name first
  410. idStr itemName = tree.GetItemText(item);
  411. int findPos = itemName.Find(searchData->searchText, false);
  412. if(findPos != -1) {
  413. //Todo: Include match whole word
  414. return item;
  415. }
  416. if(!searchData->nameOnly) {
  417. //Check the material
  418. idStr materialName = GetMediaPath(item, TYPE_MATERIAL);
  419. if(materialDocManager->FindMaterial(materialName, searchData, false)) {
  420. return item;
  421. }
  422. }
  423. } else {
  424. //Just check the tree name
  425. idStr itemName = tree.GetItemText(item);
  426. int findPos = itemName.Find(searchData->searchText, false);
  427. if(findPos != -1) {
  428. //Todo: Include match whole word
  429. return item;
  430. }
  431. }
  432. return NULL;
  433. }
  434. /**
  435. * Returns the next item to search or NULL if there is nothing else to search.
  436. * @param item The last item searched.
  437. * @param stayInFile True if the search should stay in the current file.
  438. */
  439. HTREEITEM MaterialTreeView::GetNextSeachItem(HTREEITEM item, bool stayInFile) {
  440. CTreeCtrl& tree = GetTreeCtrl();
  441. HTREEITEM nextItem = NULL;
  442. //Check our children
  443. if(tree.ItemHasChildren(item)) {
  444. nextItem = tree.GetChildItem(item);
  445. return nextItem;
  446. }
  447. //Check our siblings
  448. nextItem = tree.GetNextSiblingItem(item);
  449. if(nextItem) {
  450. return nextItem;
  451. }
  452. //Check our parents next sibiling
  453. HTREEITEM parent = item;
  454. while((parent = tree.GetParentItem(parent)) != NULL) {
  455. DWORD parType = tree.GetItemData(parent);
  456. if(stayInFile && parType == TYPE_FILE)
  457. break;
  458. HTREEITEM sib = tree.GetNextSiblingItem(parent);
  459. if(sib) {
  460. nextItem = sib;
  461. break;
  462. }
  463. }
  464. return nextItem;
  465. }
  466. /**
  467. * Deletes a given folder.
  468. * @param item The folder to delete.
  469. * @param addUndo True if this operation can be undone.
  470. */
  471. void MaterialTreeView::DeleteFolder(HTREEITEM item, bool addUndo) {
  472. CTreeCtrl& tree = GetTreeCtrl();
  473. idList<MaterialTreeItem_t> materialsToDelete;
  474. //Get the complete list of materials to delete
  475. GetMaterialPaths(item, &materialsToDelete);
  476. idStrList affectedMaterials;
  477. //Now delete the materials
  478. for(int i = 0; i < materialsToDelete.Num(); i++) {
  479. affectedMaterials.Append(materialsToDelete[i].materialName);
  480. const idMaterial* material = declManager->FindMaterial(materialsToDelete[i].materialName);
  481. MaterialDoc* pMaterial = NULL;
  482. pMaterial = materialDocManager->CreateMaterialDoc(const_cast<idMaterial *>(material));
  483. materialDocManager->DeleteMaterial(pMaterial, false);
  484. }
  485. //Make our undo modifier
  486. if(addUndo) {
  487. DeleteMaterialFolderModifier* mod = new DeleteMaterialFolderModifier(materialDocManager, tree.GetItemText(item), this, tree.GetParentItem(item), &affectedMaterials);
  488. materialDocManager->AddMaterialUndoModifier(mod);
  489. }
  490. //Now clean up the folders and quicktree
  491. CleanLookupTrees(item);
  492. //Remove any folders that were there
  493. tree.DeleteItem(item);
  494. }
  495. /**
  496. * Adds a new material folder.
  497. * @param name The name of the folder.
  498. * @param parent The parent item of the folder.
  499. */
  500. HTREEITEM MaterialTreeView::AddFolder(const char* name, HTREEITEM parent) {
  501. CTreeCtrl& tree = GetTreeCtrl();
  502. HTREEITEM newItem = tree.InsertItem(name, parent);
  503. tree.SetItemImage(newItem, IMAGE_MATERIAL_FOLDER, IMAGE_MATERIAL_FOLDER);
  504. tree.SetItemData(newItem, TYPE_MATERIAL_FOLDER);
  505. tree.Expand(newItem, TVE_EXPAND);
  506. //Make sure the tree is still sorted
  507. tree.SortChildren(parent);
  508. //Build the entire path to this item for the quicktree
  509. idStr qt = GetQuicktreePath(newItem);
  510. quickTree.Set(qt, newItem);
  511. return newItem;
  512. }
  513. /**
  514. * Renames a material folder.
  515. * @param item The folder tree item.
  516. * @param name The new name of the material folder.
  517. */
  518. void MaterialTreeView::RenameFolder(HTREEITEM item, const char* name) {
  519. CTreeCtrl& tree = GetTreeCtrl();
  520. //Clean up the quicktree with the current tree before we allow the edit to commit
  521. CleanLookupTrees(item);
  522. //Store some data so the we can make the appropriate changes after the commit
  523. renamedFolder = item;
  524. affectedMaterials.Clear();
  525. GetMaterialPaths(renamedFolder, &affectedMaterials);
  526. tree.SetItemText(item, name);
  527. PostMessage(MSG_RENAME_FOLDER_COMPLETE);
  528. }
  529. /**
  530. * Handles the keyboard shortcut for delete.
  531. */
  532. BOOL MaterialTreeView::PreTranslateMessage(MSG* pMsg) {
  533. CTreeCtrl& tree = GetTreeCtrl();
  534. if (pMsg->hwnd == tree.GetSafeHwnd()) {
  535. if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_DELETE) {
  536. OnDeleteMaterial();
  537. return TRUE;
  538. }
  539. }
  540. return FALSE;
  541. }
  542. /**
  543. * Called by the MFC framework as the view is being created.
  544. */
  545. int MaterialTreeView::OnCreate(LPCREATESTRUCT lpCreateStruct) {
  546. lpCreateStruct->style |= TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_EDITLABELS | TVS_SHOWSELALWAYS | TVS_INFOTIP;
  547. if (CTreeView::OnCreate(lpCreateStruct) == -1)
  548. return -1;
  549. CTreeCtrl& tree = GetTreeCtrl();
  550. m_image.Create(IDB_ME_TREEBITMAP, 16, 1, RGB(255, 255, 255));
  551. tree.SetImageList(&m_image, TVSIL_NORMAL);
  552. return 0;
  553. }
  554. /**
  555. * Changes the selected material when the select tree item changes.
  556. */
  557. void MaterialTreeView::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult) {
  558. LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
  559. if(pNMTreeView->itemNew.hItem) {
  560. CTreeCtrl& tree = GetTreeCtrl();
  561. DWORD type = tree.GetItemData(pNMTreeView->itemNew.hItem);
  562. if(type == TYPE_MATERIAL) {
  563. idStr mediaName = GetMediaPath(pNMTreeView->itemNew.hItem, type);
  564. const idMaterial* material = declManager->FindMaterial(mediaName);
  565. materialDocManager->SetSelectedMaterial(const_cast<idMaterial*>(material));
  566. } else {
  567. materialDocManager->SetSelectedMaterial(NULL);
  568. }
  569. } else {
  570. materialDocManager->SetSelectedMaterial(NULL);
  571. }
  572. *pResult = 0;
  573. }
  574. /**
  575. * Determines if a tree item's label can be edited.
  576. */
  577. void MaterialTreeView::OnTvnBeginlabeledit(NMHDR *pNMHDR, LRESULT *pResult) {
  578. LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
  579. CTreeCtrl& tree = GetTreeCtrl();
  580. DWORD type = tree.GetItemData(pTVDispInfo->item.hItem);
  581. //Only allow renaming of materials and material folders
  582. if(type == TYPE_MATERIAL || type == TYPE_MATERIAL_FOLDER) {
  583. *pResult = 0;
  584. } else {
  585. *pResult = 1;
  586. }
  587. }
  588. /**
  589. * Makes sure that a rename operation can be performed after a label edit is complete and
  590. * performs the folder or material rename.
  591. */
  592. void MaterialTreeView::OnTvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult) {
  593. LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
  594. *pResult = 0;
  595. if(pTVDispInfo->item.pszText) {
  596. //Convert any edited text to lower case to keep the name canonical
  597. idStr newLabel = pTVDispInfo->item.pszText;
  598. newLabel.ToLower();
  599. strncpy( pTVDispInfo->item.pszText, newLabel.c_str(), pTVDispInfo->item.cchTextMax);
  600. CTreeCtrl& tree = GetTreeCtrl();
  601. DWORD type = tree.GetItemData(pTVDispInfo->item.hItem);
  602. if(type == TYPE_MATERIAL) {
  603. MaterialDoc* pMaterial = materialDocManager->GetCurrentMaterialDoc();
  604. //Remove our old quick lookup value
  605. materialToTree.Remove(pMaterial->name.c_str());
  606. //Generate the new name
  607. idStr material;
  608. HTREEITEM parent = tree.GetParentItem(pTVDispInfo->item.hItem);
  609. DWORD parentType = tree.GetItemData(parent);
  610. if(parentType == TYPE_MATERIAL_FOLDER) {
  611. //Need to include the material folder
  612. material = GetMediaPath(parent, TYPE_MATERIAL_FOLDER);
  613. material += "/";
  614. }
  615. material += pTVDispInfo->item.pszText;
  616. if(declManager->FindMaterial(material, false)) {
  617. //Can't rename because it conflicts with an existing file
  618. MessageBox("Unable to rename material because it conflicts with another material", "Error");
  619. } else {
  620. //Add it to our quick lookup
  621. materialToTree.Set(material, pTVDispInfo->item.hItem);
  622. //Finally make the change
  623. internalChange = true;
  624. pMaterial->SetMaterialName(material);
  625. internalChange = false;
  626. renamedFolder = pTVDispInfo->item.hItem;
  627. PostMessage(MSG_RENAME_MATERIAL_COMPLETE);
  628. *pResult = 1;
  629. }
  630. } else if (type == TYPE_MATERIAL_FOLDER) {
  631. //Clean up the quicktree with the current tree before we allow the edit to commit
  632. CleanLookupTrees(pTVDispInfo->item.hItem);
  633. //Store some data so the we can make the appropriate changes after the commit
  634. renamedFolder = pTVDispInfo->item.hItem;
  635. affectedMaterials.Clear();
  636. GetMaterialPaths(renamedFolder, &affectedMaterials);
  637. PostMessage(MSG_RENAME_FOLDER_COMPLETE);
  638. RenameMaterialFolderModifier* mod = new RenameMaterialFolderModifier(materialDocManager, pTVDispInfo->item.pszText, this, pTVDispInfo->item.hItem, tree.GetItemText(pTVDispInfo->item.hItem));
  639. materialDocManager->AddMaterialUndoModifier(mod);
  640. *pResult = 1;
  641. }
  642. }
  643. }
  644. /**
  645. * Displays the popup menu.
  646. */
  647. void MaterialTreeView::OnContextMenu(CWnd* pWnd, CPoint point)
  648. {
  649. ScreenToClient (&point);
  650. PopupMenu (&point);
  651. }
  652. /**
  653. * Displays the popup menu.
  654. */
  655. void MaterialTreeView::OnNMRclick(NMHDR *pNMHDR, LRESULT *pResult)
  656. {
  657. CTreeCtrl& tree = GetTreeCtrl();
  658. DWORD dwPos = GetMessagePos();
  659. CPoint pt( LOWORD( dwPos ), HIWORD ( dwPos ) );
  660. CPoint spt = pt;
  661. tree.ScreenToClient( &spt );
  662. UINT test;
  663. HTREEITEM item = tree.HitTest( spt, &test );
  664. if ( item != NULL )
  665. {
  666. if ( test & TVHT_ONITEM )
  667. {
  668. //Select the item
  669. tree.SelectItem(item);
  670. OnContextMenu( this, pt );
  671. }
  672. }
  673. *pResult = 0;
  674. }
  675. /**
  676. * Handles keyboard shortcut for cut, copy and paste
  677. */
  678. void MaterialTreeView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
  679. {
  680. if(nChar == 3 && GetKeyState(VK_CONTROL)) {
  681. OnCopy();
  682. }
  683. if(nChar == 22 && GetKeyState(VK_CONTROL)) {
  684. OnPaste();
  685. }
  686. if(nChar == 24 && GetKeyState(VK_CONTROL)) {
  687. OnCut();
  688. }
  689. CTreeView::OnChar(nChar, nRepCnt, nFlags);
  690. }
  691. /**
  692. * Begins the process of a drag cut/copy.
  693. */
  694. void MaterialTreeView::OnTvnBegindrag(NMHDR *pNMHDR, LRESULT *pResult)
  695. {
  696. LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
  697. CTreeCtrl& tree = GetTreeCtrl();
  698. HTREEITEM selecteditem = tree.GetSelectedItem();
  699. //Check to see if the are clicking on an item
  700. UINT flags;
  701. HTREEITEM item = tree.HitTest(pNMTreeView->ptDrag, &flags);
  702. if(item && (TVHT_ONITEM & flags)) {
  703. if(item != selecteditem) {
  704. tree.SelectItem(item);
  705. }
  706. }
  707. DWORD itemType = tree.GetItemData(item);
  708. if(itemType == TYPE_MATERIAL) {
  709. //Create the drag image
  710. dragImage = tree.CreateDragImage(item);
  711. dragImage->BeginDrag(0, CPoint (8, 8));
  712. dragImage->DragEnter(GetDesktopWindow(), pNMTreeView->ptDrag);
  713. //Drag is in progress
  714. bDragging = true;
  715. dragItem = item;
  716. //Capture the messages
  717. SetCapture();
  718. }
  719. *pResult = 0;
  720. }
  721. /**
  722. * Handles mouse movement as an item is being dragged.
  723. */
  724. void MaterialTreeView::OnMouseMove(UINT nFlags, CPoint point) {
  725. if( bDragging ) {
  726. CTreeCtrl& tree = GetTreeCtrl();
  727. dropPoint = point;
  728. ClientToScreen(&dropPoint);
  729. //Move the drag image
  730. dragImage->DragMove(dropPoint);
  731. dragImage->DragShowNolock(FALSE);
  732. dragImage->DragShowNolock(TRUE);
  733. }
  734. if(bDragging) {
  735. //Test the hover item
  736. CTreeCtrl& tree = GetTreeCtrl();
  737. CPoint point;
  738. GetCursorPos(&point);
  739. ScreenToClient(&point);
  740. UINT flags;
  741. HTREEITEM item = tree.HitTest(point, &flags);
  742. if(item && (TVHT_ONITEM & flags)) {
  743. if(item != hoverItem) {
  744. hoverItem = item;
  745. hoverStartTime = timeGetTime();
  746. } else {
  747. DWORD currentTime = timeGetTime();
  748. if(currentTime - hoverStartTime > HOVER_EXPAND_DELAY) {
  749. UINT state = tree.GetItemState(hoverItem, TVIS_EXPANDED);
  750. if(state != TVIS_EXPANDED && tree.ItemHasChildren(hoverItem)) {
  751. tree.Expand(hoverItem, TVE_EXPAND);
  752. }
  753. }
  754. }
  755. }
  756. }
  757. CTreeView::OnMouseMove(nFlags, point);
  758. }
  759. /**
  760. * Handles the end of a drag copy/move when the user releases the left mouse button.
  761. */
  762. void MaterialTreeView::OnLButtonUp(UINT nFlags, CPoint point) {
  763. CTreeCtrl& tree = GetTreeCtrl();
  764. if( bDragging ) {
  765. //Release mouse capture
  766. ReleaseCapture();
  767. //Delete the drag image
  768. dragImage->DragLeave(GetDesktopWindow());
  769. dragImage->EndDrag();
  770. bDragging = false;
  771. delete dragImage;
  772. UINT flags;
  773. HTREEITEM item = tree.HitTest(point, &flags);
  774. if(item && (TVHT_ONITEM & flags)) {
  775. DWORD itemType = tree.GetItemData(item);
  776. if(itemType == TYPE_MATERIAL) //Backup one if a file is selected
  777. item = tree.GetParentItem(item);
  778. //Make sure we aren't dragging to the same place
  779. HTREEITEM dragItemParent = tree.GetParentItem(dragItem);
  780. if(dragItemParent != item) {
  781. idStr dragFile;
  782. GetFileName(dragItem, dragFile);
  783. idStr filename;
  784. GetFileName(item, filename);
  785. //Move within a file copy across files
  786. if(!dragFile.Icmp(filename)) {
  787. materialDocManager->CopyMaterial(materialDocManager->GetCurrentMaterialDoc(), true);
  788. } else {
  789. materialDocManager->CopyMaterial(materialDocManager->GetCurrentMaterialDoc(), false);
  790. }
  791. //Generate the name
  792. idStr materialName = GetMediaPath(item, itemType);
  793. idStr copyName = materialDocManager->GetCopyMaterialName();
  794. idStr copyMaterialName;
  795. copyName.ExtractFileName(copyMaterialName);
  796. materialName += "/" + copyMaterialName;
  797. //If the material name already exists add numbers until we don't find it
  798. materialName = materialDocManager->GetUniqueMaterialName(materialName);
  799. //Paste
  800. materialDocManager->PasteMaterial(materialName, filename);
  801. }
  802. }
  803. }
  804. CTreeView::OnLButtonUp(nFlags, point);
  805. }
  806. /**
  807. * Applies the current material.
  808. */
  809. void MaterialTreeView::OnApplyMaterial() {
  810. materialDocManager->ApplyMaterial(materialDocManager->GetCurrentMaterialDoc());
  811. }
  812. /**
  813. * Applies all materials in the currently selected file.
  814. */
  815. void MaterialTreeView::OnApplyFile() {
  816. idStr filename;
  817. HTREEITEM item = GetTreeCtrl().GetSelectedItem();
  818. if(GetFileName(item, filename)) {
  819. materialDocManager->ApplyFile(filename.c_str());
  820. }
  821. }
  822. /**
  823. * Applies all materials that need to be applied.
  824. */
  825. void MaterialTreeView::OnApplyAll() {
  826. materialDocManager->ApplyAll();
  827. }
  828. /**
  829. * Saves the selected material.
  830. */
  831. void MaterialTreeView::OnSaveMaterial() {
  832. materialDocManager->SaveMaterial(materialDocManager->GetCurrentMaterialDoc());
  833. }
  834. /**
  835. * Saves all materials in the selected file.
  836. */
  837. void MaterialTreeView::OnSaveFile() {
  838. idStr filename;
  839. HTREEITEM item = GetTreeCtrl().GetSelectedItem();
  840. if(GetFileName(item, filename)) {
  841. materialDocManager->SaveFile(filename.c_str());
  842. }
  843. }
  844. /**
  845. * Save all materials that have been changed.
  846. */
  847. void MaterialTreeView::OnSaveAll() {
  848. materialDocManager->SaveAllMaterials();
  849. }
  850. /**
  851. * Begins a label edit to rename a material or material folder.
  852. */
  853. void MaterialTreeView::OnRenameMaterial() {
  854. CTreeCtrl& tree = GetTreeCtrl();
  855. HTREEITEM item = tree.GetSelectedItem();
  856. tree.EditLabel(item);
  857. }
  858. /**
  859. * Adds a new material.
  860. */
  861. void MaterialTreeView::OnAddMaterial() {
  862. CTreeCtrl& tree = GetTreeCtrl();
  863. HTREEITEM item = tree.GetSelectedItem();
  864. DWORD itemType = tree.GetItemData(item);
  865. //Determine the file
  866. HTREEITEM parent = NULL;
  867. if(itemType != TYPE_FILE) {
  868. parent = tree.GetParentItem(item);
  869. while(1) {
  870. if(tree.GetItemData(parent) == TYPE_FILE)
  871. break;
  872. parent = tree.GetParentItem(parent);
  873. }
  874. } else {
  875. parent = item;
  876. }
  877. idStr filename = GetMediaPath(parent, TYPE_FILE);
  878. //Determine the material folder
  879. idStr materialFolder = "";
  880. switch(itemType) {
  881. case TYPE_MATERIAL:
  882. {
  883. HTREEITEM parentFolderItem = tree.GetParentItem(item);
  884. if(tree.GetItemData(parentFolderItem) == TYPE_MATERIAL_FOLDER)
  885. materialFolder = GetMediaPath(parentFolderItem, TYPE_MATERIAL_FOLDER);
  886. }
  887. break;
  888. case TYPE_MATERIAL_FOLDER:
  889. materialFolder = GetMediaPath(item, TYPE_MATERIAL_FOLDER);
  890. break;
  891. case TYPE_FILE:
  892. //There is no material folder
  893. break;
  894. }
  895. idStr name;
  896. int num = 1;
  897. while(1) {
  898. if(materialFolder.Length() > 0) {
  899. name = va("%s/newmaterial%d", materialFolder.c_str(), num);
  900. } else {
  901. name = va("newmaterial%d", num);
  902. }
  903. if(!declManager->FindMaterial(name, false))
  904. break;
  905. num++;
  906. }
  907. materialDocManager->AddMaterial(name.c_str(), filename.c_str());
  908. }
  909. /**
  910. * Adds a new folder
  911. */
  912. void MaterialTreeView::OnAddFolder() {
  913. CTreeCtrl& tree = GetTreeCtrl();
  914. HTREEITEM item = tree.GetSelectedItem();
  915. DWORD itemType = tree.GetItemData(item);
  916. //Backup if the selected item is a material
  917. if(itemType == TYPE_MATERIAL) {
  918. item = tree.GetParentItem(item);
  919. }
  920. //Pick a unique material name
  921. idStr newFolder;
  922. int num = 1;
  923. while(1) {
  924. newFolder = va("newfolder%d", num);
  925. if(tree.ItemHasChildren(item)) {
  926. HTREEITEM hChildItem = tree.GetChildItem(item);
  927. bool found = false;
  928. while (hChildItem != NULL)
  929. {
  930. if(!newFolder.Icmp(tree.GetItemText(hChildItem))) {
  931. found = true;
  932. break;
  933. }
  934. hChildItem = tree.GetNextSiblingItem(hChildItem);
  935. }
  936. if(!found)
  937. break;
  938. } else {
  939. break;
  940. }
  941. num++;
  942. }
  943. HTREEITEM newItem = AddFolder(newFolder, item);
  944. AddMaterialFolderModifier* mod = new AddMaterialFolderModifier(materialDocManager, newFolder, this, newItem, item);
  945. materialDocManager->AddMaterialUndoModifier(mod);
  946. }
  947. /**
  948. * Deletes a material or material folder.
  949. */
  950. void MaterialTreeView::OnDeleteMaterial() {
  951. CTreeCtrl& tree = GetTreeCtrl();
  952. HTREEITEM item = tree.GetSelectedItem();
  953. DWORD itemType = tree.GetItemData(item);
  954. if(itemType == TYPE_MATERIAL_FOLDER) {
  955. int result = MessageBox("Are you sure you want to delete this folder?", "Delete?", MB_ICONQUESTION | MB_YESNO);
  956. if(result == IDYES) {
  957. DeleteFolder(item);
  958. }
  959. } else if (itemType == TYPE_MATERIAL) {
  960. int result = MessageBox("Are you sure you want to delete this material?", "Delete?", MB_ICONQUESTION | MB_YESNO);
  961. if(result == IDYES) {
  962. materialDocManager->DeleteMaterial(materialDocManager->GetCurrentMaterialDoc());
  963. }
  964. }
  965. }
  966. /**
  967. * Reloads the selected file.
  968. */
  969. void MaterialTreeView::OnReloadFile() {
  970. CTreeCtrl& tree = GetTreeCtrl();
  971. HTREEITEM item = tree.GetSelectedItem();
  972. DWORD itemType = tree.GetItemData(item);
  973. if(itemType == TYPE_MATERIAL || itemType == TYPE_FILE || itemType == TYPE_MATERIAL_FOLDER) {
  974. idStr filename;
  975. GetFileName(item, filename);
  976. if(materialDocManager->IsFileModified(filename)) {
  977. int result = MessageBox("This file has been modified. Are you sure you want to reload this file?", "Reload?", MB_ICONQUESTION | MB_YESNO);
  978. if(result != IDYES) {
  979. return;
  980. }
  981. }
  982. materialDocManager->ReloadFile(filename);
  983. }
  984. }
  985. /**
  986. * Performs a cut operation.
  987. */
  988. void MaterialTreeView::OnCut() {
  989. CTreeCtrl& tree = GetTreeCtrl();
  990. HTREEITEM item = tree.GetSelectedItem();
  991. DWORD itemType = tree.GetItemData(item);
  992. if(item && itemType == TYPE_MATERIAL) {
  993. materialDocManager->CopyMaterial(materialDocManager->GetCurrentMaterialDoc(), true);
  994. } else if (itemType == TYPE_MATERIAL_FOLDER) {
  995. }
  996. }
  997. /**
  998. * Performs a copy operation.
  999. */
  1000. void MaterialTreeView::OnCopy() {
  1001. CTreeCtrl& tree = GetTreeCtrl();
  1002. HTREEITEM item = tree.GetSelectedItem();
  1003. DWORD itemType = tree.GetItemData(item);
  1004. if(itemType == TYPE_MATERIAL) {
  1005. materialDocManager->CopyMaterial(materialDocManager->GetCurrentMaterialDoc(), false);
  1006. } else if (itemType == TYPE_MATERIAL_FOLDER) {
  1007. }
  1008. }
  1009. /**
  1010. * Performs a paste operation.
  1011. */
  1012. void MaterialTreeView::OnPaste() {
  1013. CTreeCtrl& tree = GetTreeCtrl();
  1014. HTREEITEM item = tree.GetSelectedItem();
  1015. DWORD itemType = tree.GetItemData(item);
  1016. //Paste a material
  1017. if(item && materialDocManager->IsCopyMaterial() && itemType >= TYPE_FILE) {
  1018. //Generate the name
  1019. if(itemType == TYPE_MATERIAL) {//Backup one if a file is selected
  1020. item = tree.GetParentItem(item);
  1021. itemType = tree.GetItemData(item);
  1022. }
  1023. idStr materialName = "";
  1024. if(itemType != TYPE_FILE) {
  1025. materialName = GetMediaPath(item, itemType) + "/";
  1026. }
  1027. idStr copyName = materialDocManager->GetCopyMaterialName();
  1028. idStr copyMaterialName;
  1029. copyName.ExtractFileName(copyMaterialName);
  1030. materialName += copyMaterialName;
  1031. idStr filename;
  1032. GetFileName(item, filename);
  1033. //If the material name already exists add numbers until we don't find it
  1034. materialName = materialDocManager->GetUniqueMaterialName(materialName);
  1035. //Paste
  1036. materialDocManager->PasteMaterial(materialName, filename);
  1037. }
  1038. }
  1039. /**
  1040. * This message is sent after the label edit is complete to actually perform the rename
  1041. * operation.
  1042. */
  1043. LRESULT MaterialTreeView::OnRenameFolderComplete(WPARAM wParam, LPARAM lParam) {
  1044. //Generate new quick tree info for all material folders
  1045. BuildLookupTrees(renamedFolder);
  1046. //Go through the list of affected materials and rename them
  1047. for(int i = 0; i < affectedMaterials.Num(); i++) {
  1048. RenameMaterial(affectedMaterials[i].treeItem, affectedMaterials[i].materialName);
  1049. }
  1050. //Make sure the tree stays sorted
  1051. CTreeCtrl& tree = GetTreeCtrl();
  1052. HTREEITEM parent = tree.GetParentItem(renamedFolder);
  1053. tree.SortChildren(parent);
  1054. return 0;
  1055. }
  1056. /**
  1057. * This message is sent after the label edit is complete to ensure that the sorting stays consistent.
  1058. */
  1059. LRESULT MaterialTreeView::OnRenameMaterialComplete(WPARAM wParam, LPARAM lParam) {
  1060. //Make sure the tree stays sorted
  1061. CTreeCtrl& tree = GetTreeCtrl();
  1062. HTREEITEM parent = tree.GetParentItem(renamedFolder);
  1063. tree.SortChildren(parent);
  1064. return 0;
  1065. }
  1066. /**
  1067. * Handles all of the little problems associated with renaming a folder.
  1068. */
  1069. void MaterialTreeView::RenameMaterial(HTREEITEM item, const char* originalName) {
  1070. CTreeCtrl& tree = GetTreeCtrl();
  1071. const idMaterial* material = declManager->FindMaterial(originalName);
  1072. MaterialDoc* pMaterial;
  1073. //pMaterial = materialDocManager->GetInProgressDoc(material);
  1074. //if(!pMaterial) {
  1075. pMaterial = materialDocManager->CreateMaterialDoc(const_cast<idMaterial *>(material));
  1076. //}
  1077. //Remove our old quick lookup value
  1078. materialToTree.Remove(originalName);
  1079. //Generate the new name
  1080. idStr materialName;
  1081. HTREEITEM parent = tree.GetParentItem(item);
  1082. DWORD parentType = tree.GetItemData(parent);
  1083. if(parentType == TYPE_MATERIAL_FOLDER) {
  1084. //Need to include the material folder
  1085. materialName = GetMediaPath(parent, TYPE_MATERIAL_FOLDER);
  1086. materialName += "/";
  1087. }
  1088. materialName += tree.GetItemText(item);
  1089. //Add it to our quick lookup
  1090. materialToTree.Set(materialName, item);
  1091. //Finally make the change
  1092. internalChange = true;
  1093. pMaterial->SetMaterialName(materialName, false);
  1094. internalChange = false;
  1095. }
  1096. /**
  1097. * Returns the filename of the provided item.
  1098. * @param item The item for which to generate the filename
  1099. * @param out The location the filename will be placed.
  1100. */
  1101. bool MaterialTreeView::GetFileName(HTREEITEM item, idStr& out) {
  1102. out = "";
  1103. CTreeCtrl& tree = GetTreeCtrl();
  1104. DWORD type = tree.GetItemData(item);
  1105. if(type != TYPE_MATERIAL && type != TYPE_MATERIAL_FOLDER && type != TYPE_FILE)
  1106. return false;
  1107. if(type == TYPE_FILE) {
  1108. out = GetMediaPath(item, TYPE_FILE);
  1109. return true;
  1110. }
  1111. HTREEITEM parent = tree.GetParentItem( item );
  1112. while ( parent != NULL ) {
  1113. DWORD parentType = tree.GetItemData(parent);
  1114. if(parentType == TYPE_FILE) {
  1115. out = GetMediaPath(parent, TYPE_FILE);
  1116. return true;
  1117. }
  1118. parent = tree.GetParentItem( parent );
  1119. }
  1120. return false;
  1121. }
  1122. /**
  1123. * Returns the Doom III name for the provided item
  1124. * @param item The item for which to generate the name
  1125. * @param type The type of the selected item
  1126. */
  1127. idStr MaterialTreeView::GetMediaPath(HTREEITEM item, DWORD type) {
  1128. //Determine when to stop building the path
  1129. DWORD stopType = TYPE_ROOT;
  1130. switch(type) {
  1131. case TYPE_MATERIAL:
  1132. stopType = TYPE_FILE;
  1133. break;
  1134. case TYPE_MATERIAL_FOLDER:
  1135. stopType = TYPE_FILE;
  1136. break;
  1137. case TYPE_FILE:
  1138. stopType = TYPE_ROOT;
  1139. break;
  1140. };
  1141. CTreeCtrl& tree = GetTreeCtrl();
  1142. idStr mediaName = tree.GetItemText( item );
  1143. // have to build the name back up
  1144. HTREEITEM parent = tree.GetParentItem( item );
  1145. while ( parent != NULL ) {
  1146. //stop the iteration once we have found a specific type
  1147. DWORD parentType = tree.GetItemData(parent);
  1148. if(parentType == stopType) {
  1149. break;
  1150. }
  1151. idStr strParent = tree.GetItemText( parent );
  1152. strParent += "/";
  1153. strParent += mediaName;
  1154. mediaName = strParent;
  1155. parent = tree.GetParentItem( parent );
  1156. }
  1157. return mediaName;
  1158. }
  1159. /**
  1160. * Creates a list of material paths for all materials under the provided item.
  1161. * @param item The base item for which to generate the list
  1162. * @param list The list in which the paths will be stored.
  1163. */
  1164. void MaterialTreeView::GetMaterialPaths(HTREEITEM item, idList<MaterialTreeItem_t>* list) {
  1165. CTreeCtrl& tree = GetTreeCtrl();
  1166. if(tree.ItemHasChildren(item)) {
  1167. HTREEITEM childItem = tree.GetChildItem(item);
  1168. while(childItem != NULL) {
  1169. DWORD childType = tree.GetItemData(childItem);
  1170. if (childType == TYPE_MATERIAL) {
  1171. MaterialTreeItem_t mat;
  1172. mat.materialName = GetMediaPath(childItem, TYPE_MATERIAL);
  1173. mat.treeItem = childItem;
  1174. list->Append(mat);
  1175. } else if (childType == TYPE_MATERIAL_FOLDER) {
  1176. GetMaterialPaths(childItem, list);
  1177. }
  1178. childItem = tree.GetNextSiblingItem(childItem);
  1179. }
  1180. }
  1181. }
  1182. /**
  1183. * Adds a string list of materials to the tree creating the proper hierarchy.
  1184. * @param root The name of the root item or NULL for no root item.
  1185. * @param list The list of materials.
  1186. * @param includeFile If true the materials will be sorted by file.
  1187. */
  1188. void MaterialTreeView::AddStrList(const char *root, idStrList *list, bool includeFile) {
  1189. CTreeCtrl& treeMedia = GetTreeCtrl();
  1190. idStr out, path;
  1191. HTREEITEM base = NULL;
  1192. if(root) {
  1193. base = treeMedia.GetRootItem();
  1194. if (base) {
  1195. out = treeMedia.GetItemText(base);
  1196. if (stricmp(root, out)) {
  1197. base = NULL;
  1198. }
  1199. }
  1200. if (base == NULL) {
  1201. base = treeMedia.InsertItem(root);
  1202. treeMedia.SetItemData(base, TYPE_ROOT);
  1203. }
  1204. }
  1205. HTREEITEM item = base;
  1206. HTREEITEM add;
  1207. list->Sort();
  1208. int count = list->Num();
  1209. idStr last, qt;
  1210. for (int i = 0; i < count; i++) {
  1211. idStr *strItem = &(*list)[i];
  1212. idStr name = strItem->c_str();
  1213. idStr filename;
  1214. bool afterFile = true;
  1215. if(includeFile) {
  1216. int index = name.Find("|");
  1217. if(index >= 0) {
  1218. afterFile = false;
  1219. filename = name.Right(name.Length() - index - 1);
  1220. name = name.Left(index);
  1221. }
  1222. }
  1223. // now break the name down convert to slashes
  1224. name.BackSlashesToSlashes();
  1225. name.Strip(' ');
  1226. int index;
  1227. int len = last.Length();
  1228. if (len == 0) {
  1229. index = name.Last('/');
  1230. if (index >= 0) {
  1231. name.Left(index, last);
  1232. }
  1233. }
  1234. else if (idStr::Icmpn(last, name, len) == 0 && name.Last('/') <= len) {
  1235. name.Right(name.Length() - len - 1, out);
  1236. add = treeMedia.InsertItem(out, item);
  1237. qt = root;
  1238. qt += "/";
  1239. qt += name;
  1240. quickTree.Set(qt, add);
  1241. treeMedia.SetItemImage(add, IMAGE_MATERIAL, IMAGE_MATERIAL);
  1242. treeMedia.SetItemData(add, TYPE_MATERIAL);
  1243. //Add the item to a quick lookup table
  1244. idStr material = GetMediaPath(add, TYPE_MATERIAL);
  1245. materialToTree.Set(material, add);
  1246. continue;
  1247. }
  1248. else {
  1249. last.Empty();
  1250. }
  1251. index = 0;
  1252. item = base;
  1253. path = "";
  1254. while (index >= 0) {
  1255. index = name.Find('/');
  1256. if (index >= 0) {
  1257. HTREEITEM newItem = NULL;
  1258. HTREEITEM *check = NULL;
  1259. name.Left(index, out);
  1260. path += out;
  1261. qt = root;
  1262. qt += "/";
  1263. qt += path;
  1264. if (quickTree.Get(qt, &check)) {
  1265. newItem = *check;
  1266. }
  1267. bool thisisfile = false;
  1268. if(out == filename) {
  1269. thisisfile = true;
  1270. afterFile = true;
  1271. }
  1272. if (newItem == NULL) {
  1273. newItem = treeMedia.InsertItem(out, item);
  1274. qt = root;
  1275. qt += "/";
  1276. qt += path;
  1277. quickTree.Set(qt, newItem);
  1278. if(!afterFile || thisisfile) {
  1279. if(thisisfile) {
  1280. afterFile = true;
  1281. treeMedia.SetItemImage(newItem, IMAGE_FILE, IMAGE_FILE);
  1282. treeMedia.SetItemData(newItem, TYPE_FILE);
  1283. //Add the item to a quick lookup table
  1284. idStr file = GetMediaPath(newItem, TYPE_FILE);
  1285. //common->Printf("Adding fileToTree: %s - %d\n", file.c_str(), newItem);
  1286. fileToTree.Set(file, newItem);
  1287. } else {
  1288. treeMedia.SetItemImage(newItem, IMAGE_FOLDER, IMAGE_FOLDER);
  1289. treeMedia.SetItemData(newItem, TYPE_FOLDER);
  1290. }
  1291. } else {
  1292. treeMedia.SetItemImage(newItem, IMAGE_MATERIAL_FOLDER, IMAGE_MATERIAL_FOLDER);
  1293. treeMedia.SetItemData(newItem, TYPE_MATERIAL_FOLDER);
  1294. }
  1295. }
  1296. item = newItem;
  1297. name.Right(name.Length() - index - 1, out);
  1298. name = out;
  1299. path += "/";
  1300. }
  1301. else {
  1302. add = treeMedia.InsertItem(name, item);
  1303. qt = root;
  1304. qt += "/";
  1305. qt += path;
  1306. qt += name;
  1307. quickTree.Set(qt, add);
  1308. treeMedia.SetItemImage(add, IMAGE_MATERIAL, IMAGE_MATERIAL);
  1309. treeMedia.SetItemData(add, TYPE_MATERIAL);
  1310. path = "";
  1311. //Add the item to a quick lookup table
  1312. idStr material = GetMediaPath(add, TYPE_MATERIAL);
  1313. materialToTree.Set(material, add);
  1314. }
  1315. }
  1316. }
  1317. }
  1318. /**
  1319. * Displays the popup menu with all of the appropriate menu items enabled.
  1320. * @param pt The location where the menu should be displayed.
  1321. */
  1322. void MaterialTreeView::PopupMenu(CPoint* pt) {
  1323. //Determine the type of object clicked on
  1324. CTreeCtrl& tree = GetTreeCtrl();
  1325. UINT test;
  1326. HTREEITEM item = tree.HitTest( *pt, &test );
  1327. if ( item == NULL || !(test & TVHT_ONITEM) )
  1328. return;
  1329. ClientToScreen (pt);
  1330. CMenu FloatingMenu;
  1331. VERIFY(FloatingMenu.LoadMenu(IDR_ME_MATERIALTREE_POPUP));
  1332. CMenu* pPopupMenu = FloatingMenu.GetSubMenu (0);
  1333. DWORD itemType = tree.GetItemData(item);
  1334. //Enable/Disable based on the state
  1335. MaterialDoc* pDoc = materialDocManager->GetCurrentMaterialDoc();
  1336. //Apply Changes
  1337. if(pDoc && pDoc->applyWaiting) {
  1338. pPopupMenu->EnableMenuItem(ID_POPUP_APPLYMATERIAL, MF_BYCOMMAND | MF_ENABLED);
  1339. } else {
  1340. pPopupMenu->EnableMenuItem(ID_POPUP_APPLYMATERIAL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1341. }
  1342. //Apply File
  1343. idStr filename;
  1344. if(GetFileName(item, filename)) {
  1345. if(materialDocManager->DoesFileNeedApply(filename.c_str()))
  1346. pPopupMenu->EnableMenuItem(ID_POPUP_APPLYFILE, MF_BYCOMMAND | MF_ENABLED);
  1347. else
  1348. pPopupMenu->EnableMenuItem(ID_POPUP_APPLYFILE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1349. } else {
  1350. pPopupMenu->EnableMenuItem(ID_POPUP_APPLYFILE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1351. }
  1352. //Apply All
  1353. if(materialDocManager->DoesAnyNeedApply()) {
  1354. pPopupMenu->EnableMenuItem(ID_POPUP_APPLYALL, MF_BYCOMMAND | MF_ENABLED);
  1355. } else {
  1356. pPopupMenu->EnableMenuItem(ID_POPUP_APPLYALL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1357. }
  1358. //Save Material
  1359. if(pDoc && pDoc->modified) {
  1360. pPopupMenu->EnableMenuItem(ID_POPUP_SAVEMATERIAL, MF_BYCOMMAND | MF_ENABLED);
  1361. } else {
  1362. pPopupMenu->EnableMenuItem(ID_POPUP_SAVEMATERIAL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1363. }
  1364. //Save File
  1365. if(GetFileName(item, filename)) {
  1366. if(materialDocManager->IsFileModified(filename.c_str()))
  1367. pPopupMenu->EnableMenuItem(ID_POPUP_SAVEFILE, MF_BYCOMMAND | MF_ENABLED);
  1368. else
  1369. pPopupMenu->EnableMenuItem(ID_POPUP_SAVEFILE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1370. } else {
  1371. pPopupMenu->EnableMenuItem(ID_POPUP_SAVEFILE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1372. }
  1373. //Save All
  1374. if(materialDocManager->IsAnyModified()) {
  1375. pPopupMenu->EnableMenuItem(ID_POPUP_SAVEALL, MF_BYCOMMAND | MF_ENABLED);
  1376. } else {
  1377. pPopupMenu->EnableMenuItem(ID_POPUP_SAVEALL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1378. }
  1379. if(itemType == TYPE_MATERIAL || itemType == TYPE_MATERIAL_FOLDER) {
  1380. pPopupMenu->EnableMenuItem(ID_POPUP_RENAMEMATERIAL, MF_BYCOMMAND | MF_ENABLED);
  1381. pPopupMenu->EnableMenuItem(ID_POPUP_DELETEMATERIAL, MF_BYCOMMAND | MF_ENABLED);
  1382. } else {
  1383. pPopupMenu->EnableMenuItem(ID_POPUP_RENAMEMATERIAL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1384. pPopupMenu->EnableMenuItem(ID_POPUP_DELETEMATERIAL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1385. }
  1386. if(itemType == TYPE_FILE || itemType == TYPE_MATERIAL_FOLDER || itemType == TYPE_MATERIAL) {
  1387. pPopupMenu->EnableMenuItem(ID_POPUP_ADDMATERIAL, MF_BYCOMMAND | MF_ENABLED);
  1388. pPopupMenu->EnableMenuItem(ID_POPUP_ADDFOLDER, MF_BYCOMMAND | MF_ENABLED);
  1389. } else {
  1390. pPopupMenu->EnableMenuItem(ID_POPUP_ADDMATERIAL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1391. pPopupMenu->EnableMenuItem(ID_POPUP_ADDFOLDER, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1392. }
  1393. if(itemType == TYPE_MATERIAL) {
  1394. pPopupMenu->EnableMenuItem(ID_POPUP_CUT, MF_BYCOMMAND | MF_ENABLED);
  1395. pPopupMenu->EnableMenuItem(ID_POPUP_COPY, MF_BYCOMMAND | MF_ENABLED);
  1396. } else {
  1397. pPopupMenu->EnableMenuItem(ID_POPUP_CUT, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1398. pPopupMenu->EnableMenuItem(ID_POPUP_COPY, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1399. }
  1400. if((itemType == TYPE_MATERIAL || itemType == TYPE_FILE || itemType == TYPE_MATERIAL_FOLDER) && materialDocManager->IsCopyMaterial()) {
  1401. pPopupMenu->EnableMenuItem(ID_POPUP_PASTE, MF_BYCOMMAND | MF_ENABLED);
  1402. } else {
  1403. pPopupMenu->EnableMenuItem(ID_POPUP_PASTE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1404. }
  1405. if(itemType == TYPE_MATERIAL || itemType == TYPE_FILE || itemType == TYPE_MATERIAL_FOLDER) {
  1406. pPopupMenu->EnableMenuItem(ID_POPUP_RELOADFILE, MF_BYCOMMAND | MF_ENABLED);
  1407. } else {
  1408. pPopupMenu->EnableMenuItem(ID_POPUP_RELOADFILE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  1409. }
  1410. pPopupMenu->TrackPopupMenu (TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt->x, pt->y, &GetTreeCtrl());
  1411. }
  1412. /**
  1413. * Sets the appropriate item image based on the state of the item.
  1414. * @param item The item to set.
  1415. * @param mod Is the item modified
  1416. * @param apply Does the item need an apply
  1417. * @param children Should this method recurse through the items children and set their icons.
  1418. */
  1419. void MaterialTreeView::SetItemImage(HTREEITEM item, bool mod, bool apply, bool children) {
  1420. CTreeCtrl& tree = GetTreeCtrl();
  1421. int image;
  1422. DWORD itemType = tree.GetItemData(item);
  1423. switch(itemType) {
  1424. case TYPE_FILE:
  1425. if(mod)
  1426. image = IMAGE_FILE_MOD;
  1427. else
  1428. image = IMAGE_FILE;
  1429. break;
  1430. case TYPE_MATERIAL_FOLDER:
  1431. image = IMAGE_MATERIAL_FOLDER;
  1432. break;
  1433. case TYPE_MATERIAL:
  1434. if(mod && apply)
  1435. image = IMAGE_MATERIAL_MOD_APPLY;
  1436. else if(mod)
  1437. image = IMAGE_MATERIAL_MOD;
  1438. else
  1439. image = IMAGE_MATERIAL;
  1440. break;
  1441. }
  1442. tree.SetItemImage(item, image, image);
  1443. if(children) {
  1444. if(tree.ItemHasChildren(item)) {
  1445. HTREEITEM hChildItem = tree.GetChildItem(item);
  1446. while (hChildItem != NULL) {
  1447. SetItemImage(hChildItem, mod, apply, children);
  1448. hChildItem = tree.GetNextSiblingItem(hChildItem);
  1449. }
  1450. }
  1451. }
  1452. }
  1453. /**
  1454. * Cleans the lookup tables for the provided item and all children.
  1455. * @param item The item to start from
  1456. */
  1457. void MaterialTreeView::CleanLookupTrees(HTREEITEM item) {
  1458. idStr qt = GetQuicktreePath(item);
  1459. quickTree.Remove(qt);
  1460. CTreeCtrl& tree = GetTreeCtrl();
  1461. //Clean special lookup tables
  1462. DWORD type = tree.GetItemData(item);
  1463. if(type == TYPE_FILE) {
  1464. idStr file = GetMediaPath(item, TYPE_FILE);
  1465. fileToTree.Remove(file);
  1466. } else if(type == TYPE_MATERIAL) {
  1467. idStr name = GetMediaPath(item, TYPE_MATERIAL);
  1468. materialToTree.Remove(name);
  1469. }
  1470. //Clean all my children
  1471. if(tree.ItemHasChildren(item)) {
  1472. HTREEITEM childItem = tree.GetChildItem(item);
  1473. while(childItem != NULL) {
  1474. CleanLookupTrees(childItem);
  1475. childItem = tree.GetNextSiblingItem(childItem);
  1476. }
  1477. }
  1478. }
  1479. /**
  1480. * Build the lookup tree for a given item and all of its children.
  1481. * @param item The item to start from
  1482. */
  1483. void MaterialTreeView::BuildLookupTrees(HTREEITEM item) {
  1484. //Add my quicktree item
  1485. idStr qt = GetQuicktreePath(item);
  1486. quickTree.Set(qt, item);
  1487. CTreeCtrl& tree = GetTreeCtrl();
  1488. if(tree.ItemHasChildren(item)) {
  1489. HTREEITEM childItem = tree.GetChildItem(item);
  1490. while(childItem != NULL) {
  1491. DWORD childType = tree.GetItemData(childItem);
  1492. if(childType == TYPE_MATERIAL_FOLDER) {
  1493. //Recursively call this method for all my child folders
  1494. BuildLookupTrees(childItem);
  1495. }
  1496. childItem = tree.GetNextSiblingItem(childItem);
  1497. }
  1498. }
  1499. }
  1500. /**
  1501. * Returns the quicktree path for a given item.
  1502. * @param item The item for which to generate the quicktree path
  1503. */
  1504. idStr MaterialTreeView::GetQuicktreePath(HTREEITEM item) {
  1505. CTreeCtrl& tree = GetTreeCtrl();
  1506. idStr qt = "";
  1507. HTREEITEM pathItem = item;
  1508. while(pathItem != NULL) {
  1509. qt = "/" + idStr(tree.GetItemText(pathItem)) + qt;
  1510. pathItem = tree.GetParentItem(pathItem);
  1511. }
  1512. return qt;
  1513. }