From: pf@bilbo.bio.purdue.edu (Paul Furbacher)
Subject: Re: modifying TInputLine to handle integers/ reals etc..need help
Followup-To: comp.lang.c++
Organization: Purdue University
Date: Mon, 11 Jan 1993 04:00:08 GMT

In article <C0ntu3.22I@athena.cs.uga.edu>, 
  ravi@athena.cs.uga.edu (Ravi Vemuri) wrote:
> 
> I am having prbs creating a TInputLine object to handle integers. I overrode
> the setdata and getdata functions by incorporating function calls for
> string to integer conversion and viceversa. However, there are a few prbs
> I could'nt overcome(and hence, works only partly!):
> 1. my object does not respond to <Enter> key like the parent object does.

This means that you overrode the HandleEvent() method too.  If your
descendent has lost the ability to trap the kbEnter event, then
look to see that you are first trapping the special keycodes,
e.g., non-numeric for integer, and then pass on the event to 
the ancestor's HandleEvent() method (member function in c++).

You can also add validation upon loss of focus caused by 
kbTab and kbShiftTab by adding a trap in the HandleEvent for 
those two events --
   if (Event.what = evKeydown) and 
      ((Event.KeyCode = kbTab) or (Event.KeyCode = kbShiftTab)) then
   begin
     if not Descendent.Valid(command) then 
     begin
       Select;
       ClearEvent(Event);
     end;
   end;  

(Sorry, I'm up to my ears these days in Pascal, but it's very 
much like pseudo-code.)

Then you could trap for the "." and clear it, if you wished.
Finally, you should call the ancestor's HandleEvent() and 
let it handle all the other more mundane stuff.

> 2. I didnot override datasize(), but i think i should. however, the manual
> does state that the simple str to int and int to str conversions should
> suffice.

What function does the DataSize function perform?  It is called
by a TDialog instance when the dialog box is performing its 
SetData/GetData operation on all the subviews.  As it tracks
through the subview list in z-order, it asks "what's your datasize?",
the subview says "string10" or "longint" or "char", etc., and
the the owning group (the dialog box) either takes or gives that
many bytes to the subview.  If you've ever gotten the number of
bytes wrong in the structure you passed into the Set/GetData()
call, you know you got something weird.  The reason is that
as the owning group parcels out the bytes, it isn't smart enough
that you got things in the wrong order or gave it too many or
too few bytes to parcel out. So if you're going to alter what
you want the owning dialog box to pass to or take from your 
TIntegerLine instance, you'll have to alter the value 
which TIntegerLine.DataSize returns.

DataSize for the ancestor TInputLine reflects the length of 
the string passed in, at least in the Pascal version of TV.
With an integer (longint) inputline you would change this
to longint *if* you create descendent SetData() and GetData()
methods which convert the integer into and back from the 
string which is handled by the HandleEvent() (which is essentially
a string handling and building routine).  So, in this scheme,
GetData would take the string in the *Data field, convert it
to a longint (because DataSize = sizeof(longint)), and SetData
would take the integer (or longint) given to it and convert
it into a string to assign to *Data. 

The Pascal code looks like this.

function TIntegerLine.DataSize: word;
begin
  DataSize := sizeof(longint);
end;

procedure TIntegerLine.GetData(var Rec);
var
  Code : integer;
begin
  Val(Data^, longint(Rec), Code); 
end;

procedure TIntegerLine.SetData(var Rec);
begin
  Str(longint(Rec),Data^);
  SelectAll(True); // highlights the whole input line 
end; 

Make sense? You'll have to make some language and version 
translations no doubt, but if you look it over, it should become
clear.

Lastly, and not least importantly, you will have to create
a descendent Valid() function which will validate whether the
user has entered a correct number. You don't want "4pq8" to pass
as a valid integer!  And you'll want to perhaps limit the 
range of the value in many cases, so include range-checking in the
Valid() method as well.  If the string doesn't convert
to a valid number or exceeds the range, let the user know 
with a message dialog.  And return the focus to the input 
line with SelectAll(true).

Have fun.  Go lightly on this project -- do just enough to 
get by, because the next version of TV will most likely have 
a whole bunch of inputline validation built into it, if 
the version 2 release of TV/Pascal is an indication.  

The documentation is much better in version 2, as well. You 
can't wait can you.

PF
Newsgroups: comp.lang.c++,comp.lang.eiffel