lluicolortable.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:9k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lluicolortable.cpp
  3.  * @brief brief LLUIColorTable class implementation file
  4.  *
  5.  * $LicenseInfo:firstyear=2009&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2009-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include <queue>
  34. #include "lldir.h"
  35. #include "llui.h"
  36. #include "lluicolortable.h"
  37. #include "lluictrlfactory.h"
  38. LLUIColorTable::ColorParams::ColorParams()
  39. : value("value"),
  40. reference("reference")
  41. {
  42. }
  43. LLUIColorTable::ColorEntryParams::ColorEntryParams()
  44. : name("name"),
  45. color("")
  46. {
  47. }
  48. LLUIColorTable::Params::Params()
  49. : color_entries("color")
  50. {
  51. }
  52. void LLUIColorTable::insertFromParams(const Params& p, string_color_map_t& table)
  53. {
  54. // this map will contain all color references after the following loop
  55. typedef std::map<std::string, std::string> string_string_map_t;
  56. string_string_map_t unresolved_refs;
  57. for(LLInitParam::ParamIterator<ColorEntryParams>::const_iterator it = p.color_entries().begin();
  58. it != p.color_entries().end();
  59. ++it)
  60. {
  61. ColorEntryParams color_entry = *it;
  62. if(color_entry.color.value.isChosen())
  63. {
  64. setColor(color_entry.name, color_entry.color.value, table);
  65. }
  66. else
  67. {
  68. unresolved_refs.insert(string_string_map_t::value_type(color_entry.name, color_entry.color.reference));
  69. }
  70. }
  71. // maintain an in order queue of visited references for better debugging of cycles
  72. typedef std::queue<std::string> string_queue_t;
  73. string_queue_t ref_chain;
  74. // maintain a map of the previously visited references in the reference chain for detecting cycles
  75. typedef std::map<std::string, string_string_map_t::iterator> string_color_ref_iter_map_t;
  76. string_color_ref_iter_map_t visited_refs;
  77. // loop through the unresolved color references until there are none left
  78. while(!unresolved_refs.empty())
  79. {
  80. // we haven't visited any references yet
  81. visited_refs.clear();
  82. string_string_map_t::iterator current = unresolved_refs.begin();
  83. string_string_map_t::iterator previous;
  84. while(true)
  85. {
  86. if(current != unresolved_refs.end())
  87. {
  88. // locate the current reference in the previously visited references...
  89. string_color_ref_iter_map_t::iterator visited = visited_refs.lower_bound(current->first);
  90. if(visited != visited_refs.end()
  91.     && !(visited_refs.key_comp()(current->first, visited->first)))
  92. {
  93. // ...if we find the current reference in the previously visited references
  94. // we know that there is a cycle
  95. std::string ending_ref = current->first;
  96. std::string warning("The following colors form a cycle: ");
  97. // warn about the references in the chain and remove them from
  98. // the unresolved references map because they cannot be resolved
  99. for(string_color_ref_iter_map_t::iterator iter = visited_refs.begin();
  100. iter != visited_refs.end();
  101. ++iter)
  102. {
  103. if(!ref_chain.empty())
  104. {
  105. warning += ref_chain.front() + "->";
  106. ref_chain.pop();
  107. }
  108. unresolved_refs.erase(iter->second);
  109. }
  110. llwarns << warning + ending_ref << llendl;
  111. break;
  112. }
  113. else
  114. {
  115. // ...continue along the reference chain
  116. ref_chain.push(current->first);
  117. visited_refs.insert(visited, string_color_ref_iter_map_t::value_type(current->first, current));
  118. }
  119. }
  120. else
  121. {
  122. // since this reference does not refer to another reference it must refer to an
  123. // actual color, lets find it...
  124. string_color_map_t::iterator color_value = mLoadedColors.find(previous->second);
  125. if(color_value != mLoadedColors.end())
  126. {
  127. // ...we found the color, and we now add every reference in the reference chain
  128. // to the color map
  129. for(string_color_ref_iter_map_t::iterator iter = visited_refs.begin();
  130. iter != visited_refs.end();
  131. ++iter)
  132. {
  133. setColor(iter->first, color_value->second, mLoadedColors);
  134. unresolved_refs.erase(iter->second);
  135. }
  136. break;
  137. }
  138. else
  139. {
  140. // ... we did not find the color which imples that the current reference
  141. // references a non-existant color
  142. for(string_color_ref_iter_map_t::iterator iter = visited_refs.begin();
  143. iter != visited_refs.end();
  144. ++iter)
  145. {
  146. llwarns << iter->first << " references a non-existent color" << llendl;
  147. unresolved_refs.erase(iter->second);
  148. }
  149. break;
  150. }
  151. }
  152. // find the next color reference in the reference chain
  153. previous = current;
  154. current = unresolved_refs.find(current->second);
  155. }
  156. }
  157. }
  158. void LLUIColorTable::clear()
  159. {
  160. clearTable(mLoadedColors);
  161. clearTable(mUserSetColors);
  162. }
  163. LLUIColor LLUIColorTable::getColor(const std::string& name, const LLColor4& default_color) const
  164. {
  165. string_color_map_t::const_iterator iter = mUserSetColors.find(name);
  166. if(iter != mUserSetColors.end())
  167. {
  168. return LLUIColor(&iter->second);
  169. }
  170. iter = mLoadedColors.find(name);
  171. if(iter != mLoadedColors.end())
  172. {
  173. return LLUIColor(&iter->second);
  174. }
  175. return  LLUIColor(default_color);
  176. }
  177. // update user color, loaded colors are parsed on initialization
  178. void LLUIColorTable::setColor(const std::string& name, const LLColor4& color)
  179. {
  180. setColor(name, color, mUserSetColors);
  181. setColor(name, color, mLoadedColors);
  182. }
  183. bool LLUIColorTable::loadFromSettings()
  184. {
  185. bool result = false;
  186. std::string default_filename = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "colors.xml");
  187. result |= loadFromFilename(default_filename, mLoadedColors);
  188. std::string current_filename = gDirUtilp->getExpandedFilename(LL_PATH_TOP_SKIN, "colors.xml");
  189. if(current_filename != default_filename)
  190. {
  191. result |= loadFromFilename(current_filename, mLoadedColors);
  192. }
  193. std::string user_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "colors.xml");
  194. loadFromFilename(user_filename, mUserSetColors);
  195. return result;
  196. }
  197. void LLUIColorTable::saveUserSettings() const
  198. {
  199. Params params;
  200. for(string_color_map_t::const_iterator it = mUserSetColors.begin();
  201. it != mUserSetColors.end();
  202. ++it)
  203. {
  204. ColorEntryParams color_entry;
  205. color_entry.name = it->first;
  206. color_entry.color.value = it->second;
  207. params.color_entries.add(color_entry);
  208. }
  209. LLXMLNodePtr output_node = new LLXMLNode("colors", false);
  210. LLXUIParser::instance().writeXUI(output_node, params);
  211. if(!output_node->isNull())
  212. {
  213. const std::string& filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "colors.xml");
  214. LLFILE *fp = LLFile::fopen(filename, "w");
  215. if(fp != NULL)
  216. {
  217. LLXMLNode::writeHeaderToFile(fp);
  218. output_node->writeToFile(fp);
  219. fclose(fp);
  220. }
  221. }
  222. }
  223. bool LLUIColorTable::colorExists(const std::string& color_name) const
  224. {
  225. return ((mLoadedColors.find(color_name) != mLoadedColors.end())
  226.  || (mUserSetColors.find(color_name) != mUserSetColors.end()));
  227. }
  228. void LLUIColorTable::clearTable(string_color_map_t& table)
  229. {
  230. for(string_color_map_t::iterator it = table.begin();
  231. it != table.end();
  232. ++it)
  233. {
  234. it->second = LLColor4::magenta;
  235. }
  236. }
  237. // this method inserts a color into the table if it does not exist
  238. // if the color already exists it changes the color
  239. void LLUIColorTable::setColor(const std::string& name, const LLColor4& color, string_color_map_t& table)
  240. {
  241. string_color_map_t::iterator it = table.lower_bound(name);
  242. if(it != table.end()
  243. && !(table.key_comp()(name, it->first)))
  244. {
  245. it->second = color;
  246. }
  247. else
  248. {
  249. table.insert(it, string_color_map_t::value_type(name, color));
  250. }
  251. }
  252. bool LLUIColorTable::loadFromFilename(const std::string& filename, string_color_map_t& table)
  253. {
  254. LLXMLNodePtr root;
  255. if(!LLXMLNode::parseFile(filename, root, NULL))
  256. {
  257. llwarns << "Unable to parse color file " << filename << llendl;
  258. return false;
  259. }
  260. if(!root->hasName("colors"))
  261. {
  262. llwarns << filename << " is not a valid color definition file" << llendl;
  263. return false;
  264. }
  265. Params params;
  266. LLXUIParser::instance().readXUI(root, params, filename);
  267. if(params.validateBlock())
  268. {
  269. insertFromParams(params, table);
  270. }
  271. else
  272. {
  273. llwarns << filename << " failed to load" << llendl;
  274. return false;
  275. }
  276. return true;
  277. }
  278. void LLUIColorTable::insertFromParams(const Params& p)
  279. {
  280. insertFromParams(p, mUserSetColors);
  281. }
  282. // EOF