Multiple Column View

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Multiple Column View

gregarican
I have looked through "The Dolphin Smalltalk Companion" as well as some
other examples (like PersonalMoney) but can't seem to get a handle on
how to populate a multiple column object in a view. Specifically this
is an extended list presenter in Dolphin X6.

As an example I populate two different ListModels with information. One
of them collects document numbers. Then the other one collects document
dates. They are two different ListModels.

If I create a extended list presenter I can only populate the first
column with information. To do so I just change the name of the
presenter to be the document number variable. If I try to add a second
column I don't know how to get the information across using
getContentsBlock. If I don't use getContentsBlock the second column
just repeats the elements that are presented in the first one.

Any newbie examples anyone can pass along?


Reply | Threaded
Open this post in threaded view
|

Re: Multiple Column View

Chris Uppal-3
gregarican wrote:

> As an example I populate two different ListModels with information. One
> of them collects document numbers. Then the other one collects document
> dates. They are two different ListModels.

You can't make a ListPresenter show two different ListModels.  They are
designed to show /one/ list, with each column showing a different "aspect" of
the element in each position.

There are several ways to get the result you want.  Probably the easiest is to
have an object with contains all the data you want to display in each row, and
then use a list of those.  Chances are that if you have such closely associated
data in your domian, then you want some object which relates them anyway.

If that's unsuitable, then you can do it with a level of indirection.  Store
indexes in the ListPresenter's model, and use those to access the "real"
listss.

E.g:

    "set up a model"
    l1 := #( dog cat elephant ).
    l2 := #( Fido Tiddles Rosy ).
    m := ListModel on: (1 to: 3).

    "show a list with two columns"
    lp := ListPresenter show: 'Enhanced list view' on: m.
    lv := lp view.
    lv addColumn.

    "make the columns refer back to the other two lists"
    (lv columnAtIndex: 1) getContentsBlock: [:i | l1 at: i].
    (lv columnAtIndex: 2) getContentsBlock: [:i | l2 at: i].

Typically you wouldn't need all that code since you'd set most of it up in the
View Composer, but the idea's the same.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Multiple Column View

Ian Bartholomew-21
In reply to this post by gregarican
gregarican,

> As an example I populate two different ListModels with information. One
> of them collects document numbers. Then the other one collects document
> dates. They are two different ListModels.

All the information passed to the ListPresenter must be accessible
through one collection.  Use the #getContentsBlock to access the column
information for each row.

> Any newbie examples anyone can pass along?

Some simple examples.  I'll show them in workspace code but it should be
readily translatable to a ListPresenter/View setup.


collection := OrderedCollection with: 1@2 with: 3@4 with: 5@6 with: 7@8.
lp := ListPresenter show: 'Enhanced list view' on: collection.

"Evaluating the above shows a list view with one column, and the
points being displayed in that column.  Now add a second column"

lp view addColumn: (ListViewColumn text: 'Y').

"Evaluating all the above now gives two columns, both containing
all the points.  This is because the #getContentsBlock defaults to
answering the object in the collection (a Point)"

lp view primaryColumn text: 'X'.
lp view primaryColumn getContentsBlock: [:item| item x].
(lp view columnAtIndex: 2) getContentsBlock: [:item| item y].

"Now evaluating all the above puts the x values in the first column
and the y values in the seconds column.  This is because you have told
each column how to obtain its contents from the underlying object.


Another example

collection := OrderedCollection with: 'abc' with: 'def' with: 'ghi'
with: 'jklm' with: 'no'.
lp := ListPresenter show: 'Enhanced list view' on: collection.
lp view getImageBlock: nil.
lp view
        primaryColumn text: 'First';
        getContentsBlock: [:item | item first].
lp view addColumn: (
        (ListViewColumn text: 'Rest')
                getContentsBlock: [:item | item copyFrom: 2];
                yourself)
       


And one final one, with index/date contained ina collection of
associations (one of many ways)

collection := OrderedCollection
        with: 1 -> (Date fromString: '1/1/2006')
        with: 2 -> (Date fromString: '1/2/2006')
        with: 3 -> (Date fromString: '1/3/2006')
        with: 19 -> (Date fromString: '1/4/2006').
lp := ListPresenter show: 'Enhanced list view' on: collection.
lp view getImageBlock: nil.
lp view
        primaryColumn text: 'Index';
        getContentsBlock: [:item | item key].
lp view addColumn: (
        (ListViewColumn text: 'Date')
                getContentsBlock: [:item | item value];
                yourself)


There's a _lot_ more you can do with ListView though - this is just the
basics.

--
Ian

Use the Reply-To address to contact me (limited validity).
Mail sent to the From address is ignored.


Reply | Threaded
Open this post in threaded view
|

Re: Multiple Column View

gregarican
Thanks everyone for all of the help. This has really filled in the
blanks for me!


Reply | Threaded
Open this post in threaded view
|

Re: Multiple Column View

Ian Bartholomew-21
Just to clarify one thing which might cause a bit of confusion.

In Chris' example he passed a ListModel as the model for the
ListPresenter whereas I used an OrderedCollection.  In this situation
both will work but Chris' version is correct and will prevent future
walkbacks occurring when more complex use is made of the MVP triad.

In "proper" code, i.e. not simplified workspace examples, the issue
doesn't normally crop up as the creation of the ListPresenter and it's
population would usually be done in different places.

Personally I don't use a new ListModel but update the existing ListModel
contents - but that's just a personal preference.  I would tend to use

createComponents
[]
listP := self add: ListPresenter new name: 'whatever'

and somewhere else do

listP list: myInitialCollection

but

listP model: (ListModel on: myInitialCollection)

is just as valid.  The only difference (I think) is that the first
version will resort the list according to the ListPresenter's sort
criteria but the second won't.

--
Ian

Use the Reply-To address to contact me (limited validity).
Mail sent to the From address is ignored.


Reply | Threaded
Open this post in threaded view
|

Re: Multiple Column View

Chris Uppal-3
Ian,

> listP list: myInitialCollection
>
> but
>
> listP model: (ListModel on: myInitialCollection)
>
> is just as valid.  The only difference (I think) is that the first
> version will resort the list according to the ListPresenter's sort
> criteria but the second won't.

FWIW, I usually use the first form too.  IIRC it causes less flicker than
changing the model.

Of course, there are times when I have to set the model explicitly, e.g. if I
want two ListPresenters to share a model, or when I use one of my
DerivedListModels.

    -- chris