MakieOrg / Makie.jl

Interactive data visualizations and plotting in Julia
https://docs.makie.org/stable
MIT License
2.38k stars 302 forks source link

Textbox set! fails #3069

Open steveransome opened 1 year ago

steveransome commented 1 year ago

When using set! to modify the text in a Textbox after the user has made a change cause an error depending on the number of chars added and cursor position. Very closely related to issue 2037

ERROR: MethodError: Cannot `convert` an object of type Nothing to an object of type Vector{Point{2, Float32}}

Can be reproduced with this code ...

using GLMakie
fig = Figure(resolution=(500, 500));display(fig)
atextbox =  Textbox(fig)
Makie.set!(atextbox,"a string1")
# set focus on a textbox and add n chars
# do or don't press enter (both reproduce the error)
# setting cursor position less than n chars from the end of the string
# is the only way to reproduce the issue
Makie.set!(atextbox,"a string2")
ederag commented 1 year ago

The issue is that when the text shrinks, the cursor must be set at a valid position prior to updating the text.

Here is the workaround I just gave on discourse:

function custom_set!(tbox::Makie.Textbox, new_text)
    old_text = tbox.displayed_string[]
    old_pos = tbox.cursorindex[]
    if length(new_text) == 0
        # for now setting new_text to "" errors
        # TODO: is resetting the correct thing to do ?
        Makie.reset!(tbox)
    elseif length(new_text) == length(old_text)
        # no length change, cursor is already at the correct position
        Makie.set!(tbox, new_text)
    elseif length(new_text) > length(old_text)
        if old_pos == length(old_text)
            # Let's keep the cursor at the end.
            # Need to add the new text first,
            # to make the new cursor position valid.
            Makie.set!(tbox, new_text)
            tbox.cursorindex[] = length(new_text)
        else
            # cursor was inside the text; keep cursor position
            Makie.set!(tbox, new_text)
        end
    else
        # new text is shorter
        # place the cursor at a future valid position first (not outside new_text)
        tbox.cursorindex[] = min(old_pos, length(new_text))
        Makie.set!(tbox, new_text)
    end
end