CoolFace
Datasetpublic

dlxjj/imradv3

sourceHugging Faceupdated 8mo agoView on Hugging Face
0likes263downloads
main.cpp2830 linesDownload Raw Back to src
1#if WIN322#define WIN32_LEAN_AND_MEAN3#include <Windows.h>4#undef min5#undef max6#undef MessageBox7#endif8#if defined(__APPLE__)9#include <mach-o/dyld.h>10#endif11#include <imgui.h>12#include <imgui_internal.h>13#include <misc/cpp/imgui_stdlib.h>14#include <IconsFontAwesome6.h>15//#include <misc/fonts/IconsMaterialDesign.h>16#include <backends/imgui_impl_glfw.h>17#include <backends/imgui_impl_opengl3.h>18#include <iostream>19#include <fstream>20#include <string>21#if defined(IMGUI_IMPL_OPENGL_ES2)22#include <GLES2/gl2.h>23#endif24#include <GLFW/glfw3.h> // Will drag system OpenGL headers25#include <nfd.h>26 27#include "glfw_cursor.h"28#include "node_standard.h"29#include "cppgen.h"30#include "utils.h"31#include "ui_new_field.h"32#include "ui_message_box.h"33#include "ui_error_box.h"34#include "ui_class_wizard.h"35#include "ui_table_cols.h"36#include "ui_about_dlg.h"37#include "ui_binding.h"38#include "ui_combo_dlg.h"39#include "ui_horiz_layout.h"40#include "ui_input_name.h"41#include "ui_settings_dlg.h"42#include "ui_explorer.h"43 44#include "SimpleLayout.h"45 46#include "ImGuiColorTextEdit/TextEditor.h"47#include "nlohmann_json/json.hpp"48#include "MD5/quickdigest5.h"49#include "Constant.h"50#include "global.h"51 52using json = nlohmann::json;53 54//must come last55#define STB_IMAGE_IMPLEMENTATION56#include <stb_image.h>57 58#include <d3d11.h>59 60//#pragma comment(lib, "E:\\huggingface\\ColorTextEditorV2\\build\\bin\\opencv_core4120.lib")61//#pragma comment(lib, "E:\\huggingface\\ColorTextEditorV2\\build\\bin\\opencv_highgui4120.lib")62 63std::filesystem::path g_currPath;64HINSTANCE   g_wechatocr_dll = NULL;65typedef const char* (_cdecl* FunctionPtr) (const char* pth_img);66FunctionPtr rec;67 68std::pair<std::filesystem::path, std::filesystem::path> get_img_json_pth(const std::string& m5) {69#ifdef _DEBUG70    // 这是工作目录71    auto pth_img = g_currPath.parent_path().parent_path() / std::filesystem::path("data/img") / std::format("{}.txt", m5);72    auto pth_json = g_currPath.parent_path().parent_path() / std::filesystem::path("data/json") / std::format("{}.json", m5);73#else74    // 这是工作目录75    auto pth_img = g_currPath / std::filesystem::path("data/img") / std::format("{}.txt", m5); // .parent_path().parent_path()76    auto pth_json = g_currPath / std::filesystem::path("data/json") / std::format("{}.json", m5); // .parent_path().parent_path()77    //// 这是可执行文件所在目录 78    //auto pth_img = g_currPath / std::filesystem::path("data/img") / std::format("{}.txt", m5);79    //auto pth_json = g_currPath / std::filesystem::path("data/json") / std::format("{}.json", m5);80#endif // DEBUG81 82    pth_img = pth_img.lexically_normal();83    pth_json = pth_json.lexically_normal();84 85    std::pair<std::filesystem::path, std::filesystem::path> pth_pair{ pth_img, pth_json };86 87	return pth_pair;88}89 90 91std::string readFileToString(const std::string& filePath) {92    std::ifstream file(filePath, std::ios::binary);93    if (!file) return "";94    std::ostringstream buffer;95    buffer << file.rdbuf(); // 将文件流缓冲区内容写入字符串流96    return buffer.str();97}98 99static void glfw_error_callback(int error, const char* description)100{101    std::cerr << "Glfw Error: " << description;102}103 104const float TB_SIZE = 40;105const float TAB_SIZE = 25; //todo examine106const std::string UNTITLED = "Untitled";107const std::string DEFAULT_STYLE = "Dark";108const std::string DEFAULT_UNIT = "px";109const char* INI_FILE_NAME = "imgui.ini";110 111struct File112{113    std::string fname;114    CppGen codeGen;115    std::unique_ptr<TopWindow> rootNode;116    bool modified = false;117    fs::file_time_type time[2];118    std::string styleName;119    std::string unit;120};121 122enum ProgramState { Run, Init, Shutdown };123ProgramState programState;124std::string rootPath;125std::string initErrors, showError;126std::string uiFontName = "Roboto-Regular.ttf";127std::string pgFontName = "Roboto-Regular.ttf";128std::string pgbFontName = "Roboto-Bold.ttf";129float uiFontSize = 19;130float pgFontSize = 20;131UIContext ctx;132std::unique_ptr<Widget> newNode;133std::vector<File> fileTabs;134int activeTab = -1;135std::vector<std::pair<std::string, std::string>> styleNames; //name, path136std::string styleName;137bool reloadStyle = true;138GLFWwindow* window = nullptr;139int addInputCharacter = 0;140std::string lastPropName;141std::string activeButton = "";142std::vector<std::unique_ptr<Widget>> clipboard;143GLFWcursor* curCross = nullptr;144GLFWcursor* curWait = nullptr;145float pgHeight = 0, pgeHeight = 0;146ImRad::IOUserData ioUserData;147 148struct TB_Button149{150    std::string label;151    std::string name;152};153std::vector<std::pair<std::string, std::vector<TB_Button>>> tbButtons{154    { "Standard", {155        { ICON_FA_ARROW_POINTER, "" },156        { ICON_FA_FONT, "Text" },157        { ICON_FA_AUDIO_DESCRIPTION, "Selectable" },158        { ICON_FA_CIRCLE_PLAY, "Button" }, //ICON_FA_SQUARE_PLUS159        { "[a_]", "Input" }, //ICON_FA_CLOSED_CAPTIONING160        { ICON_FA_SQUARE_CHECK, "CheckBox" },161        { ICON_FA_CIRCLE_DOT, "RadioButton" },162        { ICON_FA_SQUARE_CARET_DOWN, "Combo" },163        { ICON_FA_SLIDERS, "Slider" },164        { ICON_FA_CIRCLE_HALF_STROKE, "ColorEdit" },165        { ICON_FA_BATTERY_HALF, "ProgressBar" },166        { ICON_FA_IMAGE, "Image" },167        { ICON_FA_LEFT_RIGHT, "Spacer" },168        { ICON_FA_MINUS, "Separator" },169        { ICON_FA_EXPAND, "CustomWidget" },170    }},171    { "Containers", {172        { ICON_FA_SQUARE_FULL, "Child" },173        { ICON_FA_TABLE_CELLS_LARGE, "Table" },174        { ICON_FA_ARROW_DOWN_WIDE_SHORT, "CollapsingHeader" },175        { ICON_FA_FOLDER_CLOSED, "TabBar" },176        { ICON_FA_SITEMAP, "TreeNode" },177        { ICON_FA_TABLE_COLUMNS, "Splitter" }, //ICON_FA_ARROWS_LEFT_RIGHT_TO_LINE178        //{ ICON_FA_CLAPPERBOARD /*ELLIPSIS*/, "MenuBar" },179        { ICON_FA_TABLE, "DockSpace" },180        { ICON_FA_MESSAGE /*RECEIPT*/, "ContextMenu" },181    }},182};183 184//CancelShutdown identifier is used in winuser.h185void DoCancelShutdown()186{187    if (programState != Shutdown)188        return;189 190    glfwSetWindowShouldClose(window, false);191    programState = Run;192    ImGui::GetIO().IniFilename = INI_FILE_NAME;193}194 195void DoReloadFile()196{197    if (activeTab < 0)198        return;199    auto& tab = fileTabs[activeTab];200    if (tab.fname == "" || !fs::is_regular_file(u8path(tab.fname)))201        return;202 203    std::map<std::string, std::string> params;204    std::string error;205    tab.rootNode = tab.codeGen.Import(tab.fname, params, error);206    auto pit = params.find("style");207    tab.styleName = pit == params.end() ? DEFAULT_STYLE : pit->second;208    pit = params.find("unit");209    tab.unit = pit == params.end() ? DEFAULT_UNIT : pit->second;210    bool styleFound = stx::count_if(styleNames, [&](const auto& st) {211        return st.first == tab.styleName;212        });213    if (!styleFound) {214        error = "Unknown style \"" + tab.styleName + "\" used\n" + error;215        tab.styleName = DEFAULT_STYLE;216    }217    tab.modified = false;218    ctx.mode = UIContext::NormalSelection;219    ctx.selected = { tab.rootNode.get() };220 221    if (error != "" && programState != Shutdown)222    {223        errorBox.title = "Reload";224        errorBox.message = "Errors occured";225        errorBox.error = error;226        errorBox.OpenPopup();227    }228}229 230void ReloadFile()231{232    if (activeTab < 0)233        return;234    auto& tab = fileTabs[activeTab];235    if (tab.fname == "" || !fs::is_regular_file(u8path(tab.fname)))236        return;237    auto time1 = fs::last_write_time(u8path(tab.fname));238    std::error_code err;239    auto time2 = fs::last_write_time(u8path(tab.codeGen.AltFName(tab.fname)), err);240    if (time1 == tab.time[0] && time2 == tab.time[1])241        return;242    tab.time[0] = time1;243    tab.time[1] = time2;244 245    if (programState != Shutdown)246    {247        std::string fn = u8string(u8path(tab.fname).filename());248        messageBox.title = "Reload";249        messageBox.message = "File content of '" + fn + "' has changed. Reload?";250        messageBox.buttons = ImRad::Yes | ImRad::No;251 252        messageBox.OpenPopup([&](ImRad::ModalResult mr) {253            if (mr == ImRad::Yes)254                DoReloadFile();255            });256    }257    else {258        DoReloadFile();259    }260}261 262void ActivateTab(int i)263{264    /*doesn't work when activeTab is closed265    std::string lastStyle;266    if (activeTab >= 0)267        lastStyle = fileTabs[activeTab].styleName;*/268    if (i >= fileTabs.size())269        i = (int)fileTabs.size() - 1;270    if (i < 0) {271        activeTab = -1;272        ctx.selected.clear();273        ctx.codeGen = nullptr;274        return;275    }276    activeTab = i;277    auto& tab = fileTabs[i];278    ctx.selected = { tab.rootNode.get() };279    ctx.codeGen = &tab.codeGen;280    ReloadFile();281 282    if (fileTabs[activeTab].styleName != styleName)283        reloadStyle = true;284}285 286void NewFile(TopWindow::Kind k)287{288    ctx.kind = k;289    auto top = std::make_unique<TopWindow>(ctx);290    File file;291    file.rootNode = std::move(top);292    file.styleName = DEFAULT_STYLE;293    file.unit = k == TopWindow::Activity ? "dp" : DEFAULT_UNIT;294    file.modified = true;295    fileTabs.push_back(std::move(file));296    ActivateTab((int)fileTabs.size() - 1);297}298 299void CopyFileReplace(const std::string& from, const std::string& to, std::vector<std::pair<std::string, std::string>>& repl)300{301    std::ifstream fin(u8path(from));302    if (!fin)303        throw std::runtime_error("can't read from " + from);304    std::ofstream fout(u8path(to));305    if (!fout)306        throw std::runtime_error("can't write to " + to);307 308    std::string line;309    while (std::getline(fin, line))310    {311        size_t i = 0;312        while (true)313        {314            i = line.find("${", i);315            if (i == std::string::npos)316                break;317            size_t j = line.find("}", i);318            if (j == std::string::npos)319                break;320            for (const auto& r : repl)321                if (!line.compare(i + 2, j - i - 2, r.first)) {322                    line.replace(line.begin() + i, line.begin() + j + 1, r.second);323                    j = i + r.second.size();324                    break;325                }326            i = j;327        }328        fout << line << "\n";329    }330}331 332void DoNewTemplate(int type, const std::string& name)333{334    nfdchar_t *outPath = NULL;335    nfdfilteritem_t filterItem[1] = { { (const nfdchar_t *)"Source code", (const nfdchar_t *)"cpp" } };336    nfdresult_t result = NFD_SaveDialog(&outPath, filterItem, 1, nullptr, "main.cpp");337    if (result != NFD_OKAY)338        return;339    fs::path p = u8path(outPath);340    NFD_FreePath(outPath);341    if (!p.has_extension())342        p.replace_extension(".cpp");343 344    try {345        switch (type)346        {347        case 0:348            fs::copy_file(u8path(rootPath + "/template/glfw/main.cpp"), p, fs::copy_options::overwrite_existing);349            break;350        case 1: {351            std::string jni = name;352            stx::replace(jni, '.', '_');353            if (name.find('.') == std::string::npos)354                throw std::runtime_error("invalid package name");355            std::string lib = name.substr(name.rfind('.') + 1);356 357            std::vector<std::pair<std::string, std::string>> repl{358                { "JAVA_PACKAGE", name },359                { "JNI_PACKAGE", jni },360                { "LIB_NAME", lib },361                { "IMRAD_INCLUDE", rootPath + "/include" },362            };363            CopyFileReplace(rootPath + "/template/android/main.cpp", u8string(p), repl);364            CopyFileReplace(rootPath + "/template/android/CMakeLists.txt", u8string(p.replace_filename("CMakeLists.txt")), repl);365            CopyFileReplace(rootPath + "/template/android/MainActivity.java", u8string(p.replace_filename("MainActivity.java")), repl);366            CopyFileReplace(rootPath + "/template/android/AndroidManifest.xml", u8string(p.replace_filename("AndroidManifest.xml")), repl);367            break;368        }369        }370    }371    catch (std::exception& e) {372        messageBox.title = "error";373        messageBox.message = e.what();374        messageBox.buttons = ImRad::Ok;375        messageBox.OpenPopup();376    }377}378 379void NewTemplate(int type)380{381    if (type == 1)382    {383        //android template384        inputName.title = "Java package name";385        inputName.hint = "com.example.test";386        inputName.OpenPopup([type](ImRad::ModalResult mr) {387            DoNewTemplate(type, inputName.name);388            });389    }390    else391        DoNewTemplate(type, "");392}393 394bool DoOpenFile(const std::string& path, std::string* errs = nullptr)395{396    File file;397    file.fname = path;398    if (u8string(u8path(file.fname).extension()).compare(0, 2, ".h")) {399        file.fname = file.codeGen.AltFName(file.fname);400    }401    if (!fs::is_regular_file(u8path(path))) {402        if (errs)403            *errs += "Can't read '" + path + "'\n";404        else {405            messageBox.title = "ImRAD";406            messageBox.message = "Can't read '" + path + "'";407            messageBox.buttons = ImRad::Ok;408            messageBox.OpenPopup();409        }410        return false;411    }412 413    std::error_code err;414    file.time[0] = fs::last_write_time(u8path(file.fname), err);415    file.time[1] = fs::last_write_time(u8path(file.codeGen.AltFName(file.fname)), err);416    std::map<std::string, std::string> params;417    std::string error;418    file.rootNode = file.codeGen.Import(file.fname, params, error);419    auto pit = params.find("style");420    file.styleName = pit == params.end() ? DEFAULT_STYLE : pit->second;421    pit = params.find("unit");422    file.unit = pit == params.end() ? DEFAULT_UNIT : pit->second;423    if (!file.rootNode) {424        if (errs)425            *errs += "Unsuccessful import of '" + path + "'\n";426        else {427            errorBox.title = "CodeGen";428            errorBox.message = "Unsuccessful import because of errors";429            errorBox.error = error;430            errorBox.OpenPopup();431        }432        return false;433    }434 435    bool styleFound = stx::count_if(styleNames, [&](const auto& st) {436        return st.first == file.styleName;437        });438    if (!styleFound) {439        if (errs)440            *errs += "Uknown style \"" + file.styleName + "\" used\n";441        else442            error = "Unknown style \"" + file.styleName + "\" used\n" + error;443        file.styleName = DEFAULT_STYLE;444    }445 446    auto it = stx::find_if(fileTabs, [&](const File& f) { return f.fname == file.fname; });447    if (it == fileTabs.end()) {448        fileTabs.push_back({});449        it = fileTabs.begin() + fileTabs.size() - 1;450    }451    int idx = int(it - fileTabs.begin());452    fileTabs[idx] = std::move(file);453    ActivateTab(idx);454 455    if (error != "") {456        if (errs)457            *errs += error;458        else {459            errorBox.title = "CodeGen";460            errorBox.message = "Import finished with errors";461            errorBox.error = error;462            errorBox.OpenPopup();463        }464    }465    return true;466}467 468void OpenFile()469{470    nfdchar_t *outPath = NULL;471    nfdfilteritem_t filterItem[1] = { { "Headers", "h,hpp" } };472    nfdresult_t result = NFD_OpenDialog(&outPath, filterItem, 1, nullptr);473    if (result != NFD_OKAY)474        return;475 476    ctx.mode = UIContext::NormalSelection;477    ctx.selected.clear();478    auto it = stx::find_if(fileTabs, [&](const File& f) { return f.fname == outPath; });479    if (it != fileTabs.end())480    {481        ActivateTab(int(it - fileTabs.begin()));482        if (it->modified) {483            messageBox.title = "Open File";484            messageBox.message = "Reload and lose unsaved changes?";485            messageBox.buttons = ImRad::Yes | ImRad::No;486            messageBox.OpenPopup([=](ImRad::ModalResult mr) {487                if (mr == ImRad::Yes)488                    DoOpenFile(outPath);489                });490        }491        else {492            DoOpenFile(outPath);493        }494    }495    else {496        DoOpenFile(outPath);497    }498    NFD_FreePath(outPath);499}500 501enum {502    CLOSE_ACTIVE = 0x1,503    CLOSE_ALL = 0x2,504    CLOSE_ALL_BUT_PREVIOUS = 0x4,505};506void CloseFile(int flags = CLOSE_ACTIVE);507bool SaveFile(int flags = 0);508bool SaveFileAs(int flags = 0);509 510void DoCloseFile(int flags)511{512    if (activeTab < 0)513        return;514 515    ctx.root = nullptr;516    ctx.selected.clear();517    fileTabs.erase(fileTabs.begin() + activeTab);518 519    if ((flags & CLOSE_ALL_BUT_PREVIOUS) && fileTabs.size() >= 2) {520        ActivateTab(activeTab >= fileTabs.size() ? 0 : activeTab); //cycle from first tab521        CloseFile(flags);522    }523    else if (flags & CLOSE_ALL) {524        ActivateTab(activeTab);525        CloseFile(flags);526    }527    else {528        ActivateTab(activeTab);529    }530}531 532void CloseFile(int flags)533{534    if (activeTab < 0)535        return;536    if (fileTabs[activeTab].modified) {537        messageBox.title = "Confirmation";538        std::string fname = u8string(u8path(fileTabs[activeTab].fname).filename());539        if (fname.empty())540            fname = UNTITLED;541        messageBox.message = "Save changes to " + fname + "?";542        messageBox.buttons = ImRad::Yes | ImRad::No | ImRad::Cancel;543        messageBox.OpenPopup([=](ImRad::ModalResult mr) {544            if (mr == ImRad::Yes)545                SaveFile(flags);546            else if (mr == ImRad::No)547                DoCloseFile(flags);548            else549                DoCancelShutdown();550            });551    }552    else {553        DoCloseFile(flags);554    }555}556 557void DoSaveFile(int flags)558{559    auto& tab = fileTabs[activeTab];560    std::map<std::string, std::string> params{561        { "style", tab.styleName },562        { "unit", tab.unit },563    };564    std::string error;565    if (!tab.codeGen.ExportUpdate(tab.fname, tab.rootNode.get(), params, error))566    {567        DoCancelShutdown();568        errorBox.title = "CodeGen";569        errorBox.message = "Unsuccessful export due to errors";570        errorBox.error = error;571        errorBox.OpenPopup();572        return;573    }574 575    std::error_code err;576    tab.modified = false;577    tab.time[0] = fs::last_write_time(u8path(tab.fname), err);578    tab.time[1] = fs::last_write_time(u8path(tab.codeGen.AltFName(tab.fname)), err);579    if (error != "" && programState != Shutdown)580    {581        errorBox.title = "CodeGen";582        errorBox.message = "Export finished with errors";583        errorBox.error = error;584        errorBox.OpenPopup([=](ImRad::ModalResult) {585            if (flags)586                DoCloseFile(flags);587            });588        return;589    }590 591    if (flags)592        DoCloseFile(flags);593}594 595bool SaveFileAs(int flags)596{597    nfdchar_t *outPath = NULL;598    nfdfilteritem_t filterItem[1] = { { (const nfdchar_t *)"Header File", (const nfdchar_t *)"h,hpp" } };599    nfdresult_t result = NFD_SaveDialog(&outPath, filterItem, 1, nullptr, nullptr);600    if (result != NFD_OKAY) {601        DoCancelShutdown();602        return false;603    }604    auto& tab = fileTabs[activeTab];605    fs::path oldName = u8path(tab.fname);606    fs::path newName = u8path(outPath).replace_extension(".h");607    NFD_FreePath(outPath);608    if (newName == oldName) {609        DoSaveFile(flags);610        return true;611    }612 613    try {614        if (oldName != "") {615            //copy files first so CppGen can parse it and preserve user content as with Save616            fs::copy_file(oldName, newName, fs::copy_options::overwrite_existing);617            fs::copy_file(618                oldName.replace_extension(".cpp"),619                newName.replace_extension(".cpp"),620                fs::copy_options::overwrite_existing);621        }622        else {623            fs::remove(newName);624            fs::remove(newName.replace_extension(".cpp"));625        }626    }627    catch (std::exception& e)628    {629        DoCancelShutdown();630        messageBox.title = "error";631        messageBox.message = e.what();632        messageBox.buttons = ImRad::Ok;633        messageBox.OpenPopup();634        return false;635    }636 637    if (oldName == "") {638        tab.codeGen.SetNamesFromId(u8string(newName.stem()));639        tab.fname = u8string(newName.replace_extension(".h"));640        DoSaveFile(flags);641    }642    else {643        messageBox.title = "codegen";644        messageBox.message = "Rename window class?";645        messageBox.buttons = ImRad::Yes | ImRad::No | ImRad::Cancel;646        messageBox.OpenPopup([&tab,newName,flags](ImRad::ModalResult mr) mutable {647            if (mr == ImRad::ModalResult::Cancel)648                return;649            if (mr == ImRad::ModalResult::Yes)650                tab.codeGen.SetNamesFromId(u8string(newName.stem()));651            tab.fname = u8string(newName.replace_extension(".h"));652            DoSaveFile(flags);653            });654    }655    return true;656}657 658bool SaveFile(int flags)659{660    auto& tab = fileTabs[activeTab];661    if (tab.fname == "") {662        return SaveFileAs(flags);663    }664    else {665        DoSaveFile(flags);666        return true;667    }668}669 670//todo: dangerous because of no reloading671void SaveAll()672{673    int tmp = activeTab;674    for (activeTab = 0; activeTab < fileTabs.size(); ++activeTab)675    {676        if (!SaveFile())677            break;678    }679    activeTab = tmp;680}681 682void ShowCode()683{684    if (activeTab < 0)685        return;686    fs::path path = fs::temp_directory_path() / "imrad-preview.cpp";687    std::ofstream fout(path);688    fout << "// NOTE: This is just a preview of the Draw() method. To see the complete code\n"689         << "// including class definition and event handlers inspect generated .h/cpp files\n\n";690    ctx.ind = "";691    auto* root = fileTabs[activeTab].rootNode.get();692    root->Export(fout, ctx);693 694    if (ctx.errors.size()) {695        fout << "\n// Export finished with errors:\n";696        for (const std::string& e : ctx.errors)697            fout << "// " << e <<  "\n";698    }699    fout.close();700    ShellExec(u8string(path));701}702 703void NewWidget(const std::string& name)704{705    if (name == "")706    {707        activeButton = "";708        ctx.selected.clear();709        ctx.mode = UIContext::NormalSelection;710    }711    else if (name == "MenuBar")712    {713        if (ctx.root->children.empty() ||714            !dynamic_cast<MenuBar*>(ctx.root->children[0].get()))715        {716            dynamic_cast<TopWindow*>(ctx.root)->flags |= ImGuiWindowFlags_MenuBar;717            ctx.root->children.insert(ctx.root->children.begin(), std::make_unique<MenuBar>(ctx));718            ctx.selected = { ctx.root->children[0]->children[0].get() };719        }720        ctx.mode = UIContext::NormalSelection;721    }722    else if (name == "ContextMenu")723    {724        activeButton = "";725        auto popup = std::make_unique<ContextMenu>(ctx);726        auto item = std::make_unique<MenuIt>(ctx);727        item->label = "Item";728        popup->children.push_back(std::move(item));729        size_t i = 0;730        for (; i < ctx.root->children.size(); ++i)731        {732            if (ctx.root->children[i]->Behavior() & Widget::SnapSides)733                break;734        }735        popup->label = "ContextMenu" + std::to_string(i + 1);736        ctx.root->children.insert(ctx.root->children.begin() + i, std::move(popup));737        ctx.mode = UIContext::NormalSelection;738        ctx.selected = { ctx.root->children[i]->children[0].get() };739    }740    else741    {742        activeButton = name;743        ctx.selected.clear();744        ctx.mode = UIContext::SnapInsert;745        newNode = Widget::Create(name, ctx);746    }747}748 749void StyleColors()750{751    ImGui::StyleColorsLight();752    ImGuiStyle& style = ImGui::GetStyle();753 754    style.Alpha = 1.0f;755    style.FrameRounding = 3.0f;756    style.WindowRounding = 3.f;757    style.Colors[ImGuiCol_Text] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);758    style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.40f, 0.40f, 0.40f, 1.00f);759    style.Colors[ImGuiCol_WindowBg] = ImVec4(0.94f, 0.94f, 0.94f, 0.94f);760    style.Colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);761    style.Colors[ImGuiCol_PopupBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.94f);762    style.Colors[ImGuiCol_Border] = ImVec4(0.00f, 0.00f, 0.00f, 0.39f);763    style.Colors[ImGuiCol_BorderShadow] = ImVec4(1.00f, 1.00f, 1.00f, 0.10f);764    style.Colors[ImGuiCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.94f);765    style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);766    style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);767    style.Colors[ImGuiCol_TitleBg] = ImVec4(0.96f, 0.96f, 0.96f, 1.00f);768    style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(1.00f, 1.00f, 1.00f, 0.51f);769    style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.82f, 0.82f, 0.82f, 1.00f);770    style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.86f, 0.86f, 0.86f, 1.00f);771    style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.98f, 0.98f, 0.98f, 0.53f);772    style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.69f, 0.69f, 0.69f, 1.00f);773    style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.59f, 0.59f, 0.59f, 1.00f);774    style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.49f, 0.49f, 0.49f, 1.00f);775    style.Colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);776    style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f);777    style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);778    style.Colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f);779    style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);780    style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);781    style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.78f);782    style.Colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.50f);783    style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);784    style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);785    style.Colors[ImGuiCol_Button] = ImVec4(0.59f, 0.59f, 0.59f, 0.50f);786    style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f);787    style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.86f, 0.59f, 0.59f, 1.00f);788    style.Colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);789    style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);790    style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);791    style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);792    style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);793    style.Colors[ImGuiCol_TabSelectedOverline].w = 0;794    style.Colors[ImGuiCol_TabDimmedSelectedOverline].w = 0;795    style.Colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);796 797    float alpha_ = 0.95f;798    if (false) //dark799    {800        for (int i = 0; i < ImGuiCol_COUNT; i++)801        {802            ImVec4& col = style.Colors[i];803            float H, S, V;804            ImGui::ColorConvertRGBtoHSV(col.x, col.y, col.z, H, S, V);805 806            if (S < 0.1f)807            {808                V = 1.0f - V;809            }810            ImGui::ColorConvertHSVtoRGB(H, S, V, col.x, col.y, col.z);811            if (col.w < 1.00f)812            {813                col.w *= alpha_;814            }815        }816    }817    else818    {819        for (int i = 0; i < ImGuiCol_COUNT; i++)820        {821            ImVec4& col = style.Colors[i];822            if (col.w < 1.00f)823            {824                col.x *= alpha_;825                col.y *= alpha_;826                col.z *= alpha_;827                col.w *= alpha_;828            }829        }830    }831 832    //ImRad::SaveStyle(rootPath + "/style/debug.ini");833}834 835void GetStyles()836{837    styleNames = {838        { "Classic", "" },839        { "Light", "" },840        { "Dark", "" }841    };842    for (fs::directory_iterator it(u8path(rootPath + "/style/")); it != fs::directory_iterator(); ++it)843    {844        if (it->path().extension() != ".ini")845            continue;846        styleNames.push_back({ u8string(it->path().stem()), u8string(it->path()) });847    }848}849 850const std::array<ImU32, UIContext::Color::COUNT>&851GetCtxColors(const std::string& styleName)852{853    static const std::array<ImU32, UIContext::Color::COUNT> classic{854        IM_COL32(255, 255, 0, 128),855        IM_COL32(255, 0, 0, 255),856        IM_COL32(128, 128, 255, 255),857        IM_COL32(255, 0, 255, 255),858        IM_COL32(0, 255, 255, 255),859        IM_COL32(0, 255, 0, 255),860    };861    static const std::array<ImU32, UIContext::Color::COUNT> light {862        IM_COL32(0, 0, 255, 128),863        IM_COL32(255, 96, 96, 255),864        IM_COL32(128, 128, 255, 255),865        IM_COL32(255, 0, 255, 255),866        IM_COL32(0, 128, 128, 255),867        IM_COL32(0, 255, 0, 255),868    };869    static const std::array<ImU32, UIContext::Color::COUNT> dark{870        IM_COL32(255, 255, 0, 128),871        IM_COL32(255, 0, 0, 255),872        IM_COL32(128, 128, 255, 255),873        IM_COL32(255, 0, 255, 255),874        IM_COL32(0, 255, 255, 255),875        IM_COL32(0, 255, 0, 255),876    };877 878    if (styleName == "Light")879        return light;880    else if (styleName == "Dark")881        return dark;882    else883        return classic;884}885 886void LoadStyle()887{888    if (!reloadStyle)889        return;890 891    reloadStyle = false;892    auto& io = ImGui::GetIO();893    std::string stylePath = rootPath + "/style/";894 895    glfwSetCursor(window, curWait);896    io.Fonts->Clear();897 898    //reload ImRAD UI first899    StyleColors();900    io.Fonts->AddFontFromFileTTF((stylePath + uiFontName).c_str(), uiFontSize);901    static ImWchar icons_ranges[] = { ICON_MIN_FA, ICON_MAX_16_FA, 0 };902    ImFontConfig cfg;903    cfg.MergeMode = true;904    //icons_config.PixelSnapH = true;905    const float faSize = uiFontSize * 18.f / 20.f;906    io.Fonts->AddFontFromFileTTF((stylePath + FONT_ICON_FILE_NAME_FAR).c_str(), faSize, &cfg, icons_ranges);907    io.Fonts->AddFontFromFileTTF((stylePath + FONT_ICON_FILE_NAME_FAS).c_str(), faSize, &cfg, icons_ranges);908    cfg.MergeMode = false;909    strcpy(cfg.Name, "imrad.H1");910    io.Fonts->AddFontFromFileTTF((stylePath + uiFontName).c_str(), uiFontSize * 1.5f, &cfg);911    strcpy(cfg.Name, "imrad.H3");912    io.Fonts->AddFontFromFileTTF((stylePath + uiFontName).c_str(), uiFontSize * 1.1f, &cfg);913 914    strcpy(cfg.Name, "imrad.pg");915    ctx.pgFont = io.Fonts->AddFontFromFileTTF((stylePath + pgFontName).c_str(), pgFontSize, &cfg);916    strcpy(cfg.Name, "imrad.pgb");917    ctx.pgbFont = io.Fonts->AddFontFromFileTTF((stylePath + pgbFontName).c_str(), pgFontSize, &cfg);918    strcpy(cfg.Name, "imrad.explorer");919    io.Fonts->AddFontFromFileTTF((stylePath + "Roboto-Regular.ttf").c_str(), uiFontSize, &cfg);920 921    cfg.MergeMode = false;922    strcpy(cfg.Name, "simhei");923    ImFont *font = io.Fonts->AddFontFromFileTTF("c:/windows/fonts/simhei.ttf", 23.0f, &cfg, io.Fonts->GetGlyphRangesChineseFull());924    IM_ASSERT(font != nullptr);925 926	// io.FontDefault = font;  // 设置默认字体,成功显示中文927 928    //ImGui::PushFont(font);929 930    ctx.defaultStyleFont = nullptr;931    ctx.fontNames.clear();932    stx::fill(ctx.colors, IM_COL32(0, 0, 0, 255));933    ctx.style = ImGuiStyle();934 935    if (activeTab >= 0)936    {937        std::string styleName = fileTabs[activeTab].styleName;938        std::string defaultFont = stylePath + "Roboto-Regular.ttf";939        if (styleName == "Classic")940        {941            ImGui::StyleColorsClassic(&ctx.style);942            ctx.defaultStyleFont = io.Fonts->AddFontFromFileTTF(defaultFont.c_str(), uiFontSize);943            ctx.defaultStyleFont->FallbackChar = '#';944            ctx.fontNames = { "" };945            ctx.colors = GetCtxColors(styleName);946        }947        else if (styleName == "Light")948        {949            ImGui::StyleColorsLight(&ctx.style);950            ctx.defaultStyleFont = io.Fonts->AddFontFromFileTTF(defaultFont.c_str(), uiFontSize);951            ctx.defaultStyleFont->FallbackChar = '#';952            ctx.fontNames = { "" };953            ctx.colors = GetCtxColors(styleName);954        }955        else if (styleName == "Dark")956        {957            ImGui::StyleColorsDark(&ctx.style);958            ctx.defaultStyleFont = io.Fonts->AddFontFromFileTTF(defaultFont.c_str(), uiFontSize);959            ctx.defaultStyleFont->FallbackChar = '#';960            ctx.fontNames = { "" };961            ctx.colors = GetCtxColors(styleName);962        }963        else964        {965            std::map<std::string, ImFont*> fontMap;966            std::map<std::string, std::string> extra;967            try {968                auto it = stx::find_if(styleNames, [&](const auto& s) { return s.first == styleName; });969                ImRad::LoadStyle(it->second, 1.f, &ctx.style, &fontMap, &extra);970 971                ctx.defaultStyleFont = fontMap[""];972                for (const auto& f : fontMap) {973                    ctx.fontNames.push_back(f.first);974                }975                for (const auto& ex : extra) {976                    if (ex.first.compare(0, 13, "imrad.colors."))977                        continue;978                    std::istringstream is(ex.second);979                    int r, g, b, a;980                    is >> r >> g >> b >> a;981                    auto clr = IM_COL32(r, g, b, a);982                    std::string key = ex.first.substr(13);983 984    #define SET_CLR(a) if (key == #a) ctx.colors[UIContext::a] = clr;985                    SET_CLR(Selected);986                    SET_CLR(Hovered);987                    SET_CLR(Snap1);988                    SET_CLR(Snap2);989                    SET_CLR(Snap3);990                    SET_CLR(Snap4);991                    SET_CLR(Snap5);992    #undef SET_CLR993                }994            }995            catch (std::exception& e)996            {997                //can't OpenPopup here, there is no window parent998                showError = e.what();999            }1000        }1001    }1002    ImGui_ImplOpenGL3_DestroyFontsTexture();1003    ImGui_ImplOpenGL3_CreateFontsTexture();1004}1005 1006void DoCloneStyle(const std::string& name)1007{1008    auto FormatClr = [](ImU32 c) {1009        std::ostringstream os;1010        os << (c & 0xff) << " " <<1011            ((c >> 8) & 0xff) << " " <<1012            ((c >> 16) & 0xff) << " " <<1013            ((c >> 24) & 0xff);1014        return os.str();1015    };1016 1017    std::string from = fileTabs[activeTab].styleName;1018    std::string path = rootPath + "/style/" + name + ".ini";1019    try1020    {1021        if (from == "Classic" || from == "Dark" || from == "Light")1022        {1023            ImGuiStyle style;1024            if (from == "Dark")1025                ImGui::StyleColorsDark(&style);1026            else if (from == "Light")1027                ImGui::StyleColorsLight(&style);1028            else1029                ImGui::StyleColorsClassic(&style);1030 1031            std::map<std::string, std::string> extra;1032            const auto& colors = GetCtxColors(from);1033#define SET_CLR(a) extra[std::string("imrad.colors.") + #a] = FormatClr(colors[UIContext::Color::a]);1034            SET_CLR(Selected);1035            SET_CLR(Hovered);1036            SET_CLR(Snap1);1037            SET_CLR(Snap2);1038            SET_CLR(Snap3);1039            SET_CLR(Snap4);1040            SET_CLR(Snap5);1041#undef SET_CLR1042            ImRad::SaveStyle(path, &style, extra);1043        }1044        else1045        {1046            fs::copy_file(u8path(rootPath + "/style/" + from + ".ini"), u8path(path), fs::copy_options::overwrite_existing);1047        }1048 1049        fileTabs[activeTab].styleName = name;1050        if (!stx::count_if(styleNames, [&](const auto& s) { return s.first == name; }))1051            styleNames.push_back({ name, path });1052 1053        messageBox.title = "Style saved";1054        messageBox.message = "New style was saved as '" + path + "'";1055        messageBox.buttons = ImRad::Ok;1056        messageBox.OpenPopup();1057    }1058    catch (std::exception& e)1059    {1060        messageBox.title = "error";1061        messageBox.message = e.what();1062        messageBox.buttons = ImRad::Ok;1063        messageBox.OpenPopup();1064    }1065}1066 1067void CloneStyle()1068{1069    inputName.title = "Clone Style";1070    inputName.hint = "Enter new style name";1071    inputName.OpenPopup([](ImRad::ModalResult mr)1072        {1073            std::string path = rootPath + "/style/" + inputName.name + ".ini";1074            if (fs::exists(u8string(path))) {1075                messageBox.title = "Confirmation";1076                messageBox.message = "Overwrite existing style?";1077                messageBox.buttons = ImRad::Yes | ImRad::No;1078                messageBox.OpenPopup([=](ImRad::ModalResult mr) {1079                    if (mr == ImRad::Yes)1080                        DoCloneStyle(inputName.name);1081                    });1082            }1083            else1084                DoCloneStyle(inputName.name);1085        });1086}1087 1088void DockspaceUI()1089{1090    // We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into,1091    // because it would be confusing to have two docking targets within each others.1092    ImGuiWindowFlags window_flags = /*ImGuiWindowFlags_MenuBar |*/ ImGuiWindowFlags_NoDocking;1093    ImGuiViewport* viewport = ImGui::GetMainViewport();1094    ImGui::SetNextWindowPos(viewport->Pos + ImVec2(0, TB_SIZE + 0));1095    ImGui::SetNextWindowSize(viewport->Size - ImVec2(0, TB_SIZE + 0));1096    ImGui::SetNextWindowViewport(viewport->ID);1097    ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);1098    ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);1099    window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;1100    window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;1101    window_flags |= ImGuiWindowFlags_NoBackground;1102 1103    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));1104    ImGui::Begin("DockSpace", nullptr, window_flags);1105    ImGui::PopStyleVar();1106    ImGui::PopStyleVar(2);1107 1108    ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");1109    ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_NoDockingOverCentralNode);1110    if (programState == Init)1111    {1112        ImGui::DockBuilderRemoveNode(dockspace_id); // clear any previous layout1113        ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_DockSpace);1114        ImGui::DockBuilderSetNodeSize(dockspace_id, viewport->Size);1115        ImGuiID dock_id_right = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Right, 350.f / viewport->Size.x, nullptr, &dockspace_id);1116        ImGuiID dock_id_left = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 300.f / (viewport->Size.x - 350), nullptr, &dockspace_id);1117        ImGuiID dock_id_right1, dock_id_right2;1118        ImGui::DockBuilderSplitNode(dock_id_right, ImGuiDir_Up, 230.f / (viewport->Size.y - TB_SIZE), &dock_id_right1, &dock_id_right2);1119        float vh = viewport->Size.y - TB_SIZE;1120        ImGuiID dock_id_top = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Up, TAB_SIZE / vh, nullptr, &dockspace_id);1121 1122        ImGui::DockBuilderDockWindow("FileTabs", dock_id_top);1123        ImGui::DockBuilderDockWindow("Hierarchy", dock_id_left);1124        ImGui::DockBuilderDockWindow("Explorer", dock_id_left);1125        ImGui::DockBuilderDockWindow("Widgets", dock_id_right1);1126        ImGui::DockBuilderDockWindow("Properties", dock_id_right2);1127        ImGui::DockBuilderDockWindow("Events", dock_id_right2);1128        ImGui::DockBuilderFinish(dockspace_id);1129    }1130 1131    ImGuiDockNode* cn = ImGui::DockBuilderGetCentralNode(dockspace_id);1132    ctx.designAreaMin = cn->Pos;1133    ctx.designAreaMax = cn->Pos + cn->Size;1134 1135    if (fileTabs.empty())1136    {1137        std::pair<std::string, std::string> help[]{1138            { "Create a New File", "Ctrl+N" },1139            { "Open File", "Ctrl+O" }1140        };1141        float lh = 2 * ImGui::GetTextLineHeight();1142        for (size_t i = 0; i < std::size(help); ++i)1143        {1144            ImVec2 size = ImGui::CalcTextSize((help[i].first + help[i].second).c_str());1145            ImGui::SetCursorScreenPos({1146                viewport->WorkSize.x / 2.5f,1147                (viewport->WorkSize.y - (std::size(help) - 1) * lh) / 2 + i * lh1148                });1149            ImVec4 clr = ImGui::GetStyleColorVec4(ImGuiCol_Text);1150            clr.w = 0.75f;1151            ImGui::PushStyleColor(ImGuiCol_Text, clr);1152            ImGui::Selectable(help[i].first.c_str(), false, 0, { 150, 0 });1153            ImGui::PopStyleColor();1154            clr.w = 1.f;1155            ImGui::PushStyleColor(ImGuiCol_Text, clr);1156            for (size_t c = 0; c < help[i].second.size(); )1157            {1158                bool first = !c;1159                std::string sub;1160                size_t j = help[i].second.find('+', c);1161                if (j != std::string::npos) {1162                    sub = help[i].second.substr(c, j - c);1163                    c = j + 1;1164                }1165                else {1166                    sub = help[i].second.substr(c);1167                    c = j;1168                }1169                ImGui::SameLine(0, 0);1170                if (!first) {1171                    ImGui::Text(" + ");1172                    ImGui::SameLine(0, 0);1173                }1174                ImGui::Selectable(sub.c_str(), true, 0, { ImGui::CalcTextSize(sub.c_str()).x, 0 });1175            }1176            ImGui::PopStyleColor();1177        }1178    }1179    else1180    {1181        float sp = ImGui::GetStyle().ItemSpacing.x;1182        ImGui::SetCursorScreenPos({1183            ctx.designAreaMin.x + sp,1184            ctx.designAreaMax.y - ImGui::GetTextLineHeight() - sp1185            });1186        ImVec4 clr = ImGui::GetStyleColorVec4(ImGuiCol_Text);1187        clr.w = 0.5f;1188        ImGui::PushStyleColor(ImGuiCol_Text, clr);1189        ImGui::Text("Zoom: %d%%", (int)(ctx.zoomFactor * 100));1190        ImGui::PopStyleColor();1191    }1192 1193    ImGui::End();1194}1195 1196void ToolbarUI()1197{1198    ImGuiViewport* viewport = ImGui::GetMainViewport();1199    ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + 0));1200    ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, TB_SIZE));

Showing the first 1,200 of 2830 lines. Download the file for the rest.