Без опису
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. using System.Linq;
  2. using System.Text;
  3. using System.Text.RegularExpressions;
  4. using UnityEngine;
  5. namespace XCharts.Runtime
  6. {
  7. public static class FormatterHelper
  8. {
  9. public const string PH_NN = "\n";
  10. private static Regex s_Regex = new Regex(@"{([a-h|.]\d*)(:\d+(-\d+)?)?(:[c-g|x|p|r]\d*|:0\.#*)?}", RegexOptions.IgnoreCase);
  11. private static Regex s_RegexSub = new Regex(@"(0\.#*)|(\d+-\d+)|(\w+)|(\.)", RegexOptions.IgnoreCase);
  12. private static Regex s_RegexN = new Regex(@"^\d+", RegexOptions.IgnoreCase);
  13. private static Regex s_RegexN_N = new Regex(@"\d+-\d+", RegexOptions.IgnoreCase);
  14. private static Regex s_RegexFn = new Regex(@"[c-g|x|p|r]\d*|0\.#*", RegexOptions.IgnoreCase);
  15. private static Regex s_RegexNewLine = new Regex(@"[\\|/]+n|</br>|<br>|<br/>", RegexOptions.IgnoreCase);
  16. private static Regex s_RegexForAxisLabel = new Regex(@"{value(:[c-g|x|p|r]\d*)?}", RegexOptions.IgnoreCase);
  17. private static Regex s_RegexSubForAxisLabel = new Regex(@"(value)|([c-g|x|p|r]\d*)", RegexOptions.IgnoreCase);
  18. private static Regex s_RegexForSerieLabel = new Regex(@"{[a-h|\.]\d*(:[c-g|x|p|r]\d*)?}", RegexOptions.IgnoreCase);
  19. private static Regex s_RegexSubForSerieLabel = new Regex(@"(\.)|([a-h]\d*)|([c-g|x|p|r]\d*)", RegexOptions.IgnoreCase);
  20. public static bool NeedFormat(string content)
  21. {
  22. return content.IndexOf('{') >= 0;
  23. }
  24. /// <summary>
  25. /// 替换字符串中的通配符,支持的通配符有{.}、{a}、{b}、{c}、{d}、{e}、{f}、{g}、{h}。
  26. /// </summary>
  27. /// <param name="content">要替换的字符串</param>
  28. /// <param name="dataIndex">选中的数据项serieData索引</param>
  29. /// <param name="numericFormatter">默认的数字格式化</param>
  30. /// <param name="serie">选中的serie</param>
  31. /// <param name="series">所有serie</param>
  32. /// <param name="theme">用来获取指定index的颜色</param>
  33. /// <param name="category">选中的类目,一般用在折线图和柱状图</param>
  34. /// <returns></returns>
  35. public static bool ReplaceContent(ref string content, int dataIndex, string numericFormatter, Serie serie,
  36. BaseChart chart, string colorName = null)
  37. {
  38. var foundDot = false;
  39. var mc = s_Regex.Matches(content);
  40. foreach (var m in mc)
  41. {
  42. var old = m.ToString();
  43. var args = s_RegexSub.Matches(m.ToString());
  44. var argsCount = args.Count;
  45. if (argsCount <= 0) continue;
  46. int targetIndex = 0;
  47. char p = GetSerieIndex(args[0].ToString(), ref targetIndex);
  48. if (targetIndex >= 0)
  49. {
  50. serie = chart.GetSerie(targetIndex);
  51. if (serie == null) continue;
  52. }
  53. else if (serie != null)
  54. {
  55. targetIndex = serie.index;
  56. }
  57. else
  58. {
  59. serie = chart.GetSerie(0);
  60. targetIndex = 0;
  61. }
  62. if (serie == null) continue;
  63. if (p == '.' || p == 'h' || p == 'H')
  64. {
  65. var bIndex = dataIndex;
  66. if (argsCount >= 2)
  67. {
  68. var args1Str = args[1].ToString();
  69. if (s_RegexN.IsMatch(args1Str)) bIndex = int.Parse(args1Str);
  70. }
  71. var color = string.IsNullOrEmpty(colorName) ?
  72. (Color) chart.GetMarkColor(serie, serie.GetSerieData(bIndex)) :
  73. SeriesHelper.GetNameColor(chart, bIndex, colorName);
  74. if (p == '.')
  75. {
  76. content = content.Replace(old, ChartCached.ColorToDotStr(color));
  77. foundDot = true;
  78. }
  79. else
  80. {
  81. content = content.Replace(old, "#" + ChartCached.ColorToStr(color));
  82. }
  83. }
  84. else if (p == 'a' || p == 'A')
  85. {
  86. if (argsCount == 1)
  87. {
  88. content = content.Replace(old, serie.serieName);
  89. }
  90. }
  91. else if (p == 'b' || p == 'B' || p == 'e' || p == 'E')
  92. {
  93. var bIndex = dataIndex;
  94. if (argsCount >= 2)
  95. {
  96. var args1Str = args[1].ToString();
  97. if (s_RegexN.IsMatch(args1Str)) bIndex = int.Parse(args1Str);
  98. }
  99. var needCategory = (p != 'e' && p != 'E') && (serie is Line || serie is Bar);
  100. if (needCategory)
  101. {
  102. var category = chart.GetTooltipCategory(dataIndex, serie);
  103. content = content.Replace(old, category);
  104. }
  105. else
  106. {
  107. var serieData = serie.GetSerieData(bIndex);
  108. content = content.Replace(old, serieData.name);
  109. }
  110. }
  111. else if (p == 'g' || p == 'G')
  112. {
  113. content = content.Replace(old, ChartCached.NumberToStr(serie.dataCount, ""));
  114. }
  115. else if (p == 'c' || p == 'C' || p == 'd' || p == 'D' || p == 'f' || p == 'f')
  116. {
  117. var isPercent = p == 'd' || p == 'D';
  118. var isTotal = p == 'f' || p == 'f';
  119. var bIndex = dataIndex;
  120. var dimensionIndex = -1;
  121. if (argsCount >= 2)
  122. {
  123. var args1Str = args[1].ToString();
  124. if (s_RegexFn.IsMatch(args1Str))
  125. {
  126. numericFormatter = args1Str;
  127. }
  128. else if (s_RegexN_N.IsMatch(args1Str))
  129. {
  130. var temp = args1Str.Split('-');
  131. bIndex = int.Parse(temp[0]);
  132. dimensionIndex = int.Parse(temp[1]);
  133. }
  134. else if (s_RegexN.IsMatch(args1Str))
  135. {
  136. dimensionIndex = int.Parse(args1Str);
  137. }
  138. else
  139. {
  140. Debug.LogError("unmatch:" + args1Str);
  141. continue;
  142. }
  143. }
  144. if (argsCount >= 3)
  145. {
  146. numericFormatter = args[2].ToString();
  147. }
  148. if (dimensionIndex == -1) dimensionIndex = 1;
  149. if (numericFormatter == string.Empty)
  150. {
  151. numericFormatter = SerieHelper.GetNumericFormatter(serie, serie.GetSerieData(bIndex), "");
  152. }
  153. var value = serie.GetData(bIndex, dimensionIndex);
  154. if (isPercent)
  155. {
  156. var total = serie.GetDataTotal(dimensionIndex, serie.GetSerieData(bIndex));
  157. var percent = total == 0 ? 0 : value / serie.yTotal * 100;
  158. content = content.Replace(old, ChartCached.FloatToStr(percent, numericFormatter));
  159. }
  160. else if (isTotal)
  161. {
  162. var total = serie.GetDataTotal(dimensionIndex, serie.GetSerieData(bIndex));
  163. content = content.Replace(old, ChartCached.FloatToStr(total, numericFormatter));
  164. }
  165. else
  166. {
  167. content = content.Replace(old, ChartCached.FloatToStr(value, numericFormatter));
  168. }
  169. }
  170. }
  171. content = s_RegexNewLine.Replace(content, PH_NN);
  172. return foundDot;
  173. }
  174. public static void ReplaceSerieLabelContent(ref string content, string numericFormatter, int dataCount, double value, double total,
  175. string serieName, string category, string dataName, Color color, SerieData serieData)
  176. {
  177. var mc = s_RegexForSerieLabel.Matches(content);
  178. foreach (var m in mc)
  179. {
  180. var old = m.ToString();
  181. var args = s_RegexSubForSerieLabel.Matches(old);
  182. var argsCount = args.Count;
  183. if (argsCount <= 0) continue;
  184. var pstr = args[0].ToString();
  185. var p = pstr.ElementAt(0);
  186. var pIndex = -1;
  187. if (pstr.Length > 1)
  188. {
  189. int.TryParse(pstr.Substring(1, pstr.Length - 1), out pIndex);
  190. }
  191. if (argsCount >= 2)
  192. {
  193. numericFormatter = args[1].ToString();
  194. }
  195. if (p == '.')
  196. {
  197. content = content.Replace(old, ChartCached.ColorToDotStr(color));
  198. }
  199. else if (p == 'a' || p == 'A')
  200. {
  201. content = content.Replace(old, serieName);
  202. }
  203. else if (p == 'b' || p == 'B')
  204. {
  205. content = content.Replace(old, category);
  206. }
  207. else if (p == 'e' || p == 'E')
  208. {
  209. content = content.Replace(old, dataName);
  210. }
  211. else if (p == 'd' || p == 'D')
  212. {
  213. var rate = pIndex >= 0 && serieData != null ?
  214. (value == 0 ? 0 : serieData.GetData(pIndex) / value * 100) :
  215. (total == 0 ? 0 : value / total * 100);
  216. content = content.Replace(old, ChartCached.NumberToStr(rate, numericFormatter));
  217. }
  218. else if (p == 'c' || p == 'C')
  219. {
  220. if (pIndex >= 0 && serieData != null)
  221. content = content.Replace(old, ChartCached.NumberToStr(serieData.GetData(pIndex), numericFormatter));
  222. else
  223. content = content.Replace(old, ChartCached.NumberToStr(value, numericFormatter));
  224. }
  225. else if (p == 'f' || p == 'f')
  226. {
  227. content = content.Replace(old, ChartCached.NumberToStr(total, numericFormatter));
  228. }
  229. else if (p == 'g' || p == 'G')
  230. {
  231. content = content.Replace(old, ChartCached.NumberToStr(dataCount, numericFormatter));
  232. }
  233. else if (p == 'h' || p == 'H')
  234. {
  235. content = content.Replace(old, "#" + ChartCached.ColorToStr(color));
  236. }
  237. }
  238. content = TrimAndReplaceLine(content);
  239. }
  240. private static char GetSerieIndex(string strType, ref int index)
  241. {
  242. index = -1;
  243. if (strType.Length > 1)
  244. {
  245. if (!int.TryParse(strType.Substring(1), out index))
  246. {
  247. index = -1;
  248. }
  249. }
  250. return strType.ElementAt(0);
  251. }
  252. public static string TrimAndReplaceLine(StringBuilder sb)
  253. {
  254. return TrimAndReplaceLine(sb.ToString());
  255. }
  256. public static string TrimAndReplaceLine(string content)
  257. {
  258. return s_RegexNewLine.Replace(content.Trim(), PH_NN);
  259. }
  260. public static void ReplaceAxisLabelContent(ref string content, string numericFormatter, double value)
  261. {
  262. var mc = s_RegexForAxisLabel.Matches(content);
  263. foreach (var m in mc)
  264. {
  265. var old = m.ToString();
  266. var args = s_RegexSubForAxisLabel.Matches(m.ToString());
  267. var argsCount = args.Count;
  268. if (argsCount <= 0) continue;
  269. if (argsCount >= 2)
  270. {
  271. numericFormatter = args[1].ToString();
  272. }
  273. content = content.Replace(old, ChartCached.FloatToStr(value, numericFormatter));
  274. }
  275. content = TrimAndReplaceLine(content);
  276. }
  277. public static void ReplaceAxisLabelContent(ref string content, string value)
  278. {
  279. var mc = s_RegexForAxisLabel.Matches(content);
  280. foreach (var m in mc)
  281. {
  282. var old = m.ToString();
  283. var args = s_RegexSubForAxisLabel.Matches(m.ToString());
  284. var argsCount = args.Count;
  285. if (argsCount <= 0) continue;
  286. content = content.Replace(old, value);
  287. }
  288. content = TrimAndReplaceLine(content);
  289. }
  290. }
  291. }