yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
icon_browser.cc
Go to the documentation of this file.
2
3#include <cctype>
4#include <cstring>
5#include <string>
6
8#include "imgui/imgui.h"
9#include "imgui/misc/cpp/imgui_stdlib.h"
10
11namespace yaze {
12namespace gui {
13namespace icon_browser_internal {
14
15namespace {
16
17bool ContainsIgnoreCase(const char* haystack, const char* needle,
18 std::size_t needle_len) {
19 if (needle_len == 0)
20 return true;
21 const std::size_t hay_len = std::strlen(haystack);
22 if (hay_len < needle_len)
23 return false;
24 for (std::size_t i = 0; i + needle_len <= hay_len; ++i) {
25 bool match = true;
26 for (std::size_t j = 0; j < needle_len; ++j) {
27 const unsigned char hc = static_cast<unsigned char>(haystack[i + j]);
28 const unsigned char nc = static_cast<unsigned char>(needle[j]);
29 if (std::tolower(hc) != std::tolower(nc)) {
30 match = false;
31 break;
32 }
33 }
34 if (match)
35 return true;
36 }
37 return false;
38}
39
40} // namespace
41
42bool MatchesQuery(const char* search_key, const char* query) {
43 if (query == nullptr || query[0] == '\0')
44 return true;
45 if (search_key == nullptr)
46 return false;
47
48 // Split query on whitespace; every term must be found in search_key.
49 const std::size_t qlen = std::strlen(query);
50 std::size_t i = 0;
51 while (i < qlen) {
52 while (i < qlen && std::isspace(static_cast<unsigned char>(query[i])))
53 ++i;
54 const std::size_t start = i;
55 while (i < qlen && !std::isspace(static_cast<unsigned char>(query[i])))
56 ++i;
57 const std::size_t term_len = i - start;
58 if (term_len == 0)
59 continue;
60 if (!ContainsIgnoreCase(search_key, query + start, term_len))
61 return false;
62 }
63 return true;
64}
65
66} // namespace icon_browser_internal
67
68const char* IconBrowser(const char* label) {
69 if (label == nullptr)
70 label = "##icon_browser";
71 ImGui::PushID(label);
72
73 static thread_local std::string s_query;
74
75 // Search box — the ID is scoped by the enclosing PushID.
76 ImGui::SetNextItemWidth(-FLT_MIN);
77 ImGui::InputTextWithHint("##search", "Search icons...", &s_query);
78
79 const char* selected_glyph = nullptr;
80
81 const float avail_x = ImGui::GetContentRegionAvail().x;
82 const float cell_size =
83 ImGui::GetFontSize() * 2.0f + ImGui::GetStyle().FramePadding.y * 2.0f;
84 const float spacing = ImGui::GetStyle().ItemSpacing.x;
85 const int columns = std::max(
86 1, static_cast<int>((avail_x + spacing) / (cell_size + spacing)));
87
88 int column = 0;
89 for (int i = 0; i < kCommonIconCount; ++i) {
90 const CommonIcon& icon = kCommonIcons[i];
91 if (!icon_browser_internal::MatchesQuery(icon.search_key, s_query.c_str()))
92 continue;
93
94 if (column > 0)
95 ImGui::SameLine();
96 ImGui::PushID(i);
97 if (ImGui::Button(icon.glyph, ImVec2(cell_size, cell_size))) {
98 selected_glyph = icon.glyph;
99 }
100 if (ImGui::IsItemHovered()) {
101 ImGui::SetTooltip("%s\n%s", icon.macro_name, icon.category);
102 }
103 ImGui::PopID();
104
105 column = (column + 1) % columns;
106 }
107
108 ImGui::PopID();
109 return selected_glyph;
110}
111
112} // namespace gui
113} // namespace yaze
bool MatchesQuery(const char *search_key, const char *query)
const int kCommonIconCount
Definition icons.cc:138
const char * IconBrowser(const char *label)
const CommonIcon kCommonIcons[]
Definition icons.cc:7
const char * search_key
const char * category
const char * macro_name