lines.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. #include "door.h"
  2. #include "utf8.h"
  3. /**
  4. * @file
  5. * @brief Line
  6. */
  7. namespace door {
  8. #ifdef EXPERIMENTAL
  9. BasicLine::BasicLine(std::string txt) : text{txt}, hasColor{false} {}
  10. BasicLine::BasicLine(std::string txt, ANSIColor c)
  11. : text{txt}, hasColor{true}, color{c} {}
  12. bool BasicLine::hasRender(void) {
  13. if (render)
  14. return true;
  15. return false;
  16. }
  17. void BasicLine::setText(std::string txt) { text = txt; }
  18. void BasicLine::setColor(ANSIColor c) {
  19. color = c;
  20. hasColor = true;
  21. }
  22. void BasicLine::setRender(renderFunction rf) { render = rf; }
  23. void BasicLine::setUpdater(updateFunction uf) { updater = uf; }
  24. /**
  25. * Update BasicLine, if we have an updater.
  26. *
  27. * If we have an updater, call it. If the text is different,
  28. * update setText() and return true.
  29. * Otherwise false.
  30. *
  31. * This doesn't detect changes (like if the render has been changed, for
  32. * example)
  33. *
  34. * @return bool
  35. */
  36. bool BasicLine::update(void) {
  37. if (updater) {
  38. std::string temp = updater();
  39. if (temp == text)
  40. return false;
  41. setText(temp);
  42. return true;
  43. }
  44. return false;
  45. }
  46. /**
  47. * Output Line
  48. *
  49. * This looks for padding and paddingColor.
  50. * This uses the render function if set.
  51. *
  52. * @param os std::ostream
  53. * @param l const BasicLine &
  54. * @return std::ostream&
  55. */
  56. std::ostream &operator<<(std::ostream &os, const BasicLine &l) {
  57. if (l.render) {
  58. // This has a renderer. Use it.
  59. Render r = l.render(l.text);
  60. r.output(os);
  61. } else {
  62. if (l.hasColor) {
  63. os << l.color;
  64. };
  65. os << l.text;
  66. }
  67. return os;
  68. }
  69. MultiLine::MultiLine(){};
  70. void MultiLine::append(std::shared_ptr<BasicLine> bl) { lines.push_back(bl); }
  71. bool MultiLine::update() {
  72. bool updated = false;
  73. for (auto line : lines) {
  74. if (line->update())
  75. updated = true;
  76. }
  77. return updated;
  78. }
  79. /**
  80. * Output Line
  81. *
  82. * This looks for padding and paddingColor.
  83. * This uses the render function if set.
  84. *
  85. * @param os std::ostream
  86. * @param ml const MultiLine &
  87. * @return std::ostream&
  88. */
  89. std::ostream &operator<<(std::ostream &os, const MultiLine &ml) {
  90. for (auto line : ml.lines) {
  91. os << *line;
  92. }
  93. return os;
  94. }
  95. #endif
  96. /**
  97. * Construct a new Line:: Line object with
  98. * string and total width.
  99. *
  100. * @param txt std::string
  101. * @param width int
  102. */
  103. Line::Line(const std::string &txt, int w) : text{txt}, width{w} {
  104. hasColor = false;
  105. }
  106. Line::Line(const std::string &txt, int w, ANSIColor c)
  107. : text{txt}, color{c}, width{w} {
  108. hasColor = true;
  109. }
  110. Line::Line(const char *txt, int w, ANSIColor c)
  111. : text{txt}, color{c}, width{w} {
  112. hasColor = true;
  113. }
  114. Line::Line(const std::string &txt, int w, renderFunction rf)
  115. : text{txt}, render{rf}, width{w} {
  116. hasColor = false;
  117. }
  118. Line::Line(const char *txt, int w, renderFunction rf)
  119. : text{txt}, render{rf}, width{w} {
  120. hasColor = false;
  121. }
  122. /**
  123. * Construct a new Line:: Line object with
  124. * const char * and total width
  125. *
  126. * @param txt const char *
  127. * @param width int
  128. */
  129. Line::Line(const char *txt, int w) : text{txt}, width{w} { hasColor = false; }
  130. /**
  131. * Construct a new Line:: Line object from an
  132. * existing Line
  133. *
  134. * @param rhs const Line&
  135. */
  136. Line::Line(const Line &rhs)
  137. : text{rhs.text}, hasColor{rhs.hasColor}, color{rhs.color},
  138. padding{rhs.padding}, paddingColor{rhs.paddingColor} {
  139. if (rhs.render) {
  140. render = rhs.render;
  141. }
  142. if (rhs.updater) {
  143. updater = rhs.updater;
  144. }
  145. width = rhs.width;
  146. }
  147. Line::Line(Line &&rhs)
  148. : text{rhs.text}, hasColor{rhs.hasColor}, color{rhs.color},
  149. padding{rhs.padding}, paddingColor{rhs.paddingColor} {
  150. if (rhs.render)
  151. render = rhs.render;
  152. if (rhs.updater)
  153. updater = rhs.updater;
  154. width = rhs.width;
  155. }
  156. /**
  157. * Has a render function been set?
  158. *
  159. * @return bool
  160. */
  161. bool Line::hasRender(void) {
  162. if (render) {
  163. return true;
  164. } else {
  165. return false;
  166. }
  167. }
  168. /**
  169. * Return total length of Line
  170. *
  171. * text.length + 2 * padding length
  172. *
  173. * @return int
  174. */
  175. int Line::length(void) {
  176. if (!padding.empty()) {
  177. if (unicode) {
  178. return utf8::distance(padding.begin(), padding.end()) * 2 +
  179. utf8::distance(text.begin(), text.end());
  180. } else {
  181. return padding.length() * 2 + text.length();
  182. }
  183. }
  184. if (unicode) {
  185. return utf8::distance(text.begin(), text.end());
  186. } else {
  187. return text.length();
  188. }
  189. }
  190. /**
  191. * Make text the given width by padding string with spaces.
  192. *
  193. * @param width int
  194. */
  195. void Line::fit(void) {
  196. int need;
  197. if (door::unicode)
  198. need = width - utf8::distance(text.begin(), text.end());
  199. else
  200. need = width - text.length();
  201. need -= padding.length() * 2;
  202. if (need > 0) {
  203. text.append(std::string(need, ' '));
  204. }
  205. }
  206. /**
  207. * Set Line text.
  208. * @param txt std::string
  209. */
  210. void Line::setText(std::string &txt) { text = txt; }
  211. /**
  212. * Set Line text.
  213. * @param txt const char *
  214. */
  215. void Line::setText(const char *txt) { text = txt; }
  216. /**
  217. * set padding (color and text)
  218. *
  219. * @param padstring std::string
  220. * @param padColor ANSIColor
  221. */
  222. void Line::setPadding(std::string &padstring, ANSIColor padColor) {
  223. padding = padstring;
  224. paddingColor = padColor;
  225. }
  226. /**
  227. * set padding (color and text)
  228. *
  229. * @param padstring const char *
  230. * @param padColor ANSIColor
  231. */
  232. void Line::setPadding(const char *padstring, ANSIColor padColor) {
  233. padding = padstring;
  234. paddingColor = padColor;
  235. }
  236. /**
  237. * set color
  238. *
  239. * @param c ANSIColor
  240. */
  241. void Line::setColor(ANSIColor c) {
  242. color = c;
  243. hasColor = true;
  244. }
  245. /**
  246. * set render
  247. *
  248. * Set the renderFunction to use for this Line. This
  249. * replaces the colorizer.
  250. * @param rf renderFunction
  251. */
  252. void Line::setRender(renderFunction rf) { render = rf; }
  253. /**
  254. * set updater function
  255. *
  256. * This can update the line text when called.
  257. * @todo Define an updateFunction.
  258. * @param newUpdater updateFunction
  259. */
  260. void Line::setUpdater(updateFunction newUpdater) { updater = newUpdater; }
  261. std::string Line::debug(void) {
  262. std::string desc;
  263. desc = "Line(";
  264. desc += text;
  265. desc += "): ";
  266. if (updater) {
  267. desc += "[U]";
  268. }
  269. if (render) {
  270. desc += "[R]";
  271. }
  272. return desc;
  273. }
  274. /**
  275. * Call updater, report if the text was actually changed.
  276. *
  277. * @return bool
  278. */
  279. bool Line::update(void) {
  280. if (updater) {
  281. std::string newText = updater();
  282. // int line_len;
  283. int need;
  284. if (unicode) {
  285. // line_len = utf8::distance(text.begin(), text.end());
  286. need = width - utf8::distance(newText.begin(), newText.end());
  287. } else {
  288. // line_len = text.length();
  289. need = width - newText.length();
  290. }
  291. need -= padding.length() * 2;
  292. if (need > 0) {
  293. newText.append(std::string(need, ' '));
  294. }
  295. if (newText != text) {
  296. text = newText;
  297. return true;
  298. }
  299. }
  300. return false;
  301. }
  302. /**
  303. * Output Line
  304. *
  305. * This looks for padding and paddingColor.
  306. * This uses the render function if set.
  307. *
  308. * @param os std::ostream
  309. * @param l const Line &
  310. * @return std::ostream&
  311. */
  312. std::ostream &operator<<(std::ostream &os, const Line &l) {
  313. // Door *d = dynamic_cast<Door *>(&os);
  314. if (!l.padding.empty()) {
  315. os << l.paddingColor << l.padding;
  316. }
  317. if (l.render) {
  318. // This has a renderer. Use it.
  319. Render r = l.render(l.text);
  320. r.output(os);
  321. } else {
  322. if (l.hasColor) {
  323. os << l.color;
  324. };
  325. os << l.text;
  326. }
  327. if (!l.padding.empty()) {
  328. os << l.paddingColor << l.padding;
  329. }
  330. return os;
  331. }
  332. } // namespace door