Constrained text entry



Hi, a couple of months ago I was developing a prototype app in GTK and encountered the problem below.  At the time I painstakingly
searched the list archive for an answer.  I remember one month had 4 separate top level threads which basically boiled down to how
to do one general thing, and none were answered.  At that point I just laughed and decided that the prototype code didn't have to
be perfect.  But now I am thinking about doing a production quality GTK app, and I need to know if this is possible.

The problem is very simple and common: I want to have a constrained GtkEntry widget, suppose one which only holds a floating point
double.  So obviously you just catch the signal that lets the value change, and if it parses in your favorite ascii->number
function, you are all set.  If it doesn't, you need to set the entry box back to what it was before so the user can see that it
didn't work.

Problem: GtkEntry provides apparently only two signals for changing.  "changed" catches every change.  I insert an "a" into the
number and I immediately get called.  That's not the right behavior because you can't always enforce the structure correctly that
way.  Perhaps you wonder, "But if you want a number in the box, why would you allow a letter to be entered?"  One counterexample is
that a floating point number in string form can standardly contain the character "e", yet simply allowing only numbers and "e" in
the text still allows plenty of awful junk.  "1eee7ee7e" for example.  Likewise "-" and "." characters.

The other signal provided is "activate" which gets called if the user puts in text and hits enter.  But in that case, the user
needs to hit enter to see that what he did is invalid.  He could presumably go on using his app for 5 minutes not realizing that he
put 2 decimal points in his number, still displayed on screen but not refleted by the program running.

There are some focus events which one can utilize, for example "focus-out-event" which belongs to GtkWidget.  IIRC these still
don't yeild the correct behavior, either necessary or sufficient.  I cannot be more specific as the test cases that I wrote were
done for a company whose code base I no longer have access to.

What is the correct behavior?  It's a bit tricky.  I can think of at least three distinct cases.

	1) nonmodal entry on a toplevel window
		Example: the zoom percent box in the toolbar of MS Office 97
	2) entry in modal dialog box
		Example: "column width" command in MS Excel 97
	3) nonmodal entry in app with multiple top level windows
		Example: the prototype tool that I was developing before.  It
		had an OpenInventor browsing window (based on Motif), and GTK
		control panel that had number entries for tweaking parameters
		of the graphic.

1) Any text is allowed to be typed so long as the application's focus remains in the entry and the system focus remains on the
application.  If the user clicks/tabs away, switches apps or virtual desktops, the program must reclaim the focus, set the entry
back to its original string, and place the focus on the fully selected string (not with a caret at an insertion point- just as if I
freshly tabbed into this box so that I can overtype it if I choose).

This is the behavior of Office 97, and IMHO the "right thing" (or at least a very sensible default) irrespective of platform or
application.

2) Suppose the dialog has an "OK" and a "Cancel" button.  Unless this is a complex dialog box requiring interrelationships between
multiple numbers to be satisfied, the entry should allow any text until pressing "OK" or "Cancel".  (If you do have aforementioned
relationships, behavior might be better designed as in 1). )  If the user clicks "OK", the text is parsed.  On any failure, a modal
message box tells the user that a certain entry is malformed and leaves the dialog up.  Focus reverts to the entry which violated
the test.  If multiple violations occur, only one need be mentioned and everything will work out.  If the user clicks "Cancel",
then all entries must be discarded and no parsing should take place.  On the next appearance of the dialog box, the values should
be reset.

This is the behavior of the "column width" command in MS Excel 97.

3)  This is the same as 1) only you have to also catch focus switches between different toplevel windows of the same application,
even if they are made with different toolkits or whatever.  This may or may not be for free depending on the way you are catching
your X events/GTK signals/whatever.  On the other hand, even incorporating together the event loops of GTK and Motif/Inventor was a
real pain, so I can imagine there being some bad interaction here that would prevent ever getting the behavior right.

A general consideration: it is not necessarily acceptable to check the data too frequently.  Suppose the validity of a text entry
is determined as a function of a slow network request, or just has high computational cost (say 1 second of full CPU).  Then you
can't go checking it every time the focus changes or something dumb like that.

A general disclaimer: I did not verify any of these behaviors against a mainstream Macintosh application.

Whatever the "right" answer to this is, this problem is so common that it needs to be documented as a GTK example somewhere.  (In
the tutorial?)  If the behavior is not possible with the API, the API needs to add a signal or whatever.  Issues such as these are
subtle and not probably sought after by impatient free software developers for whom command line interface is a "good" UI
regardless of application type.  That does not justify wasting development effort on making bad software.  Projects such as GNOME
are doomed to never hit mainstream if things so basic as this (to a mainstream user) are not uniformly practiced.  (Ok, usability
ranting over.)

I am optimally hoping somebody has already solved exactly this thing, which would prevent me from having to reproduce the best
approximation of this that I could construct, and sending it to the list to see if somebody can improve it.  But I will write those
test cases should the replys or lack thereof on the list indicate that this is necessary.

Thanks,


Jeff Henrikson  (not on gtk-list, please cc)







[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]