Page 1 of 1

Text filter in editbox

Posted: Sun May 20, 2007 13:29
by Pompei2
Hi guys,

Can I somehow restrict an editbox to accept only numbers ? I mean like the one from the spinner ? How does the spinner do this ?

Posted: Sun May 20, 2007 15:21
by Rackle
From CEGUISpinner.cpp:

Code: Select all

    void Spinner::onValueChanged(WindowEventArgs& e)
    {
        Editbox* editbox = getEditbox();

        // mute to save doing unnecessary events work.
        bool wasMuted = editbox->isMuted();
        editbox->setMutedState(true);

        // Update text with new value.
        // (allow empty and '-' cases to equal 0 with no text change required)
        if (!(d_currentValue == 0 &&
              (editbox->getText().empty() || editbox->getText() == "-")))
        {
            editbox->setText(getTextFromValue());
        }
        // restore previous mute state.
        editbox->setMutedState(wasMuted);

        fireEvent(EventValueChanged, e, EventNamespace);
    }

    String Spinner::getTextFromValue(void) const
    {
        std::stringstream tmp;

        switch (d_inputMode)
        {
        case FloatingPoint:
            tmp << d_currentValue;
            break;
        case Integer:
            tmp << static_cast<int>(d_currentValue);
            break;
        case Hexadecimal:
            tmp << std::hex << std::uppercase << static_cast<int>(d_currentValue);
            break;
        case Octal:
            tmp << std::oct << static_cast<int>(d_currentValue);
            break;
        default:
            throw InvalidRequestException("Spinner::getValueFromText - An unknown TextInputMode was encountered.");
        }

        return String(tmp.str());
    }


That's the simple case, where you can input numbers. However it's be fun to have formatted input, something like: ">>>,>>9.99" to input a decimal number. Or inputting a credit card number: "999 999 999 999" (I think that's the format).

Have a look at Formatted_Numeric_Data, at the ICU::formatText function. It may be useful.

Posted: Sun May 20, 2007 20:56
by Pompei2
Oh thank you, I was hoping it's possible to do this w/o code :) As I just use my inut to get an ICQ number, i think ICU is overkill, but you had a good idea, I'll try it to make the text look like "xxx-xxx-xxx" :) shouldn't be too hard.

Posted: Tue May 22, 2007 08:56
by Rackle
ICU is great to display test in various locales. Most people (and by most I mean the people near where _I_ live) use the comma to separate thousands and a period to separate decimals: 123,456.78. However I wonder if most (and by that I mean the actual meaning of the word, the greatest amount of) people do not instead use the period to separate thousands and a comma to separate decimals: 123.456,78.

By limiting an application to a particular type of data (numeric, date) we alianate those people that do not use the same locale as us. Concretely that translates to lost sales, lost revenues. With my version of ICU I showed that it wasn't too difficult to present values in a locale-independant manner within Cegui. However I have only done the easy part; the display of data. The input of formatted data is more difficult. But once you have it working for one locale of data then it shouldn't be too difficult to make it work for other locales.

I recommend at least using IBM's ICU formatting rules, so that should anyone wish to use ICU to easily retrieve a localised format string, it could plug in easily into your solution.

Posted: Tue May 22, 2007 09:01
by Rackle
I'm not sure how to actually implement this feature but this idea may provide a research direction.

Trick the user. Yup, fool him/her into believing that the EditBox contains a mask when in fact it does not.

Let's say my mask is "999 999" and I type "123". On the "text changed" event I retrieve the typed value and determine that a space should be inserted. So I mute the "text changed" event, retrieve the current text, add a space, set that as the new text and unmute the "text changed" event, and make sure the cursor is after the space.

That's one approach. Hopefully it isn't too bad, or you can find a better one. I wonder how the big boys (MFC, .Net, Java) actually implement this feature.

Posted: Tue May 22, 2007 11:33
by lindquist
I believe the Editbox::setValidationString member can solve you problem. It takes a perl compatible regular expression and rejects input if the result would not pass the regex.

to restrict the user to '123 456 789' type strings you could use something like this: (written as a C string literal)

Code: Select all

"\\d{0,3} ?\\d{0,3} ?\\d{0,3}"

this will still allow entering just 2 spaces, but my regex is somewhat rusty and I'm not sure how to work around this.

it's important that the regex will match all possible inputs and not just the final result. fx:

Code: Select all

"\\d{3} \\d{3} \\d{3}"

would make it impossible to enter anything into a empty box as one char would never match.

Hope it gives some ideas.

Posted: Tue May 22, 2007 20:43
by Pompei2
Yeah, I don#t know much about regex. I tried this member by setting the property just to "a" and hoping this would allow only an "a" to be enterd ... didn't seem to work :) I go try your regexp and I'll tell you.


Edit: Great ! it actually works very good :) thank you for your regexp !

And btw ... setting the regexp to just "a" DOES work ! I just tried it and it worked.

I was thinking of an approach like rackle, but now ... no more need ! That's what i call a powerful GUI :)