#pragma once #include "common.hpp" #include "components/config.hpp" #include "components/types.hpp" #include "config.hpp" #include "drawtypes/label.hpp" #include "utils/math.hpp" #include "utils/string.hpp" LEMONBUDDY_NS #define DEFAULT_SPACING -1 #ifndef BUILDER_SPACE_TOKEN #define BUILDER_SPACE_TOKEN "%__" #endif using namespace drawtypes; class builder { public: explicit builder(const bar_settings bar, bool lazy = true) : m_bar(bar), m_lazy(lazy) {} void set_lazy(bool mode) { m_lazy = mode; } string flush() { if (m_lazy) { while (m_counters[syntaxtag::A] > 0) cmd_close(true); while (m_counters[syntaxtag::B] > 0) background_close(true); while (m_counters[syntaxtag::F] > 0) color_close(true); while (m_counters[syntaxtag::T] > 0) font_close(true); while (m_counters[syntaxtag::U] > 0) line_color_close(true); while (m_counters[syntaxtag::u] > 0) underline_close(true); while (m_counters[syntaxtag::o] > 0) overline_close(true); } string output = m_output.data(); // reset values m_output.clear(); for (auto& counter : m_counters) counter.second = 0; for (auto& value : m_colors) value.second = ""; m_fontindex = 1; return string_util::replace_all(output, string{BUILDER_SPACE_TOKEN}, " "); } void append(string text) { string str(text); auto len = str.length(); if (len > 2 && str[0] == '"' && str[len - 1] == '"') m_output += str.substr(1, len - 2); else m_output += str; } void node(string str, bool add_space = false) { string::size_type n, m; string s(str); while (true) { if (s.empty()) { break; } else if ((n = s.find("%{F-}")) == 0) { color_close(!m_lazy); s.erase(0, 5); } else if ((n = s.find("%{F#")) == 0 && (m = s.find("}")) != string::npos) { if (m - n - 4 == 2) color_alpha(s.substr(n + 3, m - 3)); else color(s.substr(n + 3, m - 3)); s.erase(n, m + 1); } else if ((n = s.find("%{B-}")) == 0) { background_close(!m_lazy); s.erase(0, 5); } else if ((n = s.find("%{B#")) == 0 && (m = s.find("}")) != string::npos) { background(s.substr(n + 3, m - 3)); s.erase(n, m + 1); } else if ((n = s.find("%{T-}")) == 0) { font_close(!m_lazy); s.erase(0, 5); } else if ((n = s.find("%{T")) == 0 && (m = s.find("}")) != string::npos) { font(std::atoi(s.substr(n + 3, m - 3).c_str())); s.erase(n, m + 1); } else if ((n = s.find("%{U-}")) == 0) { line_color_close(!m_lazy); s.erase(0, 5); } else if ((n = s.find("%{U#")) == 0 && (m = s.find("}")) != string::npos) { line_color(s.substr(n + 3, m - 3)); s.erase(n, m + 1); } else if ((n = s.find("%{+u}")) == 0) { underline(); s.erase(0, 5); } else if ((n = s.find("%{+o}")) == 0) { overline(); s.erase(0, 5); } else if ((n = s.find("%{-u}")) == 0) { underline_close(true); s.erase(0, 5); } else if ((n = s.find("%{-o}")) == 0) { overline_close(true); s.erase(0, 5); } else if ((n = s.find("%{A}")) == 0) { cmd_close(true); s.erase(0, 4); } else if ((n = s.find("%{")) == 0 && (m = s.find("}")) != string::npos) { append(s.substr(n, m + 1)); s.erase(n, m + 1); } else if ((n = s.find("%{")) > 0) { append(s.substr(0, n)); s.erase(0, n); } else break; } if (!s.empty()) append(s); if (add_space) space(); } void node(string str, int font_index, bool add_space = false) { font(font_index); node(str, add_space); font_close(); } // void node(progressbar_t bar, float perc, bool add_space = false) { // if (!bar) // return; // node(bar->get_output(math_util::cap(0, 100, perc)), add_space); // } void node(label_t label, bool add_space = false) { if (!label || !*label) return; auto text = label->get(); if (label->m_maxlen > 0 && text.length() > label->m_maxlen) { text = text.substr(0, label->m_maxlen) + "..."; } if ((label->m_overline.empty() && m_counters[syntaxtag::o] > 0) || (m_counters[syntaxtag::o] > 0 && label->m_margin > 0)) overline_close(true); if ((label->m_underline.empty() && m_counters[syntaxtag::u] > 0) || (m_counters[syntaxtag::u] > 0 && label->m_margin > 0)) underline_close(true); if (label->m_margin > 0) space(label->m_margin); if (!label->m_overline.empty()) overline(label->m_overline); if (!label->m_underline.empty()) underline(label->m_underline); background(label->m_background); color(label->m_foreground); if (label->m_padding > 0) space(label->m_padding); node(text, label->m_font, add_space); if (label->m_padding > 0) space(label->m_padding); color_close(m_lazy && label->m_margin > 0); background_close(m_lazy && label->m_margin > 0); if (!label->m_underline.empty() || (label->m_margin > 0 && m_counters[syntaxtag::u] > 0)) underline_close(m_lazy && label->m_margin > 0); if (!label->m_overline.empty() || (label->m_margin > 0 && m_counters[syntaxtag::o] > 0)) overline_close(m_lazy && label->m_margin > 0); if (label->m_margin > 0) space(label->m_margin); } // void node(ramp_t ramp, float perc, bool add_space = false) { // if (!ramp) // return; // node(ramp->get_by_percentage(math_util::cap(0, 100, perc)), add_space); // } // void node(animation_t animation, bool add_space = false) { // if (!animation) // return; // node(animation->get(), add_space); // } void offset(int pixels = 0) { if (pixels != 0) tag_open('O', std::to_string(pixels)); } void space(int width = DEFAULT_SPACING) { if (width == DEFAULT_SPACING) width = m_bar.spacing; if (width <= 0) return; string str(width, ' '); append(str); } void remove_trailing_space(int width = DEFAULT_SPACING) { if (width == DEFAULT_SPACING) width = m_bar.spacing; if (width <= 0) return; string::size_type spacing = width; string str(spacing, ' '); if (m_output.length() >= spacing && m_output.substr(m_output.length() - spacing) == str) m_output = m_output.substr(0, m_output.length() - spacing); } void invert() { tag_open('R', ""); } void font(int index) { if (index <= 0 && m_counters[syntaxtag::T] > 0) font_close(true); if (index <= 0 || index == m_fontindex) return; if (m_lazy && m_counters[syntaxtag::T] > 0) font_close(true); m_counters[syntaxtag::T]++; m_fontindex = index; tag_open('T', std::to_string(index)); } void font_close(bool force = false) { if ((!force && m_lazy) || m_counters[syntaxtag::T] <= 0) return; m_counters[syntaxtag::T]--; m_fontindex = 1; tag_close('T'); } void background(string color) { if (color.length() == 2 || (color.find("#") == 0 && color.length() == 3)) { color = "#" + color.substr(color.length() - 2); auto bg = m_bar.background.hex(); color += bg.substr(bg.length() - (bg.length() < 6 ? 3 : 6)); } else if (color.length() >= 7 && color == "#" + string(color.length() - 1, color[1])) { color = color.substr(0, 4); } if (color.empty() && m_counters[syntaxtag::B] > 0) background_close(true); if (color.empty() || color == m_colors[syntaxtag::B]) return; if (m_lazy && m_counters[syntaxtag::B] > 0) background_close(true); m_counters[syntaxtag::B]++; m_colors[syntaxtag::B] = color; tag_open('B', color); } void background_close(bool force = false) { if ((!force && m_lazy) || m_counters[syntaxtag::B] <= 0) return; m_counters[syntaxtag::B]--; m_colors[syntaxtag::B] = ""; tag_close('B'); } void color(string color_) { auto color(color_); if (color.length() == 2 || (color.find("#") == 0 && color.length() == 3)) { color = "#" + color.substr(color.length() - 2); auto bg = m_bar.foreground.hex(); color += bg.substr(bg.length() - (bg.length() < 6 ? 3 : 6)); } else if (color.length() >= 7 && color == "#" + string(color.length() - 1, color[1])) { color = color.substr(0, 4); } if (color.empty() && m_counters[syntaxtag::F] > 0) color_close(true); if (color.empty() || color == m_colors[syntaxtag::F]) return; if (m_lazy && m_counters[syntaxtag::F] > 0) color_close(true); m_counters[syntaxtag::F]++; m_colors[syntaxtag::F] = color; tag_open('F', color); } void color_alpha(string alpha_) { auto alpha(alpha_); string val = m_bar.foreground.hex(); if (alpha.find("#") == std::string::npos) { alpha = "#" + alpha; } if (alpha.size() == 4) { color(alpha); return; } if (val.size() < 6 && val.size() > 2) { val.append(val.substr(val.size() - 3)); } color((alpha.substr(0, 3) + val.substr(val.size() - 6)).substr(0, 9)); } void color_close(bool force = false) { if ((!force && m_lazy) || m_counters[syntaxtag::F] <= 0) return; m_counters[syntaxtag::F]--; m_colors[syntaxtag::F] = ""; tag_close('F'); } void line_color(string color) { if (color.empty() && m_counters[syntaxtag::U] > 0) line_color_close(true); if (color.empty() || color == m_colors[syntaxtag::U]) return; if (m_lazy && m_counters[syntaxtag::U] > 0) line_color_close(true); m_counters[syntaxtag::U]++; m_colors[syntaxtag::U] = color; tag_open('U', color); } void line_color_close(bool force = false) { if ((!force && m_lazy) || m_counters[syntaxtag::U] <= 0) return; m_counters[syntaxtag::U]--; m_colors[syntaxtag::U] = ""; tag_close('U'); } void overline(string color = "") { if (!color.empty()) line_color(color); if (m_counters[syntaxtag::o] > 0) return; m_counters[syntaxtag::o]++; append("%{+o}"); } void overline_close(bool force = false) { if ((!force && m_lazy) || m_counters[syntaxtag::o] <= 0) return; m_counters[syntaxtag::o]--; append("%{-o}"); } void underline(string color = "") { if (!color.empty()) line_color(color); if (m_counters[syntaxtag::u] > 0) return; m_counters[syntaxtag::u]++; append("%{+u}"); } void underline_close(bool force = false) { if ((!force && m_lazy) || m_counters[syntaxtag::u] <= 0) return; m_counters[syntaxtag::u]--; append("%{-u}"); } void cmd(mousebtn index, string action, bool condition = true) { int button = static_cast(index); if (!condition || action.empty()) return; action = string_util::replace_all(action, ":", "\\:"); action = string_util::replace_all(action, "$", "\\$"); action = string_util::replace_all(action, "}", "\\}"); action = string_util::replace_all(action, "{", "\\{"); action = string_util::replace_all(action, "%", "\x0025"); append("%{A" + std::to_string(button) + ":" + action + ":}"); m_counters[syntaxtag::A]++; } void cmd_close(bool force = false) { if (m_counters[syntaxtag::A] > 0 || force) append("%{A}"); if (m_counters[syntaxtag::A] > 0) m_counters[syntaxtag::A]--; } protected: void tag_open(char tag, string value) { append("%{" + string({tag}) + value + "}"); } void tag_close(char tag) { append("%{" + string({tag}) + "-}"); } private: const bar_settings m_bar; string m_output; bool m_lazy = true; map m_counters{ // clang-format off {syntaxtag::A, 0}, {syntaxtag::B, 0}, {syntaxtag::F, 0}, {syntaxtag::T, 0}, {syntaxtag::U, 0}, {syntaxtag::O, 0}, {syntaxtag::R, 0}, // clang-format on }; map m_colors{ // clang-format off {syntaxtag::B, ""}, {syntaxtag::F, ""}, {syntaxtag::U, ""}, // clang-format on }; int m_fontindex = 1; }; LEMONBUDDY_NS_END