Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Input widgets with different IDs conflict with each other? #78

Closed
FaresX opened this issue Jan 7, 2023 · 6 comments
Closed

Input widgets with different IDs conflict with each other? #78

FaresX opened this issue Jan 7, 2023 · 6 comments
Labels
question Further information is requested

Comments

@FaresX
Copy link

FaresX commented Jan 7, 2023

屏幕截图_20230107_131500

As the picture shows, when I input 1 in the first InputText Widget, any other Input Widgets will be filled with the same contents, though I have used different IDs. Here is some of the codes:
function edit(insbuf::InstrBuffer, addr)
    for qt in insbuf.quantities
        edit(qt, insbuf.instrnm, addr)
    end
end

function edit(qt::InstrQuantity, instrnm, addr, ::Val{:set})
    id = string(instrnm, "-", addr, "-", qt.name)
    ftsz = CImGui.GetFontSize()
    CImGui.Text(qt.alias)
    CImGui.SameLine(ftsz*(maxaliaslist[instrnm]/3+0.5))
    CImGui.Text(""); CImGui.SameLine() ###alias
    Us = conf["U"][qt.utype]
    U = isempty(Us) ? "" : Us[qt.uindex]
    CImGui.PushStyleVar(CImGui.ImGuiStyleVar_ItemSpacing, (0, 2))
    width = (CImGui.GetContentRegionAvailWidth()-6ftsz)/2
    CImGui.PushItemWidth(width)
    CImGui.InputTextWithHint("##设置$id", "设置值", qt.set, length(qt.set))
    CImGui.PopItemWidth()
    CImGui.SameLine() ###设置值
    valstr = qt.read
    val = U == "" ? valstr : @trypass string(parse(Float64, valstr)/ustrip(upreferred(U), 1U)) valstr
    CImGui.PushFont(secondft)
    CImGui.Button(string(val, "##$id"), (width, Float32(0)))
    CImGui.PopFont()
    CImGui.SameLine() ###实际值
    CImGui.PushItemWidth(3ftsz)
    @c showunit("##insbuf$id", qt.utype, &qt.uindex)
    CImGui.PopItemWidth()
    CImGui.PopStyleVar()
    CImGui.SameLine() ###单位
    CImGui.PushStyleVar(CImGui.ImGuiStyleVar_FrameRounding, 6)
    if CImGui.Button(" 确认 ##$id")
        if addr != ""
            svstr = replace(qt.set, r"\0.*"=>"")
            sv = U == "" ? svstr : @trypass string(eval(Meta.parse(sv)))*ustrip(upreferred(U), 1U) svstr
            instr = INSTR(instrnm, addr)
            setfunc = Symbol(instrnm, :_, qt.name, :_set)
            getfunc = Symbol(instrnm, :_, qt.name, :_get)
            lockstates() do
                @trylink_do instr (eval(:($setfunc($instr, $sv))); qt.read = eval(:($getfunc($instr)))) nothing
            end
        end
    end
    CImGui.PopStyleVar()
end
@Gnimuc
Copy link
Owner

Gnimuc commented Jan 7, 2023

You could use PushID() / PopID().

@FaresX
Copy link
Author

FaresX commented Jan 7, 2023

function edit(insbuf::InstrBuffer, addr)
    for qt in insbuf.quantities
        CImGui.PushID(qt.name)
        edit(qt, insbuf.instrnm, addr)
        CImGui.PopID()
    end
end
isvalidaddr = selectaddr in append!(collect.(keys.(values(instrbuffer)))...)
selectaddr = isvalidaddr ? selectaddr : ""
selectins in keys(default_insbufs) || push!(default_insbufs, selectins=>InstrBuffer(selectins))
insbuf = selectaddr == "" ? default_insbufs[selectins] : instrbuffer[selectins][selectaddr]
CImGui.PushID(string(selectins, selectaddr))
edit(insbuf, selectaddr)
CImGui.PopID()

image
I have tried it. There exists the same problem and I think it is not because of the IDs. When I do not select any addresses, there is no problem. Here, "instrbuffer" is a global variable in my module, and "default_insbufs" is a local variable inside a let block.

@Gnimuc
Copy link
Owner

Gnimuc commented Jan 7, 2023

Please submit an MWE, I'm not responsible for debugging your incomplete code with such limited info.

@Gnimuc Gnimuc added the question Further information is requested label Jan 7, 2023
@FaresX
Copy link
Author

FaresX commented Jan 8, 2023

I have fixed this issue, but I am not clear about the reason. According to your suggestion, I wrote the sample code below. When I follow the workflow that generates data remotely and fetches back, the problem will be reproduced. However, when all things happen locally, there will be no problem.

module Example

using CImGui
using CImGui.CSyntax
using CImGui.CSyntax.CStatic
using CImGui.GLFWBackend
using CImGui.OpenGLBackend
using CImGui.GLFWBackend.GLFW
using CImGui.OpenGLBackend.ModernGL
using CImGui.LibCImGui
using Distributed

function ui()
    glsl_version = 130
    GLFW.WindowHint(GLFW.CONTEXT_VERSION_MAJOR, 3)
    GLFW.WindowHint(GLFW.CONTEXT_VERSION_MINOR, 0)
    error_callback(err::GLFW.GLFWError) = @error "GLFW ERROR: code $(err.code) msg: $(err.description)"

    # setup GLFW error callback
    GLFW.SetErrorCallback(error_callback)
    # create window
    window = GLFW.CreateWindow(1920, 1080, "Example")
    @assert window != C_NULL
    GLFW.MakeContextCurrent(window)
    GLFW.SwapInterval(1)  # enable vsync

    # setup Dear ImGui context
    ctx = CImGui.CreateContext()
    # setup Dear ImGui style
    CImGui.StyleColorsDark()

    # setup Platform/Renderer bindings
    ImGui_ImplGlfw_InitForOpenGL(window, true)
    ImGui_ImplOpenGL3_Init(glsl_version)

    @async try
        p_open = true
        while !GLFW.WindowShouldClose(window)
            GLFW.PollEvents()
            ImGui_ImplOpenGL3_NewFrame()
            ImGui_ImplGlfw_NewFrame()
            CImGui.NewFrame()

            p_open && @c showexample(&p_open)

            CImGui.Render()
            GLFW.MakeContextCurrent(window)
            display_w, display_h = GLFW.GetFramebufferSize(window)
            glViewport(0, 0, display_w, display_h)
            glClearColor(0.2, 0.2, 0.2, 1) 
            glClear(GL_COLOR_BUFFER_BIT)
            ImGui_ImplOpenGL3_RenderDrawData(CImGui.GetDrawData())

            GLFW.MakeContextCurrent(window)
            GLFW.SwapBuffers(window)
            yield()
        end
    catch e
        @error "Error in renderloop!" exception=e
        Base.show_backtrace(stderr, catch_backtrace())
    finally
        ImGui_ImplOpenGL3_Shutdown()
        ImGui_ImplGlfw_Shutdown()
        CImGui.DestroyContext(ctx)
        GLFW.DestroyWindow(window)
    end
end

function showexample(p_open::Ref)
    CImGui.SetNextWindowPos((600, 100), CImGui.ImGuiCond_Once)
    CImGui.SetNextWindowSize((1000, 800), CImGui.ImGuiCond_Once)
    if CImGui.Begin("Example", p_open)
        CImGui.Button("Add Test") && (add_remote(); add_local())
        # CImGui.Button("Add Test") && push!(testlist, Test())
        for (i, test) in enumerate(testlist)
            CImGui.PushID(i)
            edit(test)
            CImGui.PopID()
        end
        CImGui.End()
    end
end

mutable struct Test
    input1
    input2
end

Test() = Test("\0"^16, "\0"^16)

function edit(t::Test)
    CImGui.InputTextWithHint("Input1", "Input1", t.input1, length(t.input1)); CImGui.SameLine()
    CImGui.InputTextWithHint("Input2", "Input2", t.input2, length(t.input2))
end

testlist = []

function add_remote()
    remotecall_wait(workers()[1]) do 
        push!(testlist, Test())     
    end
end

function add_local()
    testlist_remote = remotecall_fetch(()->testlist, workers()[1]) |> deepcopy
    global testlist = testlist_remote
end

end # Example

Example.ui()

@FaresX
Copy link
Author

FaresX commented Jan 8, 2023

Just a little while ago, I found that the problem is the using of deepcopy instead of remote_do.

@JamesWrigley
Copy link
Collaborator

I'm gonna close this since it looks like the problem is solved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants