TextPropertyComponent with only integers?

Is there a way to make the TextPropertyComponent to handle only integers?

The getText/setText override seems a dead end.

If the TextPropertyComponent would expose the TextEditor there was the chance to use the InputFilter.

I think that would be the preferred way.

1 Like

Good idea, but sadly AFAIK everything is kept private in TextPropertyComponent.
The narrow interface makes it hard for subclasses to change the behaviour.
(Or there is something obvious i can not see).
I thought to put a CachedValue<int> somewhere but without any success. :thinking:

If you’re overriding setText() in a custom TextPropertyComponent, could you just do some checks that the text only contains characters 0-9?

void setText (const juce::String& text) override
{
    jassert(text.containsOnly ("0123456789");

    const auto intValue = text.getIntValue();
}
1 Like

The non destructive way is to inherit the TextPropertyComponent and add your InputFilter in the virtual createTextEditor command:

class MyTextPropertyComponent : public juce::TextPropertyComponent
{
    class NumberFilter : public juce::TextEditor::InputFilter
    {
    public:
        NumberFilter() = default;
        juce::String filterNewText (juce::TextEditor &, const juce::String &newInput)
        {
            // do your filter here
        }
    };

    juce::TextEditor* createEditorComponent() override
    {
        auto* ed = juce::TextPropertyComponent::createEditorComponent();
        ed->setInputFilter (new NumberFilter(), true);
        return ed;
    }
};

Hope that helps

2 Likes

@ImJimmi

After scratching my head one hour more i see how to do that now.
I need to override both getText/setText methods.
Not so hard but not easy (intuitive) to understand the trick at first.
I’ll post the result later.

@daniel

Thanks, i’ll try it and see if it is better that the last minute idea i get. :grinning_face_with_smiling_eyes:

Never mind, it doesn’t work. I looked at the wrong class, i.e. the wrapped TextPropertyComponent::LabelComp. We have no access to that, so it is impossible without the juce team allowing to access the editor.

Something like this would be needed:

juce::TextEditor* TextPropertyComponent::getTextEditor();

And even that has the problem that the textEditor in the TextPropertyComponent is in fact derrived from juce::Label. That means the TextEditor we want to modify is only created once clicked on the Label.

Options (for the juce authors)
a) the InputFilter could be set on the Label and the label could be accessed with a getter
b) the InputFilter could be set on the TextPropertyComponent (awkward)
c) add a Callback to override:

TextPropertyComponent::editingStarted (juce::TextEditor& editor) override
{
    editor.setInputFilter (new MyInputFilter(), true);
}
1 Like

Something like that seems to work roughly (old value could be cached to avoid to set to zero when bad entry is catched). One problem is that the var into the ValueTree attached seems to be set twice. Once with the wrong value, and just after with the good one. It could be a problem.

public:
    juce::String getText() const override
    {
        return parsed (TextPropertyComponent::getText());
    }
        
    void setText (const juce::String& s) override
    {
        TextPropertyComponent::setText (parsed (s));
    }

private:
    juce::String parsed (const juce::String& s) const
    {
        return juce::String (s.getIntValue());
    }

If you need to preserve leading zeroes (so that “001” does not become “1”), String::retainCharacters ("0123456789") might be a better option than String::getIntValue().

1 Like