From: pf@bilbo.bio.purdue.edu (Paul Furbacher)
Newsgroups: comp.lang.pascal
Subject: Re: TV Help with ListViewers
Date: 5 Oct 92 06:31:05 GMT
Distribution: comp.lang.pascal
Organization: Purdue University

In article <1992Oct3.214144.22386@a.cs.okstate.edu>, 
   greaham@a.cs.okstate.edu (GREAHAM DARIN DONA) wrote:

>     I have a program that within it's many parts contain a collection of 
> six items.  

Actually, you have an undetermined number of items, each of which has
six "fields" or "sub-items" per item. Each item is composed of either an
object instance, or a record, of six fields.  Since you say that you 
have successfully streamed the collection, each item is probably an 
instance of a 6-field object, no?

>     Now the problem.  After loading the file, I want to put the contents
> into a ListViewer (with both horizontal and vertical scrollbars) but can't
> figure out how to do this.  A ListBox really won't do my any good since
> the six items in the collection will most likely be longer horizontally
> than the listbox will allow.

Since you want to scroll horizontally within the same column, the 
horizontal scrollbar of TListBox instance will not serve your purpose.
The behavior of the horizontal scrollbar is defined in TListViewer, and
is for scrolling between columns when "ANumCols" > 1 (File|Open and 
File|Save dialogs present file lists in this manner).  See below for 
some suggestions for solving your problem.  

> 
>     The six items in question are strings and the collection is a normal
> collection for now.  

Since the "fields" are strings, it might serve you better to
declare the collection as an instance of PStringCollection.  
Using the abstract methods of TCollection can get you into 
trouble.

> I've got the ListViewer inserted into a dialog box
> with both scrollbars present, the only problem I have is getting the data
> from the collection inserted in the ListViewer, 

Try the "NewList()" method provided in TListBox.  You can use
the "SetData()" method of the dialog box, but then you'll have
to define a special record for the setdata/getdata calls.
It seems to me a more direct and more conscious programming 
practice to insert the list just after creating the instance 
of the listbox, rather than at some point later using the 
SetData() method.  It's a matter of programming style preference.

> and Borland's TV Guide 
> doesn't do much for explaining how to manage this.

Ah, but printing out files which you have "grepped" for 
methods related to collections will provide you tons of
examples.  There's a wealth of info in those TVISION and
TVDEMOS directories: don't go to bed at night without 
some of them as good bedtime stories.

>     Here is a quick pic of what I'm after:

For clarity, I've altered your "pic" (good thing I'm doing
this on a Mac with a good newsreader!).

>  ------------------------------------------------------
>  |                                                    |
>  | =======================================            |
>  | = 1field1,1field2,1field3,1field4,1field5,1field6 =|
>  | = 2field1,2field2,2field3,2field4,2field5,2field6 =|
>  | = "                                           "   =|
> 

You haven't provided any convincing or compelling reasons as 
to why all fields of an item need to be displayed.  Can't the
user make a decision based on "field1"?

There are two ways to solve this: 1) create a descendent of
TListBox which scrolls within the column (could be a bit of work), 
or 2) use a combination of existing TV objects to work around the
problem.  

1)  A quick sketch of the work you'll have to do, as I see it (someone
else hopefully will see a way which I've missed).  The over-ridden
Init() method will have to create the horizontal scrollbar, if you want
it to be more or less automatic.  You'll have to figure out the maximum
width of all *items* in the collection and set the appropriate 
values of the scrollbar (see description of TScrollbar.SetParams()).
   Over-ride the HandleEvent() method so as to trap events from the 
horizontal scrollbar in order to call the over-ridden Draw method to 
redraw the items.  In the Draw method, get the value of the horizontal
scrollbar, and draw the fields of the items in the listbox view 
accordingly.  Grep the demos for examples of Draw methods and 
study them hard.

2)  Provide a typical listbox which shows only "field1" of each item
and provide a "static field list" view which shows all the other 
fields of the *focused item* in the list box.  Update the 
"static field list" view when the focused item changes.  This could 
be a lot easier to implement, but won't teach you as much about 
the deeper aspects of TV.  If you have to get the job done real soon,
choose this approach.  If you have six fields, you'll need six 
instances of PStaticText.  When you change the "Text" of each, remember
to 
   ...
   DisposeStr(FieldX^.Text);
   FieldX^.Text := NewStr(MyCollection^.FieldX^);
   ...
because you cannot (without doing some damage) simply 
re-assign a string to the "Text" field of a TStaticText instance.

You would have to figure out when the focused item has changed, but 
this isn't too hard.


Hope this gives you enough of a guide to solve the problem.
Have fun.

PF