CoolFace
Datasetpublic

dlxjj/imradv3

sourceHugging Faceupdated 8mo agoView on Hugging Face
0likes263downloads
binding_input.h1269 linesDownload Raw Back to src
1#pragma once2#include <array>3#include <optional>4#include <imgui.h>5#include <imgui_internal.h>6#include <misc/cpp/imgui_stdlib.h>7#include "stx.h"8#include "utils.h"9#include "binding_property.h"10#include "cppgen.h"11#include "ui_new_field.h"12#include "ui_binding.h"13#include "ui_combo_dlg.h"14 15inline const char* PARENT_STR = "inherit";16inline const uint32_t NONE_COLOR = 0xff800000;17inline const uint32_t NEW_COLOR = 0xff006000;18inline const uint32_t RENAME_COLOR = 0xff004080;19 20inline bool IsHighlighted(const std::string& id)21{22    ImGuiID iid = ImGui::GetID(id.c_str());23    if (ImGui::GetHoveredID() == iid || ImGui::GetActiveID() == iid || ImGui::GetFocusID() == iid)24        return true;25    ImGuiID popupId = ImGui::GetIDWithSeed("##ComboPopup", 0, iid);26    if (ImGui::IsPopupOpen(popupId, 0))27        return true;28    return false;29}30 31enum {32    BindingButton_ReferenceOnly = 0x133};34 35template <class T>36inline bool BindingButton(const char* label, bindable<T>* val, const std::string& type, int flags, UIContext& ctx)37{38    if (val == ctx.setProp)39    {40        //commit dialog request41        ctx.setProp = nullptr;42        *val->access() = ctx.setPropValue;43        return true;44    }45 46    bool bound;47    if constexpr (std::is_same_v<T, std::string> ||48        std::is_same_v<T, std::vector<std::string>> ||49        std::is_same_v<T, color_t>)50    {51        bound = !val->used_variables().empty();52    }53    else if constexpr (std::is_same_v<T, bool>)54        bound = !val->empty(); //the default value is usually empty55    else56        bound = !val->empty() && !val->has_value();57 58    ImGui::PushStyleColor(ImGuiCol_Button, bound ? 0xff0080ff : 0xffc0c0c0);59    float sp = (ImGui::GetFrameHeight() - 12) / 2;60    ImGui::SetCursorPosX(ImGui::GetCursorPosX() + sp);61    ImGui::SetCursorPosY(ImGui::GetCursorPosY() + sp);62    ImGui::PushItemFlag(ImGuiItemFlags_NoNav, true);63    bool pushed = ImGui::Button(("##" + std::string(label)).c_str(), { 12, 12 });64    ImGui::PopItemFlag();65    ImGui::PopStyleColor();66    if (pushed)67    {68        bindingDlg.font = type.find("std::string") != std::string::npos ? ctx.defaultStyleFont : nullptr;69        bindingDlg.codeGen = ctx.codeGen;70        bindingDlg.curArray = ctx.GetCurrentArray();71        bindingDlg.name = label;72        bindingDlg.expr = val->c_str();73        bindingDlg.type = type;74        bindingDlg.forceReference = flags & BindingButton_ReferenceOnly;75        bindingDlg.OpenPopup([&ctx, val](ImRad::ModalResult) {76            ctx.setProp = val;77            ctx.setPropValue = bindingDlg.expr;78            });79        return true;80    }81 82    return false;83}84 85template <class T, class = std::enable_if_t<!std::is_same_v<T, void>>>86inline bool BindingButton(const char* label, bindable<T>* val, int flags, UIContext& ctx)87{88    return BindingButton(label, val, typeid_name<T>(), flags, ctx);89}90 91template <class T, class = std::enable_if_t<!std::is_same_v<T, void>>>92inline bool BindingButton(const char* label, bindable<T>* val, UIContext& ctx)93{94    return BindingButton(label, val, typeid_name<T>(), 0, ctx);95}96 97//---------------------------------------------------------------------------------98 99enum100{101    InputDirectVal_Modified = 0x1,102    InputDirectVal_ShortcutButton = 0x2,103};104 105template <class T>106bool InputDirectVal(direct_val<T, false>* val, int fl, UIContext& ctx)107{108    ImGui::PushFont(!ImRad::IsCurrentItemDisabled() && (fl & InputDirectVal_Modified) ?109        ctx.pgbFont : ctx.pgFont);110    std::string id = "##" + std::to_string((uint64_t)val);111    bool changed = false;112    if constexpr (std::is_same_v<T, int>) {113        bool high = IsHighlighted(id);114        ImGui::PushID(id.c_str());115        high |= IsHighlighted("+") || IsHighlighted("-");116        ImGui::PopID();117        if (ImRad::IsCurrentItemDisabled())118            high = false;119        changed = ImGui::InputInt(id.c_str(), val->access(), high ? 1 : 0);120    }121    else if constexpr (std::is_same_v<T, float>)122        changed = ImGui::InputFloat(id.c_str(), val->access(), 0, 0, "%.f");123    else124        assert(false);125 126    ImGui::PopFont();127    return changed;128}129 130inline bool InputDirectVal(direct_val<dimension_t>* val, int flags, UIContext& ctx)131{132    ImGui::PushFont(!ImRad::IsCurrentItemDisabled() && (flags & InputDirectVal_Modified) ?133        ctx.pgbFont : ctx.pgFont);134    std::string id = "##" + std::to_string((uint64_t)val);135    bool changed = ImGui::InputFloat(id.c_str(), val->access(), 0, 0, "%.0f");136    ImGui::PopFont();137    return changed;138}139 140inline bool InputDirectVal(direct_val<pzdimension_t>* val, UIContext& ctx)141{142    ImGui::PushFont(val->has_value() ? ctx.pgbFont : ctx.pgFont);143    std::string id = "##" + std::to_string((uint64_t)val);144    std::string tmp = val->has_value() ? std::to_string((int)*val->access()) : "";145    std::string hint = ImGui::GetActiveID() == ImGui::GetCurrentWindow()->GetID(id.c_str()) ? "" : PARENT_STR;146    bool changed = ImGui::InputTextWithHint(id.c_str(), hint.c_str(), &tmp, ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll);147    if (changed)148    {149        std::istringstream is(tmp);150        is >> *val->access();151        if (!is && ImGui::IsItemDeactivatedAfterEdit())152            val->clear();153    }154    ImGui::PopFont();155    return changed;156}157 158inline bool InputDirectVal(direct_val<pzdimension2_t>* val, UIContext& ctx)159{160    bool changed = false;161    std::string id = "##" + std::to_string((uint64_t)val);162    ImGui::PushFont(!ImRad::IsCurrentItemDisabled() && val->has_value() ?163        ctx.pgbFont : ctx.pgFont);164    ImGui::PushMultiItemsWidths(2, ImGui::CalcItemWidth());165    for (int i = 0; i < 2; ++i)166    {167        ImGui::PushID(i);168        if (i)169            ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x);170        //bool ch = ImGui::InputFloat2(id.c_str(), (float*)val->access(), "%.0f");171        std::string tmp = val->has_value() ? std::to_string((int)(*val->access())[i]) : "";172        std::string hint = i || ImGui::GetActiveID() == ImGui::GetCurrentWindow()->GetID(id.c_str()) ? "" : PARENT_STR;173        if (ImGui::InputTextWithHint(id.c_str(), hint.c_str(), &tmp, ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll))174        {175            changed = true;176            std::istringstream is(tmp);177            is >> (*val->access())[i];178            if (!is && ImGui::IsItemDeactivatedAfterEdit())179                val->clear();180        }181        ImGui::PopItemWidth();182        ImGui::PopID();183    }184    ImGui::PopFont();185    return changed;186}187 188inline bool InputDirectVal(direct_val<bool>* val, int fl, UIContext& ctx)189{190    std::string id = "##" + std::to_string((uint64_t)val);191    bool val1 = *val;192 193    ImGui::PushStyleColor(ImGuiCol_CheckMark, ImGui::GetStyleColorVec4(194        (fl & InputDirectVal_Modified) ? ImGuiCol_Text : ImGuiCol_TextDisabled));195 196    if ((fl & InputDirectVal_Modified) && !val1) {197        ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2);198        ImGui::PushStyleColor(ImGuiCol_Border, ImGui::GetStyleColorVec4(ImGuiCol_Text));199    }200 201    bool changed = ImGui::Checkbox(id.c_str(), val->access());202 203    if ((fl & InputDirectVal_Modified) && !val1) {204        ImGui::PopStyleVar();205        ImGui::PopStyleColor();206    }207    ImGui::PopStyleColor();208 209    return changed;210}211 212inline bool InputDirectVal(direct_val<std::string>* val, int fl, UIContext& ctx)213{214    ImGui::PushFont(215        !IsAscii(*val->access()) ? ctx.defaultStyleFont :216        !ImRad::IsCurrentItemDisabled() && (fl & InputDirectVal_Modified) ? ctx.pgbFont :217        ctx.pgFont218    );219    std::string id = "##" + std::to_string((uint64_t)val);220    bool ch = ImGui::InputText(id.c_str(), val->access(), ImGuiInputTextFlags_CallbackCharFilter, DefaultCharFilter);221    ImGui::PopFont();222    return ch;223}224 225inline bool InputDirectVal(direct_val<shortcut_t>* val, int flags, UIContext& ctx)226{227    if (flags & InputDirectVal_ShortcutButton)228        ImGui::SetNextItemWidth(ImGui::CalcItemWidth() - ImGui::GetFrameHeight());229 230    std::string id = "##" + std::to_string((uint64_t)val);231    ImGui::PushFont(!ImRad::IsCurrentItemDisabled() ? ctx.pgbFont : ctx.pgFont);232    bool changed = ImGui::InputText(id.c_str(), val->access(), ImGuiInputTextFlags_CallbackCharFilter, DefaultCharFilter);233    ImGui::PopFont();234 235    if (flags & InputDirectVal_ShortcutButton)236    {237        std::string buttonId = id + "But";238        std::string popupId = id + "DropDown";239 240        ImGui::SameLine(0, 0);241        if (IsHighlighted(id) || IsHighlighted(buttonId) ||242            ImGui::IsPopupOpen(ImGui::GetID(popupId.c_str()), 0))243        {244            ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[val->flags() ? ImGuiCol_ButtonActive : ImGuiCol_Button]);245            if (ImGui::ArrowButton(buttonId.c_str(), ImGuiDir_Down)) // { ImGui::GetFrameHeight(), ImGui::GetFrameHeight() }))246            {247                ImGui::OpenPopup(popupId.c_str());248            }249            ImGui::PopStyleColor();250        }251        else252        {253            ImGui::InvisibleButton(buttonId.c_str(), { ImGui::GetFrameHeight(), ImGui::GetFrameHeight() });254        }255 256        ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 8, 8 });257        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, { 0, 8 });258        if (ImGui::BeginPopup(popupId.c_str()))259        {260            if (ImGui::MenuItem("Global", nullptr, val->flags() & ImGuiInputFlags_RouteGlobal)) {261                changed = true;262                val->set_flags(val->flags() ^ ImGuiInputFlags_RouteGlobal);263            }264            if (ImGui::MenuItem("Repeat", nullptr, val->flags() & ImGuiInputFlags_Repeat)) {265                changed = true;266                val->set_flags(val->flags() ^ ImGuiInputFlags_Repeat);267           }268           ImGui::EndPopup();269        }270        ImGui::PopStyleVar(2);271    }272 273    return changed;274}275 276 277inline bool InputDirectValContextMenu(direct_val<std::string>* val, UIContext& ctx)278{279    bool changed = false;280    ImGui::PushFont(!ImRad::IsCurrentItemDisabled() ? ctx.pgbFont : ctx.pgFont);281    std::string id = "##" + std::to_string((uint64_t)val);282    if (ImGui::BeginCombo(id.c_str(), val->c_str(),283        IsHighlighted(id) ? 0 : ImGuiComboFlags_NoArrowButton))284    {285        ImGui::PopFont();286        ImGui::PushFont(ImGui::GetFont());287 288        if (ImGui::Selectable(" ", val->empty()))289        {290            changed = true;291            *val->access() = "";292        }293        for (const std::string& cm : ctx.contextMenus)294        {295            if (ImGui::Selectable(cm.c_str(), cm == val->c_str()))296            {297                changed = true;298                *val->access() = cm;299            }300        }301        ImGui::EndCombo();302    }303    ImGui::PopFont();304    return changed;305}306 307template <class T>308inline bool InputDirectValEnum(direct_val<T, true>* val, int fl, UIContext& ctx)309{310    bool changed = false;311    std::string id = "##" + std::to_string((uint64_t)val);312    std::string value = val->get_id();313    size_t pre = 0;314    if (!value.compare(0, 5, "ImGui")) {315        pre = value.find("_");316        if (pre != std::string::npos && pre + 1 < value.size())317            ++pre;318        else319            pre = 0;320    }321    ImGui::PushFont(!ImRad::IsCurrentItemDisabled() && (fl & InputDirectVal_Modified) ?322        ctx.pgbFont : ctx.pgFont);323    if (ImGui::BeginCombo(id.c_str(), val->get_id().c_str() + pre,324        !ImRad::IsCurrentItemDisabled() && IsHighlighted(id) ? 0 : ImGuiComboFlags_NoArrowButton))325    {326        ImGui::PopFont();327        ImGui::PushFont(ImGui::GetFont());328        changed = true;329        for (const auto& item : val->get_ids())330        {331            if (!item.first.compare(0, 5, "ImGui")) {332                pre = item.first.find("_");333                if (pre != std::string::npos && pre + 1 < item.first.size())334                    ++pre;335                else336                    pre = 0;337            }338            if (ImGui::Selectable(item.first.c_str() + pre, *val->access() == item.second))339                *val->access() = item.second;340        }341        ImGui::EndCombo();342    }343    ImGui::PopFont();344    return changed;345}346 347template <class T>348inline int InputDirectValFlags(const char* name, direct_val<T, true>* val, int defVal, UIContext& ctx)349{350    int changed = false;351    ImVec2 pad = ImGui::GetStyle().FramePadding;352    ImGui::Unindent();353    ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 0.0f, pad.y });354    //ImGui::PushStyleColor(ImGuiCol_NavCursor, { 0, 0, 0, 0 });355    ImGui::SetNextItemAllowOverlap();356    if (ImGui::TreeNodeEx(name, ImGuiTreeNodeFlags_SpanAllColumns /*| ImGuiTreeNodeFlags_NoNavFocus*/)) {357        ImGui::PopStyleVar();358        ImGui::Indent();359        ImGui::TableNextColumn();360        ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { pad.x, 0 }); //row packing361        ImGui::Spacing();362        for (const auto& id : val->get_ids())363        {364            if (id.first == "") {365                ImGui::Separator();366                continue;367            }368            if (defVal != -1) {369                bool different = ((int)*val & id.second) != (defVal & id.second);370                ImGui::PushFont(ImRad::GetFontByName(different ? "imrad.pgb" : "imrad.pg"));371            }372            size_t pre = 0;373            if (!id.first.compare(0, 5, "ImGui")) {374                pre = id.first.find('_');375                if (pre != std::string::npos && pre + 1 < id.first.size())376                    ++pre;377                else378                    pre = 0;379            }380            ImU64 flags = *val;381            if (ImGui::CheckboxFlags(id.first.c_str() + pre, &flags, id.second)) {382                changed = id.second;383                *val->access() = (int)flags;384            }385            if (defVal != -1)386                ImGui::PopFont();387        }388        ImGui::PopStyleVar();389        ImGui::TreePop();390        ImGui::Unindent();391    }392    else393    {394        ImGui::PopStyleVar();395        ImGui::TableNextColumn();396        std::string label, tip;397        for (const auto& id : val->get_ids())398        {399            if (id.first != "" && (*val & id.second) == id.second)400            {401                size_t pre = 0;402                if (!id.first.compare(0, 5, "ImGui")) {403                    size_t i = id.first.find('_');404                    if (i != std::string::npos && i + 1 < id.first.size())405                        pre = i + 1;406                }407                tip += id.first.substr(pre) + "\n";408            }409        }410        if (tip == "")411            tip = "None";412        ImGui::SetNextItemWidth(-ImGui::GetFrameHeight());413        ImGui::PushFont(!ImRad::IsCurrentItemDisabled() && *val != defVal ?414            ctx.pgbFont : ctx.pgFont);415        //float w = ImGui::GetContentRegionAvail().x;416        ImGui::Text("...");417        ImGui::PopFont();418        if (//ImGui::GetItemRectSize().x > w &&419            ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))420        {421            ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 8, 8 });422            ImGui::SetTooltip("%s", tip.c_str());423            ImGui::PopStyleVar();424        }425    }426    ImGui::Indent();427    //ImGui::PopStyleColor();428    return changed;429}430 431//-------------------------------------------------------------------------------432 433enum434{435    InputBindable_StretchButton = 0x1,436    InputBindable_StretchButtonDisabled = InputBindable_StretchButton | 0x2,437    InputBindable_MultilineEdit = 0x4,438    InputBindable_CustomButton = 0x8,439    InputBindable_Modified = 0x10,440    InputBindable_ShowVariables = 0x20,441    InputBindable_ShowNone = 0x40,442};443 444template <class T,445    class = std::enable_if_t<!std::is_same_v<T, dimension_t>> >446inline bool InputBindable(bindable<T>* val, const std::string& type, int flags, UIContext& ctx)447{448    if (val == ctx.setProp)449    {450        //commit dialog request451        ctx.setProp = nullptr;452        *val->access() = ctx.setPropValue;453        return true;454    }455 456    bool changed = false;457    std::string id = "##" + std::to_string((uint64_t)val);458 459    if (!(flags & InputBindable_ShowVariables))460    {461        int fl = ImGuiInputTextFlags_CallbackCharFilter;462        if constexpr (!std::is_same_v<T, std::string>) {463            if (val->has_value())464                fl |= ImGuiInputTextFlags_AutoSelectAll;465        }466        ImGui::PushFont(!ImRad::IsCurrentItemDisabled() && (flags & InputBindable_Modified) ?467            ctx.pgbFont : ctx.pgFont);468        changed = ImGui::InputText(id.c_str(), val->access(), fl, DefaultCharFilter);469        ImGui::PopFont();470 471        /*if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip) &&472            ImGui::CalcTextSize(val->c_str()).x > ImGui::GetItemRectSize().x)473        {474            ImGui::SetItemTooltip(val->c_str());475        }*/476        if (ImGui::IsItemDeactivatedAfterEdit())477        {478            //disallow empty state479            std::string v = Trim(val->c_str());480            if (v.empty())481                *val = {};482            else483                *val->access() = v;484        }485    }486    else487    {488        ImGui::PushFont(!ImRad::IsCurrentItemDisabled() && (flags & InputBindable_Modified) ?489            ctx.pgbFont : ctx.pgFont);490        if (ImGui::BeginCombo(id.c_str(), val->c_str(),491            !ImRad::IsCurrentItemDisabled() && IsHighlighted(id) ? 0 : ImGuiComboFlags_NoArrowButton))492        {493            ImGui::PopFont();494            ImGui::PushFont(ImGui::GetFont());495 496            ImGui::PushStyleColor(ImGuiCol_Text, NONE_COLOR);497            if ((flags & InputBindable_ShowNone) && ImGui::Selectable("None"))498            {499                *val->access() = "";500                changed = true;501            }502            ImGui::PopStyleColor();503 504            ImGui::PushStyleColor(ImGuiCol_Text, RENAME_COLOR);505            if (val->has_single_variable() && ImGui::Selectable("Rename..."))506            {507                auto vars = val->used_variables();508                newFieldPopup.codeGen = ctx.codeGen;509                newFieldPopup.varOldName = vars[0];510                newFieldPopup.mode = NewFieldPopup::RenameField;511                newFieldPopup.OpenPopup([val, root = ctx.root]{512                    root->RenameFieldVars(newFieldPopup.varOldName, newFieldPopup.varName);513                    });514            }515            ImGui::PopStyleColor();516 517            ImGui::PushStyleColor(ImGuiCol_Text, NEW_COLOR);518            if (ImGui::Selectable("New Variable..."))519            {520                newFieldPopup.varType = type;521                newFieldPopup.codeGen = ctx.codeGen;522                newFieldPopup.mode = NewFieldPopup::NewField;523                newFieldPopup.OpenPopup([&ctx, val] {524                    ctx.setProp = val;525                    ctx.setPropValue = newFieldPopup.varName;526                    });527            }528            ImGui::PopStyleColor();529 530            ImGui::Separator();531            auto vars = ctx.codeGen->GetVarExprs(type, true, ctx.GetCurrentArray());532            /*auto* dc = ImGui::GetCurrentWindow()->DrawList;533            float sp = ImGui::CalcTextSize(" ").x;*/ 534            for (const auto& v : vars)535            {536                if (ImGui::Selectable(v.first.c_str(), v.first == val->c_str()))537                {538                    *val->access() = v.first;539                    changed = true;540                }541                /*ImVec2 p = ImGui::GetCursorScreenPos();542                p.x += sp;543                p.y -= 0.5f * ImGui::GetTextLineHeight();544                dc->AddCircleFilled(p, 0.2f * ImGui::GetFontSize(), 0xff000000);*/545            }546 547            ImGui::EndCombo();548        }549        ImGui::PopFont();550    }551 552    return changed;553}554 555template <class T,556    class = std::enable_if_t<!std::is_same_v<T, void> && !std::is_same_v<T, dimension_t>> >557    inline bool InputBindable(bindable<T>* val, int flags, UIContext& ctx)558{559    return InputBindable(val, typeid_name<T>(), flags, ctx);560}561 562inline bool InputBindable(bindable<font_name_t>* val, UIContext& ctx)563{564    std::string fn = val->empty() ? PARENT_STR :565        val->has_value() ? val->eval(ctx) : val->c_str();566    bool changed = false;567    std::string id = "##" + std::to_string((uint64_t)val);568    if (ImGui::BeginCombo(id.c_str(), nullptr,569        ImGuiComboFlags_CustomPreview | (IsHighlighted(id) ? 0 : ImGuiComboFlags_NoArrowButton)))570    {571        for (const auto& f : ctx.fontNames)572        {573            if (ImGui::Selectable(f == "" ? " " : f.c_str(), f == fn)) {574                changed = true;575                if (f == "")576                    *val->access() = f;577                else578                    val->set_font_name(f);579            }580        }581        ImGui::EndCombo();582    }583    if (ImGui::BeginComboPreview())584    {585        ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyleColorVec4(586            val->empty() ? ImGuiCol_TextDisabled : ImGuiCol_Text));587        ImGui::PushFont(!ImRad::IsCurrentItemDisabled() && !val->empty() ?588            ctx.pgbFont : ctx.pgFont);589        ImGui::TextUnformatted(fn.c_str());590        ImGui::PopFont();591        ImGui::PopStyleColor();592        ImGui::EndComboPreview();593    }594    return changed;595}596 597inline bool InputBindable(bindable<color_t>* val, int defStyleCol, UIContext& ctx)598{599    static std::string lastColor;600    static int lastStyleClr;601 602    auto nextData = ImGui::GetCurrentContext()->NextItemData; //copy603    int styleClr = val->style_color();604    ImVec4 buttonClr = val->empty() ?605        ctx.style.Colors[defStyleCol] :606        ImGui::ColorConvertU32ToFloat4(val->eval(defStyleCol, ctx));607    std::string id = "##" + std::to_string((uint64_t)val);608    ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]);609    if (ImGui::ColorButton(id.c_str(), buttonClr, ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_AlphaPreview))610    {611        lastColor = val->c_str();612        lastStyleClr = styleClr;613        ImGui::OpenPopup(id.c_str());614    }615    ImGui::PopStyleColor();616 617    ImGui::SameLine();618    ImVec2 sz{ 0, 0 };619    if (nextData.HasFlags & ImGuiNextItemDataFlags_HasWidth)620    {621        sz.x = nextData.Width;622        if (sz.x < 0)623            sz.x += ImGui::GetContentRegionAvail().x;624    }625    std::string clrName = styleClr >= 0 ? ImGui::GetStyleColorName(styleClr) :626        val->empty() ? PARENT_STR :627        val->c_str();628    clrName += id;629    ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyleColorVec4(val->empty() ? ImGuiCol_TextDisabled : ImGuiCol_Text));630    ImGui::PushFont(!ImRad::IsCurrentItemDisabled() && !val->empty() ?631        ctx.pgbFont : ctx.pgFont);632    if (ImGui::Selectable(clrName.c_str(), false, 0, sz))633    {634        lastColor = val->c_str();635        lastStyleClr = styleClr;636        ImGui::OpenPopup(id.c_str());637    }638    ImGui::PopFont();639    ImGui::PopStyleColor();640 641    static ImU32 COLORS[]{642        /* 5x5 palette643        IM_COL32(255, 255, 255, 255),644        IM_COL32(246, 246, 194, 255),645        IM_COL32(202, 23, 55, 255),646        IM_COL32(246, 58, 56, 255),647        IM_COL32(162, 34, 31, 255),648        IM_COL32(7, 17, 115, 255),649        IM_COL32(159, 215, 252, 255),650        IM_COL32(15, 63, 25, 255),651        IM_COL32(96, 231, 66, 255),652        IM_COL32(205, 255, 202, 255),653        IM_COL32(246, 253, 85, 255),654        IM_COL32(248, 117, 0, 255),655        IM_COL32(244, 180, 118, 255),656        IM_COL32(104, 102, 90, 255),657        IM_COL32(165, 166, 160, 255),658        IM_COL32(54, 8, 81, 255),659        IM_COL32(148, 35, 213, 255),660        IM_COL32(248, 181, 248, 255),661        IM_COL32(204, 22, 182, 255),662        IM_COL32(219, 190, 2, 255),663        IM_COL32(10, 226, 211, 255),664        IM_COL32(2, 251, 171, 255),665        IM_COL32(143, 105, 69, 255),666        IM_COL32(59, 33, 8, 255),667        IM_COL32(0, 0, 0, 255),*/668 669        //8x5 palette670        IM_COL32(255,255,255,255), //IM_COL32(0,0,0,255),671        IM_COL32(152,51,0,255),672        IM_COL32(51,51,0,255),673        IM_COL32(0,51,0,255),674        IM_COL32(0,51,102,255),675        IM_COL32(0,0,128,255),676        IM_COL32(51,51,153,255),677        IM_COL32(0,0,0,255),678 679        IM_COL32(128,0,0,255),680        IM_COL32(255,102,0,255),681        IM_COL32(128,128,0,255),682        IM_COL32(0,128,0,255),683        IM_COL32(0,128,128,255),684        IM_COL32(0,0,255,255),685        IM_COL32(102,102,153,255),686        IM_COL32(64,64,64,255),687 688        IM_COL32(255,0,0,255),689        IM_COL32(255,153,0,255),690        IM_COL32(153,204,0,255),691        IM_COL32(51,153,102,255),692        IM_COL32(51,204,204,255),693        IM_COL32(51,102,255,255),694        IM_COL32(128,0,128,255),695        IM_COL32(128,128,128,255),696 697        IM_COL32(254,0,255,255),698        IM_COL32(255,203,0,255),699        IM_COL32(255,255,0,255),700        IM_COL32(0,255,0,255),701        IM_COL32(0,255,254,255),702        IM_COL32(0,204,255,255),703        IM_COL32(153,51,102,255),704        IM_COL32(192,192,192,255),705 706        IM_COL32(255,153,204,255),707        IM_COL32(255,204,151,255),708        IM_COL32(255,255,153,255),709        IM_COL32(205,255,205,255),710        IM_COL32(205,255,255,255),711        IM_COL32(153,204,254,255),712        IM_COL32(204,154,255,255),713        IM_COL32(255,255,255,255),714    };715    bool changed = false;716    static std::string lastOpen;717    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 5, 5 });718    ImGui::SetNextWindowPos(ImGui::GetCursorScreenPos() + ImVec2{ ImGui::GetContentRegionAvail().x, 0 }, ImGuiCond_Always, { 1, 0 });719    if (ImGui::BeginPopup(id.c_str(), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoNav))720    {721        lastOpen = id.c_str();722        *val->access() = lastColor;723        bool autoSel = ImGui::ColorButton("tooltip", ctx.style.Colors[defStyleCol], ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_AlphaPreview);724        bool autoHover = ImGui::IsItemHovered();725        ImGui::SameLine(0, 0);726        ImGui::Selectable("  Automatic", false, ImGuiSelectableFlags_NoPadWithHalfSpacing);727        autoHover = autoHover || ImGui::IsItemHovered();728        autoSel = autoSel || ImGui::IsItemClicked(ImGuiMouseButton_Left);729        if (autoSel)730        {731            changed = true;732            lastColor = "";733            *val = {};734        }735        if (autoHover)736        {737            *val = {};738        }739        ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0);740        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, { 4, 4 });741        for (int i = 0; i < stx::ssize(COLORS); ++i)742        {743            ImGui::PushID(i);744            ImGui::PushStyleColor(ImGuiCol_Button, COLORS[i]);745            ImGui::PushStyleColor(ImGuiCol_ButtonHovered, COLORS[i]);746            //if (ImGui::ColorButton("##clr", ImGui::ColorConvertU32ToFloat4(COLORS[i]), ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_AlphaPreview, { 30, 30 }))747            if (ImGui::Button("##clr", { 30, 30 }))748            {749                changed = true;750                *val = i ? COLORS[i] : 0x00ffffff;751                lastColor = *val->access();752            }753            if (ImGui::IsItemHovered())754            {755                *val = i ? COLORS[i] : 0x00ffffff;756            }757            if (!i)758            {759                ImVec2 p1 = ImGui::GetItemRectMin();760                ImVec2 p2 = ImGui::GetItemRectMax();761                ImGui::GetWindowDrawList()->AddLine({ p1.x, p2.y }, { p2.x, p1.y }, 0xff0000ff);762            }763            ImGui::PopStyleColor(2);764            ImGui::PopID();765            if ((i + 1) % 8)766                ImGui::SameLine();767        }768        ImGui::PopStyleVar(2);769        ImGui::Spacing();770        ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);771        int clri = val->style_color();772        std::string clrName = lastStyleClr >= 0 ? ImGui::GetStyleColorName(lastStyleClr) : "Style Color...";773        if (ImGui::BeginCombo("##cmb", clrName.c_str()))774        {775            for (int i = 0; i < ImGuiCol_COUNT; ++i)776            {777                auto cc = ctx.style.Colors[i];778                auto ccc = ImGui::ColorConvertFloat4ToU32(cc);779                ImGui::ColorButton("##color", cc, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoBorder | ImGuiColorEditFlags_AlphaPreview);780                ImGui::SameLine();781                if (ImGui::Selectable(ImGui::GetStyleColorName(i), clri == i))782                {783                    changed = true;784                    val->set_style_color(i);785                    lastColor = *val->access();786                    break;787                }788                ImRect r{ ImGui::GetItemRectMin(), ImGui::GetItemRectMax() };789                r.Min.y -= ImGui::GetStyle().ItemSpacing.y;790                if (r.Contains(ImGui::GetMousePos())) //more stable than IsItemHovered791                {792                    val->set_style_color(i);793                }794            }795            ImGui::EndCombo();796        }797        if (changed)798            ImGui::CloseCurrentPopup();799        ImGui::EndPopup();800    }801    else if (lastOpen == id.c_str())802    {803        lastOpen = "";804        //return last value if the current color was hovered only805        *val->access() = lastColor;806    }807    ImGui::PopStyleVar();808 809    return changed;810}811 812inline bool InputBindable(bindable<std::string>* val, int flags, UIContext& ctx, std::function<void()> fun = [] {})813{814    std::string id = "##" + std::to_string((uint64_t)val);815    std::string butId = "..." + id;816    bool high = IsHighlighted(id) || IsHighlighted(butId);817    bool hasButton = flags & (InputBindable_MultilineEdit | InputBindable_CustomButton);818    float w = ImGui::CalcItemWidth();819    if (hasButton && high)820        w -= ImGui::GetFrameHeight();821 822    ImGui::SetNextItemWidth(w);823    ImGui::PushFont(824        !IsAscii(*val->access()) ? ctx.defaultStyleFont :825        !ImRad::IsCurrentItemDisabled() ? ctx.pgbFont :826        ctx.pgFont827    );828    bool changed = ImGui::InputText(id.c_str(), val->access(), ImGuiInputTextFlags_CallbackCharFilter, DefaultCharFilter);829    ImGui::PopFont();830    831    if (hasButton && high)832    {833        ImGui::SameLine(0, 0);834        ImGui::PushItemFlag(ImGuiItemFlags_NoNav, true);835        bool isDown = false;836        if (flags & InputBindable_MultilineEdit)837            isDown = val->access()->find('\n') != std::string::npos;838        ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyleColorVec4(839            isDown ? ImGuiCol_ButtonActive : ImGuiCol_Button840            ));841        if (ImGui::Button(butId.c_str(), { ImGui::GetFrameHeight(), ImGui::GetFrameHeight() }))842        {843            if (flags & InputBindable_CustomButton)844            {845                fun();846            }847            else if (flags & InputBindable_MultilineEdit)848            {849                comboDlg.title = "Multiline text";850                comboDlg.value = *val->access();851                comboDlg.font = ctx.defaultStyleFont;852                comboDlg.OpenPopup([&ctx, val](ImRad::ModalResult mr) {853                    ctx.setProp = val;854                    ctx.setPropValue = comboDlg.value;855                    });856            }857        }858        ImGui::PopStyleColor();859        ImGui::PopItemFlag();860    }861 862    return changed;863}864 865inline bool InputBindable(bindable<std::vector<std::string>>* val, UIContext& ctx)866{867    bool changed = false;868    std::string id = "##" + std::to_string((uint64_t)val);869    std::string label;870    int nl = (int)stx::count(*val->access(), '\0');871    if (!val->has_single_variable())872        label = "[" + std::to_string(nl) + "]";873    else874        label = val->used_variables()[0];875    label += id;876 877    ImGui::PushFont(!ImRad::IsCurrentItemDisabled() && !val->empty() ?878        ctx.pgbFont : ctx.pgFont);879    /*float w = ImGui::CalcItemWidth();880    ImGui::SetNextItemWidth(w - ImGui::GetFrameHeight());881 882    ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);883    ImRad::Selectable(label.c_str(), false, 0, { -2 * ImGui::GetFrameHeight(), 0 });884    ImGui::PopItemFlag();885    ImGui::PopFont();886 887    bool high = IsHighlighted(label) || IsHighlighted(id);888    ImGui::SameLine(0, 0);889    ImGui::SetNextItemWidth(-ImGui::GetFrameHeight());890    ImGui::SetNextWindowSizeConstraints({ w, 0 }, { FLT_MAX, FLT_MAX });891    if (high && ImGui::BeginCombo(id.c_str(), nullptr, ImGuiComboFlags_NoPreview))*/892    if (ImGui::BeginCombo(id.c_str(), label.c_str(),893            IsHighlighted(id) ? 0 : ImGuiComboFlags_NoArrowButton))894    {895        ImGui::PopFont();896        ImGui::PushFont(ImGui::GetFont());897 898        ImGui::PushStyleColor(ImGuiCol_Text, RENAME_COLOR);899        if (ImGui::Selectable("Edit Items..."))900        {901            changed = true;902            std::string tmp = *val->access(); //preserve embeded nulls903            stx::replace(tmp, '\0', '\n');904            if (tmp.size() && tmp.back() == '\n')905                tmp.pop_back();906            comboDlg.title = "Items";907            comboDlg.value = tmp;908            comboDlg.font = ctx.defaultStyleFont;909            comboDlg.OpenPopup([val](ImRad::ModalResult) {910                std::string tmp = comboDlg.value;911                while (tmp.size() && tmp.back() == '\n')912                    tmp.pop_back();913                *val->access() = tmp;914                if (!val->has_single_variable()) {915                    if (tmp.size() && tmp.back() != '\n')916                        tmp.push_back('\n');917                    stx::replace(tmp, '\n', '\0');918                    *val->access() = tmp;919                }920                });921        }922        ImGui::PopStyleColor();923 924        ImGui::PushStyleColor(ImGuiCol_Text, NEW_COLOR);925        if (ImGui::Selectable("New Variable..."))926        {927            newFieldPopup.varType = "std::vector<std::string>";928            newFieldPopup.codeGen = ctx.codeGen;929            newFieldPopup.mode = NewFieldPopup::NewField;930            newFieldPopup.OpenPopup([val, &ctx] {931                *val->access() = '{' + newFieldPopup.varName + '}';932                //todo933                //ctx.setProp = &items;934                //ctx.setPropValue = '{' + newFieldPopup.varName + '}';935                });936        }937        ImGui::PopStyleColor();938 939        ImGui::Separator();940        const auto& vars = ctx.codeGen->GetVarExprs("std::vector<std::string>", true, ctx.GetCurrentArray());941        for (const auto& v : vars)942        {943            if (ImGui::Selectable(v.first.c_str(), '{' + v.first + '}' == val->c_str()))944            {945                *val->access() = '{' + v.first + '}';946                changed = true;947            }948        }949        ImGui::EndCombo();950    }951 952    ImGui::PopFont();953    return changed;954}955 956inline bool InputBindable(bindable<dimension_t>* val, int flags, UIContext& ctx)957{958    if (val == ctx.setProp)959    {960        //commit dialog request961        ctx.setProp = nullptr;962        if (ctx.setPropValue == "")963            *val = 0;964        else965            *val->access() = ctx.setPropValue;966        return true;967    }968 969    std::string id = "##" + std::to_string((uint64_t)val);970    std::string butId = ICON_FA_LEFT_RIGHT + id;971    if (flags & InputBindable_StretchButton)972        ImGui::SetNextItemWidth(ImGui::CalcItemWidth() - ImGui::GetFrameHeight());973 974    bool stretch = val->stretched();975    ImGui::PushFont(!ImRad::IsCurrentItemDisabled() && (flags & InputBindable_Modified) ?976        ctx.pgbFont : ctx.pgFont);977    int fl = ImGuiInputTextFlags_CallbackCharFilter;978    if (val->has_value())979        fl |= ImGuiInputTextFlags_AutoSelectAll;980    bool changed = ImGui::InputText(id.c_str(), val->access(), fl, DefaultCharFilter);981    /*std::string tmp = *val->access();982    bool active = ImGui::GetFocusID() == ImGui::GetID(id.c_str()) ||983        ImGui::GetActiveID() == ImGui::GetID(id.c_str());984    if (!active)985        tmp = val->to_arg("");986    bool changed = ImGui::InputText(id.c_str(), &tmp, fl, DefaultCharFilter);987    if (changed) {988        if (stretch && tmp.size() && tmp.back() == 'x')989            val->set_from_arg(tmp);990        else991            *val->access() = tmp;992    }*/993    ImGui::PopFont();994 995    //disallow empty state996    if (ImGui::IsItemDeactivatedAfterEdit())997    {998        if (!stretch && val->empty())999            *val = 0;1000        else if (stretch && !val->has_value()) {1001            *val = 1.0f;1002            val->stretch(true);1003        }1004    }1005 1006    if (flags & InputBindable_StretchButton)1007    {1008        ImGui::SameLine(0, 0);1009        if (IsHighlighted(id) || IsHighlighted(butId))1010        {1011            ImGui::PushFont(ImGui::GetDefaultFont());1012            ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[stretch ? ImGuiCol_ButtonActive : ImGuiCol_Button]);1013            ImGui::BeginDisabled((flags & InputBindable_StretchButtonDisabled) == InputBindable_StretchButtonDisabled);1014            if (ImGui::Button(butId.c_str(), { ImGui::GetFrameHeight(), ImGui::GetFrameHeight() }))1015            {1016                changed = true;1017                stretch = !stretch;1018                *val = stretch ? 1.0f : 0.f;1019                val->stretch(stretch);1020            };1021            ImGui::EndDisabled();1022            ImGui::PopStyleColor();1023            ImGui::PopFont();1024        }1025        else1026        {1027            ImGui::InvisibleButton(butId.c_str(), { ImGui::GetFrameHeight(), ImGui::GetFrameHeight() });1028        }1029    }1030 1031    return changed;1032}1033 1034template <class T>1035inline bool InputFieldRef(field_ref<T>* val, const std::string& type, bool allowEmpty, UIContext& ctx)1036{1037    if (val == ctx.setProp)1038    {1039        //commit dialog request1040        ctx.setProp = nullptr;1041        *val->access() = ctx.setPropValue;1042        return true;1043    }1044 1045    bool changed = false;1046    std::string id = "##" + std::to_string((uint64_t)val);1047    ImGui::PushFont(ctx.pgbFont);1048    if (ImGui::BeginCombo(id.c_str(), val->c_str(),1049        !ImRad::IsCurrentItemDisabled() && IsHighlighted(id) ? 0 : ImGuiComboFlags_NoArrowButton))1050    {1051        ImGui::PopFont();1052        ImGui::PushFont(ImGui::GetFont());1053 1054        ImGui::PushStyleColor(ImGuiCol_Text, NONE_COLOR);1055        if (allowEmpty && ImGui::Selectable("None"))1056        {1057            *val->access() = "";1058            changed = true;1059        }1060        ImGui::PopStyleColor();1061 1062        ImGui::PushStyleColor(ImGuiCol_Text, RENAME_COLOR);1063        if (val->has_single_variable() && ImGui::Selectable("Rename..."))1064        {1065            auto vars = val->used_variables();1066            assert(vars.size() == 1);1067            newFieldPopup.codeGen = ctx.codeGen;1068            newFieldPopup.varOldName = vars[0];1069            newFieldPopup.mode = NewFieldPopup::RenameField;1070            newFieldPopup.OpenPopup([val, root=ctx.root] {1071                root->RenameFieldVars(newFieldPopup.varOldName, newFieldPopup.varName);1072                });1073        }1074        ImGui::PopStyleColor();1075 1076        ImGui::PushStyleColor(ImGuiCol_Text, NEW_COLOR);1077        if (ImGui::Selectable("New Variable..."))1078        {1079            newFieldPopup.varType = type;1080            newFieldPopup.codeGen = ctx.codeGen;1081            newFieldPopup.mode = NewFieldPopup::NewField;1082            newFieldPopup.OpenPopup([&ctx, val] {1083                ctx.setProp = val;1084                ctx.setPropValue = newFieldPopup.varName;1085                });1086        }1087        ImGui::PopStyleColor();1088 1089        ImGui::Separator();1090        auto vars = ctx.codeGen->GetVarExprs(type, true, ctx.GetCurrentArray());1091        for (const auto& v : vars)1092        {1093            if (ImGui::Selectable(v.first.c_str(), v.first == val->c_str()))1094            {1095                *val->access() = v.first;1096                changed = true;1097            }1098        }1099 1100        ImGui::EndCombo();1101    }1102    ImGui::PopFont();1103    return changed;1104}1105 1106template <class T>1107inline bool InputFieldRef(field_ref<T>* val, bool allowEmpty, UIContext& ctx)1108{1109    std::string type = typeid_name<T>();1110    return InputFieldRef(val, type, allowEmpty, ctx);1111}1112 1113template <>1114inline bool InputFieldRef(field_ref<void>* val, bool allowEmpty, UIContext& ctx) = delete;1115 1116 1117inline bool InputDataSize(bindable<int>* val, bool allowEmpty, UIContext& ctx)1118{1119    if (val == ctx.setProp)1120    {1121        //commit dialog request1122        ctx.setProp = nullptr;1123        *val->access() = ctx.setPropValue;1124        return true;1125    }1126 1127    bool changed = false;1128    std::string id = "##" + std::to_string((uint64_t)val);1129    ImGui::PushFont(ctx.pgbFont);1130 1131    if (ImGui::BeginCombo(id.c_str(), val->c_str(),1132            IsHighlighted(id) ? 0 : ImGuiComboFlags_NoArrowButton))1133    {1134        ImGui::PopFont();1135        ImGui::PushFont(ImGui::GetFont());1136 1137        ImGui::PushStyleColor(ImGuiCol_Text, NONE_COLOR);1138        if (allowEmpty && ImGui::Selectable("None"))1139        {1140            *val->access() = "";1141            changed = true;1142        }1143        ImGui::PopStyleColor();1144 1145        /* it's confusing to offer new variable here. User can still do it from BindingButton1146        ImGui::PushStyleColor(ImGuiCol_Text, NEW_COLOR);1147        if (ImGui::Selectable("New Variable..."))1148        {1149            newFieldPopup.varType = ""; //allow to create std::vector etc.1150            newFieldPopup.codeGen = ctx.codeGen;1151            newFieldPopup.mode = NewFieldPopup::NewField;1152            newFieldPopup.OpenPopup([&ctx, val] {1153                ctx.setProp = val;1154                if (cpp::is_std_container(newFieldPopup.varType))1155                    ctx.setPropValue = newFieldPopup.varName + ".size()";1156                else1157                    ctx.setPropValue = newFieldPopup.varName;1158                });1159        }1160        ImGui::PopStyleColor();1161        */1162 1163        ImGui::Separator();1164        const auto& vars = ctx.codeGen->GetVarExprs("int", false);1165        for (const auto& v : vars)1166        {1167            if (ImGui::Selectable(v.first.c_str(), v.first == val->c_str()))1168            {1169                *val->access() = v.first;1170                changed = true;1171            }1172        }1173 1174        ImGui::EndCombo();1175    }1176    ImGui::PopFont();1177    return changed;1178}1179 1180template <class FuncSig>1181inline bool InputEvent(const std::string& name, event<FuncSig>* val, int flags, UIContext& ctx)1182{1183    if (val == ctx.setProp)1184    {1185        //commit dialog request1186        ctx.setProp = nullptr;1187        *val->access() = ctx.setPropValue;1188        return true;1189    }1190 1191    bool changed = false;1192    std::string type = typeid_name<FuncSig>();1193    std::string id = "##" + std::to_string((uint64_t)val);1194    std::string inputId = id + "Input";1195    bool buttonVisible = !ImRad::IsCurrentItemDisabled() && (IsHighlighted(inputId) || IsHighlighted(id));1196    float width = ImGui::CalcItemWidth();1197    if (buttonVisible)1198        width -= ImGui::GetFrameHeight();1199    float realWidth = ImGui::CalcItemSize({ width, 0 }, 0, 0).x;1200    ImGui::SetNextItemWidth(width);

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