#pragma once #include "common.hpp" #include "components/builder.hpp" #include "components/config.hpp" #include "components/types.hpp" #include "drawtypes/label.hpp" #include "utils/mixins.hpp" LEMONBUDDY_NS namespace drawtypes { class progressbar : public non_copyable_mixin { public: explicit progressbar( const bar_settings& bar, int width, string format, bool lazy_builder_closing) : m_builder(make_unique(bar, lazy_builder_closing)) , m_format(format) , m_width(width) {} explicit progressbar(const bar_settings& bar, int width, bool lazy_builder_closing = true) : progressbar(bar, width, "", lazy_builder_closing) {} void set_fill(icon_t&& fill) { m_fill = forward(fill); } void set_empty(icon_t&& empty) { m_empty = forward(empty); } void set_indicator(icon_t&& indicator) { m_indicator = forward(indicator); } void set_gradient(bool mode) { m_gradient = mode; } void set_colors(vector&& colors) { m_colors = forward(colors); } string output(float percentage, bool floor_percentage = false) { if (m_colors.empty()) m_colors.emplace_back(m_fill->m_foreground); float add = floor_percentage ? 0 : 0.5; int fill_width = (int)m_width * percentage / 100 + add; int empty_width = m_width - fill_width; int color_step = m_width / m_colors.size() + 0.5f; auto output = string(m_format); if (m_indicator && *m_indicator) { if (empty_width == 1) empty_width = 0; else if (fill_width == 0) empty_width--; else fill_width--; } if (!m_gradient) { auto color = m_colors.size() * percentage / 100; if (color >= m_colors.size()) color = 0; m_fill->m_foreground = m_colors[color - 1]; while (fill_width--) m_builder->node(m_fill); } else { int i = 0; for (auto color : m_colors) { i += 1; int j = 0; if ((i - 1) * color_step >= fill_width) break; m_fill->m_foreground = color; while (j++ < color_step && (i - 1) * color_step + j <= fill_width) m_builder->node(m_fill); } } output = string_util::replace_all(output, "%fill%", m_builder->flush()); m_builder->node(m_indicator); output = string_util::replace_all(output, "%indicator%", m_builder->flush()); while (empty_width--) m_builder->node(m_empty); output = string_util::replace_all(output, "%empty%", m_builder->flush()); return output; } protected: unique_ptr m_builder; vector m_colors; string m_format; unsigned int m_width; bool m_gradient = false; icon_t m_fill; icon_t m_empty; icon_t m_indicator; }; using progressbar_t = shared_ptr; inline auto get_config_bar(const bar_settings& bar, const config& conf, string section, string name = "bar", bool lazy_builder_closing = true) { progressbar_t p; name = string_util::ltrim(string_util::rtrim(name, '>'), '<'); auto width = conf.get(section, name + "-width"); auto format = conf.get(section, name + "-format", "%fill%%indicator%%empty%"); if (format.empty()) p.reset(new progressbar(bar, width, lazy_builder_closing)); else p.reset(new progressbar(bar, width, format, lazy_builder_closing)); p->set_gradient(conf.get(section, name + "-gradient", true)); p->set_colors(conf.get_list(section, name + "-foreground", {})); p->set_indicator(get_config_icon( conf, section, name + "-indicator", format.find("%indicator%") != string::npos, "")); p->set_fill( get_config_icon(conf, section, name + "-fill", format.find("%fill%") != string::npos, "")); p->set_empty(get_config_icon( conf, section, name + "-empty", format.find("%empty%") != string::npos, "")); return p; } } LEMONBUDDY_NS_END