Re: Sort in a ListModel

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

Re: Sort in a ListModel

Sergei Gnezdov-2
I followed instructions in the old post which tells how to handle
sorted lists.

> From: "Ian Bartholomew" <[hidden email]>
> Subject: Re: Sort in a ListModel
> Date: Fri, 6 Jul 2001 20:59:36 +0100
> Message-ID: <9i55fb$h3rdb$[hidden email]>
>
> [Snip...]
>
> You then add the method that updates the ListPresenter -
>
> MyPresenter>>onMyListChanged
>     myListPresenter model list: self model myList

I ended up writing the following code in onMyListChanged:

        sortBlock := listPresenter sortBlock.
        listPresenter model list: self model myList.
        listPresenter view refreshContents.
        listPresenter beSorted: sortBlock.

I observed that I have to keep track of the sorting all by myself and
that I have to refresh the view explicitly.  Is it the right way to do
work with the list?


Thank you

------------------------------------------------------------------
The following is a contents of Ian's message for your convenience.
------------------------------------------------------------------
From: "Ian Bartholomew" <[hidden email]>
Newsgroups: comp.lang.smalltalk.dolphin
Subject: Re: Sort in a ListModel
Date: Fri, 6 Jul 2001 20:59:36 +0100
Message-ID: <9i55fb$h3rdb$[hidden email]>

Dmitry,

> What should I do really, any ideas?

Dolphin's MVP is slightly awkward in the way it handles
ListPresenters, you
can easily end up with a ListModel and ListPresenter that have a bit
too
much in common.

One solution is to split them completely -

To do this - your MyModel contains a list held in a simple
OrderedCollection. All additions, deletions or modification to items
in the
list are then done through methods that trigger an event specific to
your
model (#myListChanged for instance). MyModel also exposes the list by
including a method that answers, preferably, a copy of the list.

MyModel>>addItem: aNewItem
    myList add: aNewItem.
    self trigger: #myListChanged

MyModel>>myList
    ^myList copy

Your MyPresenter adds a ListPresenter as normal -

MyPresenter>>createComponents
    ....
    myListPresenter := self add: ListPresenter new name: 'my list
view'

You also have to tell the associated model that you are interested in
the
new triggered event.  Where and when to do this depends to some extent
on
how you connect the MyModel instance to your MyPresenter instance. A
good
place is in the #createSchematicWiring method but this requires you to
use
the model created in MyPresenter class>>defaultModel. If not the
#onViewOpened can be useful.

MyPresenter>>createSchematicWiring
    .....
    self model when: #myListChanged send: #onMyListChanged to: self

You then add the method that updates the ListPresenter -

MyPresenter>>onMyListChanged
    myListPresenter model list: self model myList

One final job is to ensure that the list is populated when MyPresenter
is
initially opened -

MyPresenter>>onViewOpened
    ........
    self onMyListChanged

Now, when your user clicks on the sort header the ListModel associated
with
the ListPresenter is sorted, and converted to a SortedCollection but
the
OrderedCollection contained in your presenter is unchanged. Adding
items to
the list, in the model, triggers the event and tells MyPresenter to
update
the list.

Some other points -
- If you want to maintain the current selection after a new item has
been
added you have to add a couple of lines to #onMyListChanged to
remember the
selection and reselect it, if possible, after the list is changed.

- If you have a large list then doing a blanket update on every change
is
very inefficient. You can get round that by adding extra triggers that
specify the action that has occurred and the data that changed. For
example -

MyModel>>addItem aNewItem
    myList addItem: aNewItem.
    self trigger: #itemAddedToList with: aNewItem

for which you could than use the event target -

MyPresenter>>onItemAddedToList: anItem
    myListPresenter model add: anItem

If you want a simple demo package that shows the above then mail me

Regards
    Ian


Reply | Threaded
Open this post in threaded view
|

Re: Sort in a ListModel

Ian Bartholomew-19
Sergei,

> I observed that I have to keep track of the sorting all by myself and
> that I have to refresh the view explicitly.  Is it the right way to do
> work with the list?

It still appears to work correctly for me, at least in a workspace (and I've
no reason to believe it will be different in an actual method).  To
demonstrate, in a workspace evaluate

lp := ListPresenter show: 'Enhanced list view'.
lp view primaryColumn
    text: 'Key';
    getContentsBlock: (Message selector: #key).
lp view addColumn: ((ListViewColumn text: 'Value')
    getContentsBlock: (Message selector: #value);
    yourself).
data := Array with: 1->$f with: 3->$d with: 2->$e.
lp list: data.

<aside>

The problem in the original thread was that if you immediately
evaluate

lp list == data

it will answer true.  However if you click on a ListColumn header, to sort
the list, then the same evaluation will now answer false.

<back>

Sort the list by clicking on the value column header and then evaluate

data1 := Array with: 26->$p with: 24->$r with: 25->$q .
lp list: data1

The new list is displayed using the sort order that was selected when the
column header was clicked for the previous list, and that's what I would
have expected.

I'm not sure why you are having problems with the sorting in your
application.  What actually happens if you use the original code, does the
ListView display the list but just doesn't sort it correctly?

--
Ian

Use the Reply-To address to contact me.
Mail sent to the From address is ignored.


Reply | Threaded
Open this post in threaded view
|

Re: Sort in a ListModel

Chris Uppal-3
In reply to this post by Sergei Gnezdov-2
Sergei Gnezdov wrote:

> listPresenter model list: self model myList.

Try:

    listPresenter list: self model myList.

 From memory, that preserves the sort block.  (And that's what Ian's using in
his reply)

BTW, I've grown increasingly dissatisfied with the way that that once a Dolphin
list view's contents have been sorted, there's no way (for the user of the GUI)
to turn sorting *off* again.  I have a set of hacks/patches to the base image
that change the way sorted list headers work so that they cycle through 3
states -- unsorted, sorted, reverse sorted  -- instead of just toggling between
sorted and reverse-sorted.  Would anyone else like to see such a thing, perhaps
as part of the base image ?  I'll post code if there's any interest.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Sort in a ListModel

Bill Schwab-2
Chris,

> I have a set of hacks/patches to the base image
> that change the way sorted list headers work so that they cycle through 3
> states -- unsorted, sorted, reverse sorted  -- instead of just toggling
between
> sorted and reverse-sorted.  Would anyone else like to see such a thing,
perhaps
> as part of the base image ?  I'll post code if there's any interest.

That's a great idea!

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Sort in a ListModel

Sergei Gnezdov-2
In reply to this post by Ian Bartholomew-19
On Mon, 12 Apr 2004 09:49:03 +0100, "Ian Bartholomew"
<[hidden email]> wrote:

>Sergei,
>
>> I observed that I have to keep track of the sorting all by myself and
>> that I have to refresh the view explicitly.  Is it the right way to do
>> work with the list?
>
>It still appears to work correctly for me, at least in a workspace (and I've
>no reason to believe it will be different in an actual method).  To
>demonstrate, in a workspace evaluate
>
>lp := ListPresenter show: 'Enhanced list view'.
>lp view primaryColumn
>    text: 'Key';
>    getContentsBlock: (Message selector: #key).
>lp view addColumn: ((ListViewColumn text: 'Value')
>    getContentsBlock: (Message selector: #value);
>    yourself).
>data := Array with: 1->$f with: 3->$d with: 2->$e.
>lp list: data.
>
><aside>
>
>The problem in the original thread was that if you immediately
>evaluate
>
>lp list == data
>
>it will answer true.  However if you click on a ListColumn header, to sort
>the list, then the same evaluation will now answer false.
>
><back>
>
>Sort the list by clicking on the value column header and then evaluate
>
>data1 := Array with: 26->$p with: 24->$r with: 25->$q .
>lp list: data1
>
>The new list is displayed using the sort order that was selected when the
>column header was clicked for the previous list, and that's what I would
>have expected.
>
>I'm not sure why you are having problems with the sorting in your
>application.  What actually happens if you use the original code, does the
>ListView display the list but just doesn't sort it correctly?

Based on your description I don't think that my problem is exactly the
same.

I had the following issue (initially).

List is sorted when item is added.  When the original list is saved,
the added item is lost.  This loss is observed only when list is
sorted.

So, I set on the quest to solve the problem.  I introduced the model
and connected it according to the instructions in this thread.
Unfortunately, I discovered that when I add a new item it does not
show up in the list.  So, I came up with the set of calls to make sure
that when item is added:
- original sorting is not destroyed
- added item is selected

The code I posted attempts to preserve sorting.  I also had a code to
select added object.


Reply | Threaded
Open this post in threaded view
|

Re: Sort in a ListModel

Chris Uppal-3
Sergei Gnezdov wrote:

> Unfortunately, I discovered that when I add a new item it does not
> show up in the list.  So, I came up with the set of calls to make sure
> that when item is added:
> - original sorting is not destroyed
> - added item is selected

I may be misunderstanding what you are trying to do, but this works for me (and
is how these components are designed to work).

    "create list model, and show presenter on it"
    lm := ListModel on: ('hello there' asOrderedCollection).
    lp := ListPresenter show: 'Enhanced list view' on: lm.

    "now click on column header to get sorted collection"

    "now add new item and make it selected"
    lm add: $c.
    lp selection: $c.

The key point is the use of a ListModel.  Since ListPresenters have a ListModel
internally, you could have phrased the whole snippet in terms of that, instead
of creating your own explicitly:

   "show list presenter and add items to it's ListModel"
    lp := ListPresenter show: 'Enhanced list view'.
    lp model addAll: 'hello there'.

    "now click on column header to get sorted collection"

    "now add new item and make it selected"
    lp model add: $c.
    lp selection: $c.

The difference is often only a matter of taste.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Sort in a ListModel

Sergei Gnezdov-2
In reply to this post by Ian Bartholomew-19
On Mon, 12 Apr 2004 09:49:03 +0100, "Ian Bartholomew"
<[hidden email]> wrote:

>Sergei,
>
>> I observed that I have to keep track of the sorting all by myself and
>> that I have to refresh the view explicitly.  Is it the right way to do
>> work with the list?
>
>It still appears to work correctly for me, at least in a workspace (and I've
>no reason to believe it will be different in an actual method).  To
>demonstrate, in a workspace evaluate
>
>lp := ListPresenter show: 'Enhanced list view'.
>lp view primaryColumn
>    text: 'Key';
>    getContentsBlock: (Message selector: #key).
>lp view addColumn: ((ListViewColumn text: 'Value')
>    getContentsBlock: (Message selector: #value);
>    yourself).
>data := Array with: 1->$f with: 3->$d with: 2->$e.
>lp list: data.
>
><aside>
>
>The problem in the original thread was that if you immediately
>evaluate
>
>lp list == data
>
>it will answer true.  However if you click on a ListColumn header, to sort
>the list, then the same evaluation will now answer false.
>
><back>
>
>Sort the list by clicking on the value column header and then evaluate
>
>data1 := Array with: 26->$p with: 24->$r with: 25->$q .
>lp list: data1
>
>The new list is displayed using the sort order that was selected when the
>column header was clicked for the previous list, and that's what I would
>have expected.
>
>I'm not sure why you are having problems with the sorting in your
>application.  What actually happens if you use the original code, does the
>ListView display the list but just doesn't sort it correctly?

Based on your description I don't think that my problem is exactly the
same.

I had the following issue (initially).

List is sorted when item is added.  When the original list is saved,
the added item is lost.  This loss is observed only when list is
sorted.

I introduced the model and connected it according to the instructions
in this thread.  Unfortunately, I discovered that when I add a new
item it does not show up in the list.  So, I came up with the set of
calls to make sure  that when item is added:
- original sorting is not destroyed
- added item is selected

The code I posted attempts to preserve the sorting.  I also had a code
to select added object.


Reply | Threaded
Open this post in threaded view
|

Re: Sort in a ListModel

Chris Uppal-3
In reply to this post by Bill Schwab-2
Bill,
>
> > I have a set of hacks/patches to the base image
> > that change the way sorted list headers work so that they cycle through
> > 3 states -- unsorted, sorted, reverse sorted  -- instead of just
> > toggling between sorted and reverse-sorted.  Would anyone else like to
> > see such a thing, perhaps as part of the base image ?  I'll post code
> > if there's any interest.
>
> That's a great idea!

I've sent the code off-line.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Sort in a ListModel

Sergei Gnezdov-3
On 2004-04-17, Chris Uppal <[hidden email]> wrote:
>> > Would anyone else like to
>> > see such a thing, perhaps as part of the base image ?  I'll post code
>> > if there's any interest.
>>
>> That's a great idea!
>
> I've sent the code off-line.
>
>     -- chris

I don't understand this.


Reply | Threaded
Open this post in threaded view
|

Re: Sort in a ListModel

Chris Uppal-3
Sergei Gnezdov wrote:

> > I've sent the code off-line.

> I don't understand this.

I meant that I'd sent the code to Bill by email.

(In a news group posting, "off-line" is often used to mean "via a medium other
than the news group, such as phone or email".)

    -- chris