#include "drawtypes/layouticonset.hpp" POLYBAR_NS namespace drawtypes { layouticonset::layouticonset(label_t&& default_icon) : m_default_icon(default_icon) {} bool layouticonset::add(const string& layout, const string& variant, label_t&& icon) { if (layout == VARIANT_ANY && variant == VARIANT_ANY) { return false; } m_layout_icons.emplace_back(layout, variant, icon); return true; } label_t layouticonset::get(const string& layout, const string& variant) const { // The layout, variant are matched against defined icons in that order: // 1. perfect match on layout and perfect match on variant (ex: us;Colemak;) // 2. perfect match on layout and case insensitive search on variant (ex: us;coLEmAk;) // 3. perfect match on layout and the any variant '_' (ex: us; or us;_;) // 4. any layout for icon and perfect match on variant (ex: _;Colemak;) // 5. any layout for icon and case insensitive search on variant (ex: _;coLEmAk;) // 6. no match at all => default icon if defined /* * The minimal case that was matched. * Once a case is matched, this is updated and no case with the same or higher number can be matched again. */ int min_case = 6; // Case 6: initializing with default label_t icon = m_default_icon; for (auto it : m_layout_icons) { const string& icon_layout = std::get<0>(it); const string& icon_variant = std::get<1>(it); label_t icon_label = std::get<2>(it); bool is_variant_match = icon_variant == variant; bool is_variant_any = icon_variant == VARIANT_ANY; bool is_variant_match_fuzzy = !is_variant_any && !icon_variant.empty() && string_util::contains_ignore_case(variant, icon_variant); // Which of the 6 match cases is matched here. int current_case = 6; if (icon_layout == layout) { if (is_variant_match) { // Case 1 current_case = 1; } else if (is_variant_match_fuzzy) { // Case 2 current_case = 2; } else if (is_variant_any) { // Case 3 current_case = 3; } } else if (icon_layout == VARIANT_ANY) { if (is_variant_match) { // Case 4 current_case = 4; } else if (is_variant_match_fuzzy) { // Case 5 current_case = 5; } } /* * We matched with a higher priority than before -> update icon. */ if (current_case < min_case) { icon = icon_label; min_case = current_case; } if (current_case == 1) { // Case 1: perfect match, we can break early break; } } return icon; } bool layouticonset::contains(const string& layout, const string& variant) const { for (auto it : m_layout_icons) { const string& icon_layout = std::get<0>(it); const string& icon_variant = std::get<1>(it); if (icon_layout == layout && icon_variant == variant) { return true; } } return false; } } // namespace drawtypes POLYBAR_NS_END