Replies: 2 comments
|
Many thanks for this nice idea! I made a few modifications, in order to include the header file content automatically (Also, this version does search "as you type") #include <algorithm> // std::transform
#include <iterator> // std::back_inserter
#include <regex>
#include <sstream>
#include <string>
//
#define HELLOIMGUI_NO_FONT_AWESOME4
#include <hello_imgui/hello_imgui.h>
#include <hello_imgui/icons_font_awesome_6.h>
#include <imgui.h>
#include <misc/cpp/imgui_stdlib.h>
std::string read_icons_font_awesome_6_header();
namespace
{
std::map<std::string, std::string> allIcons, selectedIcons;
std::vector<std::string> filteredIcons;
std::string copyText;
ImFont *defaultFont{nullptr};
void filterIcons(std::string const &key = "") {
filteredIcons.clear();
if (key.empty()) {
std::transform(allIcons.begin(), allIcons.end(), std::back_inserter(filteredIcons),
[](auto &kv) { return kv.first; });
return;
}
std::string tmp(key);
std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::toupper);
for (const auto &icon : allIcons) {
if (icon.first.find(tmp) != std::string::npos) {
filteredIcons.emplace_back(icon.first);
}
}
}
void loadIcons() {
static const std::regex icon_regex(R"X(^#define\s+ICON_FA_(\w+)\s+"([^"]+)")X", std::regex_constants::icase);
static const std::regex hex_regex(R"X(\\X([\dA-F]{2}))X", std::regex_constants::icase);
std::istringstream infile(read_icons_font_awesome_6_header());
std::string line;
while (std::getline(infile, line)) {
std::smatch match;
if (std::regex_search(line, match, icon_regex)) {
const auto &&key = match.str(1);
const auto &&val = match.str(2);
std::sregex_iterator iter(val.cbegin(), val.cend(), hex_regex);
while (std::sregex_iterator{} != iter) {
allIcons[key] += strtol(iter->str(1).c_str(), nullptr, 16);
++iter;
}
}
}
}
void drawIcons(const std::vector<std::string> &buffer) {
using namespace std::string_literals;
if (buffer.empty()) {
return;
}
ImGui::TableNextRow(ImGuiTableRowFlags_None, 90.0F);
for (const auto &item : buffer) {
ImGui::TableNextColumn();
ImGui::PushFont(defaultFont, 24.0F);
if (ImGui::Button(""s.append(ICON_FA_BOOKMARK).append("## ").append(item).c_str())) {
if (selectedIcons.count(item) == 0) {
selectedIcons[item] = allIcons[item];
copyText += "ICON_FA_" + item + "\n";
}
}
ImGui::SameLine();
ImGui::TextUnformatted(item.c_str());
ImGui::PopFont();
ImGui::PushFont(defaultFont, 48.0F);
ImGui::TextUnformatted(allIcons.at(item).c_str());
ImGui::PopFont();
}
}
} // namespace
int main(int, char *[]) {
loadIcons();
filterIcons();
std::string inputBufer;
auto guiFunction = [&inputBufer]() {
using namespace std::string_literals;
ImGui::PushFont(defaultFont, 24.0F);
bool changed = ImGui::InputText("##Filter", &inputBufer, 32);
if (changed) {
filterIcons(inputBufer);
}
ImGui::SameLine();
// if (ImGui::Button("Filter "s.append(ICON_FA_MAGNIFYING_GLASS).c_str())) {
// filterIcons(inputBufer);
// }
ImGui::SameLine();
if (ImGui::Button("Clear Filter "s.append(ICON_FA_TRASH).c_str())) {
inputBufer = "";
filterIcons(inputBufer);
}
ImGui::PopFont();
auto flags = ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable |
ImGuiTableFlags_Hideable;
if (ImGui::BeginTable("table_nested1", 2, flags)) {
ImGui::TableNextColumn();
static const auto column_width{180.0F};
auto width = ImGui::GetContentRegionAvail().x;
auto C = std::max(int(width / column_width), 2);
std::vector<std::string> rowBuffer;
ImGui::BeginChild("Icons", ImVec2(0, ImGui::GetContentRegionAvail().y), ImGuiWindowFlags_None);
if (ImGui::BeginTable("filteredIconsTable", C, ImGuiTableFlags_NoBordersInBodyUntilResize)) {
for (const auto &icon : filteredIcons) {
rowBuffer.emplace_back(icon);
if (rowBuffer.size() >= C) {
drawIcons(rowBuffer);
rowBuffer.clear();
}
}
drawIcons(rowBuffer);
rowBuffer.clear();
ImGui::EndTable();
}
ImGui::EndChild();
ImGui::TableNextColumn();
ImGui::BeginChild("SelectedIcons", ImVec2(0, ImGui::GetContentRegionAvail().y), ImGuiWindowFlags_None);
if (ImGui::Button("Clear Selected "s.append(ICON_FA_ANCHOR_CIRCLE_CHECK).c_str())) {
selectedIcons.clear();
copyText = "";
}
ImGui::InputTextMultiline("##source", ©Text, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 10),
ImGuiInputTextFlags_ReadOnly);
for (const auto &icon : selectedIcons) {
ImGui::PushFont(defaultFont, 24.0F);
ImGui::TextUnformatted(icon.first.c_str());
ImGui::PopFont();
ImGui::PushFont(defaultFont, 48.0F);
ImGui::TextUnformatted(allIcons.at(icon.first).c_str());
ImGui::PopFont();
}
ImGui::EndChild();
ImGui::EndTable();
}
};
HelloImGui::RunnerParams runnerParams;
runnerParams.appWindowParams.windowTitle = "Font Tool";
runnerParams.callbacks.LoadAdditionalFonts = [] {
HelloImGui::FontLoadingParams fontParams;
fontParams.mergeToLastFont = true;
defaultFont = HelloImGui::LoadFont("fonts/DroidSans.ttf", 0.0F);
HelloImGui::LoadFont("fonts/Font_Awesome_6_Free-Solid-900.otf", 0.0F, fontParams);
};
runnerParams.imGuiWindowParams.showStatusBar = true;
runnerParams.callbacks.ShowGui = guiFunction;
HelloImGui::Run(runnerParams);
return 0;
}
#include <fstream>
#include <filesystem>
// Relative to imgui_bundle root, we have:
//
// __FILE__ = [path_to_imgui_bundle]/bindings/imgui_bundle/demos_cpp/sandbox/sandbox_tmp.cpp
// And we want to get the content of
// [path_to_imgui_bundle]/external/hello_imgui/hello_imgui/src/hello_imgui/icons_font_awesome_6.h
std::string read_icons_font_awesome_6_header()
{
namespace fs = std::filesystem;
fs::path header =
fs::path(__FILE__).parent_path() /
"../../../../external/hello_imgui/hello_imgui/src/hello_imgui/icons_font_awesome_6.h";
std::ifstream f(header);
if (!f)
throw std::runtime_error("Cannot open " + header.string());
std::ostringstream ss;
ss << f.rdbuf();
return ss.str();
}I will not add this to the official example for the moment. But it already serves as a nice example in the present discussion ;-) |
0 replies
|
Sorry forgot to paste the cmake part. Here is the code. In this way we don't need read the source at runtime ... I think as demo code, either way should be fine 🤔 include(hello_imgui_add_app)
set(APP_NAME fontTool)
file(
GLOB "${APP_NAME}_SOURCES"
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
)
hello_imgui_add_app(${APP_NAME} ${${APP_NAME}_SOURCES})
# app_post_setup(TARGET ${APP_NAME}) # my own function to add some compile flags, should be fine to omit
target_include_directories(
${APP_NAME} PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
)
file(READ ${THIRDPP_DIR}/hello_imgui/src/hello_imgui/icons_font_awesome_6.h icons_font_awesome_6_h)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/template.h.in
${CMAKE_CURRENT_BINARY_DIR}/asset_blob.h
@ONLY
)///template.h.in
#include <string>
std::string embedded_asset = R"XXX(@icons_font_awesome_6_h@)XXX";
Incremental search, nice change! |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Hi,
When Font Awesome 6 was introduced last year, I built a small utility to make icon selection easier. The code is simple and focused, so I thought it might be a good fit for the Hello ImGui demo.
I haven’t had time to work on ImGui-related projects until recently, but I’ve now updated the utility to support the 1.92 API. If you think it could be useful, I’d be happy to submit a pull request to contribute it to the demo code.
BR
Boying
All reactions