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 ;-) |
Beta Was this translation helpful? Give feedback.
-
|
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! |
Beta Was this translation helpful? Give feedback.
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
Beta Was this translation helpful? Give feedback.
All reactions