bar.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. #include "door.h"
  2. #include "utf8.h"
  3. #include <iomanip>
  4. #include <iostream>
  5. namespace door {
  6. BarLine::BarLine(int width)
  7. : Line("", width), barstyle{BarStyle::SOLID},
  8. current_percent{0}, length{width} {
  9. init();
  10. }
  11. BarLine::BarLine(int width, BarStyle style)
  12. : Line("", width), barstyle{style}, current_percent{0}, length{width} {
  13. init();
  14. }
  15. BarLine::BarLine(int width, BarStyle style, ANSIColor c)
  16. : Line("", width, c), barstyle{style}, current_percent{0}, length{width} {
  17. init();
  18. }
  19. void BarLine::init(void) {
  20. // set update function.
  21. door::updateFunction barLineUpdate = [this](void) -> std::string {
  22. if (!colorRange.empty()) {
  23. // Ok, there is a range, so test for it.
  24. ANSIColor ac;
  25. // unsigned long p;
  26. for (auto bc : colorRange) {
  27. if (current_percent <= bc.percent) {
  28. ac = bc.c;
  29. // p = bc.percent;
  30. break;
  31. };
  32. }
  33. // cout << "!" << current_percent << "," << p << " ";
  34. setColor(ac);
  35. }
  36. return this->update_bar();
  37. };
  38. setUpdater(barLineUpdate);
  39. update();
  40. }
  41. void BarLine::watch(float &percent) {
  42. door::updateFunction lineWatchUpdate = [this, &percent]() -> std::string {
  43. this->set(percent);
  44. if (!colorRange.empty()) {
  45. // Ok, there is a range, so test for it.
  46. ANSIColor ac;
  47. // unsigned long p;
  48. for (auto bc : colorRange) {
  49. if (current_percent <= bc.percent) {
  50. ac = bc.c;
  51. // p = bc.percent;
  52. break;
  53. };
  54. }
  55. // cout << "!" << current_percent << "," << p << " ";
  56. setColor(ac);
  57. }
  58. return this->update_bar();
  59. };
  60. setUpdater(lineWatchUpdate);
  61. update();
  62. }
  63. void BarLine::watch(int &value, int &max) {
  64. door::updateFunction lineWatchUpdate = [this, &value, &max]() -> std::string {
  65. this->set(value, max);
  66. if (!colorRange.empty()) {
  67. // Ok, there is a range, so test for it.
  68. ANSIColor ac;
  69. // unsigned long p;
  70. for (auto bc : colorRange) {
  71. if (current_percent <= bc.percent) {
  72. ac = bc.c;
  73. // p = bc.percent;
  74. break;
  75. };
  76. }
  77. // cout << "!" << current_percent << "," << p << " ";
  78. setColor(ac);
  79. }
  80. return this->update_bar();
  81. };
  82. setUpdater(lineWatchUpdate);
  83. update();
  84. }
  85. void BarLine::setStyle(BarStyle s) { barstyle = s; }
  86. void BarLine::set(int value, int max) {
  87. unsigned long percentage = value * 100 * 100 / max;
  88. set(percentage);
  89. }
  90. void BarLine::set(float percent) {
  91. unsigned long percentage = (unsigned long)(percent * 100.0);
  92. set(percentage);
  93. }
  94. void BarLine::set(unsigned long percent) {
  95. current_percent = percent;
  96. update_bar();
  97. }
  98. std::string BarLine::update_bar(void) {
  99. unsigned long step_width;
  100. std::string btext;
  101. switch (barstyle) {
  102. case BarStyle::SOLID:
  103. case BarStyle::PERCENTAGE:
  104. case BarStyle::PERCENT_SPACE: {
  105. step_width = 100 * 100 / length;
  106. int steps = current_percent / step_width;
  107. // number of steps visible.
  108. // for now:
  109. if (door::unicode)
  110. for (int i = 0; i < steps; ++i)
  111. btext.append("\u2588");
  112. else
  113. btext.assign(steps, '\xdb');
  114. for (int x = steps; x < length; ++x)
  115. btext.append(" ");
  116. // line.setText(text);
  117. /*
  118. cout << "percent " << std::setw(5) << current_percent << " : step_width "
  119. << std::setw(5) << step_width << std::setw(5) << steps << " of "
  120. << std::setw(5) << length << " ";
  121. */
  122. if ((barstyle == BarStyle::PERCENTAGE) ||
  123. (barstyle == BarStyle::PERCENT_SPACE)) {
  124. // Put the % text in the text.
  125. std::string percent;
  126. percent = std::to_string(current_percent / 100);
  127. int pos = (length / 2) - 1;
  128. if (percent != "100") {
  129. percent.append(1, '%');
  130. if (percent.length() < 3)
  131. percent.insert(0, " ");
  132. }
  133. if (barstyle == BarStyle::PERCENT_SPACE) {
  134. percent.insert(0, 1, ' ');
  135. percent.append(1, ' ');
  136. pos -= 1;
  137. }
  138. // cout << "[" << percent << "] " << std::setw(3) << pos << " ";
  139. // unicode ... is unipain.
  140. if (door::unicode) {
  141. // handle unicode here
  142. // Find start position, and ending position for the replacement.
  143. const char *cp = btext.c_str();
  144. const char *end = cp;
  145. while (*end != 0)
  146. end++;
  147. for (int i = 0; i < pos; i++) {
  148. utf8::next(cp, end);
  149. }
  150. // find position using unicode position
  151. int unicode_pos = cp - btext.c_str();
  152. const char *cp_len_start = cp;
  153. const char *cp_len = cp;
  154. for (int i = 0; i < (int)percent.length(); i++) {
  155. utf8::next(cp_len, end);
  156. }
  157. int unicode_len = cp_len - cp_len_start;
  158. // cout << " " << std::setw(3) << unicode_pos << " " << std::setw(3) <<
  159. // unicode_len << " ";
  160. btext.replace(unicode_pos, unicode_len, percent);
  161. } else {
  162. btext.replace(pos, percent.length(), percent);
  163. };
  164. }
  165. return btext;
  166. break;
  167. };
  168. case BarStyle::HALF_STEP: {
  169. step_width = 100 * 100 / length;
  170. int steps = current_percent * 2 / step_width;
  171. /*
  172. cout << "percent " << std::setw(5) << current_percent << " : step_width "
  173. << std::setw(5) << step_width << std::setw(5) << steps << " of "
  174. << std::setw(5) << length << " ";
  175. */
  176. if (door::unicode)
  177. for (int i = 0; i < steps / 2; i++)
  178. btext.append("\u2588");
  179. else
  180. btext.assign(steps / 2, '\xdb');
  181. if (steps % 2 == 1) {
  182. if (door::unicode)
  183. btext.append("\u258c");
  184. else
  185. btext.append(1, '\xdd');
  186. steps++;
  187. }
  188. for (int x = steps; x < length * 2; x += 2)
  189. btext.append(" ");
  190. return btext;
  191. break;
  192. }
  193. case BarStyle::GRADIENT: {
  194. step_width = 100 * 100 / length;
  195. int steps = current_percent * 4 / step_width;
  196. /*
  197. cout << "percent " << std::setw(5) << current_percent << " : step_width "
  198. << std::setw(5) << step_width << std::setw(5) << steps << " of "
  199. << std::setw(5) << length << " ";
  200. */
  201. if (door::unicode)
  202. for (int i = 0; i < steps / 4; i++)
  203. btext.append("\u2588");
  204. else
  205. btext.assign(steps / 4, '\xdb');
  206. if (steps % 4 != 0) {
  207. // display the gradient
  208. switch (steps % 4) {
  209. case 1:
  210. if (door::unicode)
  211. btext.append("\u2591");
  212. else
  213. btext.append(1, '\xb0');
  214. break;
  215. case 2:
  216. if (door::unicode)
  217. btext.append("\u2592");
  218. else
  219. btext.append(1, '\xb1');
  220. break;
  221. case 3:
  222. if (door::unicode)
  223. btext.append("\u2593");
  224. else
  225. btext.append(1, '\xb2');
  226. break;
  227. }
  228. while (steps % 4 != 0)
  229. steps++;
  230. }
  231. for (int x = steps; x < length * 4; x += 4)
  232. btext.append(" ");
  233. return btext;
  234. break;
  235. }
  236. }
  237. // cout << "percent" << current_percent << " : " << steps << " of " << length
  238. // << " " << std::endl;
  239. return btext;
  240. }
  241. void BarLine::setColorRange(vector<BarColorRange> bcr) { colorRange = bcr; }
  242. } // namespace door