Traditional way to update a ListPresenter in a Shell is to wire events
to know when the modification of items has occuurred. Then find out indices of items has changed, and send updateAtIndex: to ListModel or ListPresenter as many times as the items that changed. I suggest following patchings on ListModel can do all the updating works seemlessly. ListModel>>setList: collection searchPolicy: policy "Private - Initialize the receiver's identity instance variables. Answer the receiver." list := collection. searchPolicy := policy. "PATCHING begins" list do: [:each| each when: #valueChanged send: #updateItem: to: self with: each ]. "PATCHING ends" ListModel>>list: aSequenceableCollection "Set the list of the receiver, i.e. the collection that it represents" list == aSequenceableCollection ifFalse: [ list := aSequenceableCollection. "HwaJongOh begins" list do: [:each| each when: #valueChanged send: #updateItem: to: self with: each ]. "HwaJongOh ends" self trigger: #listChanged ] ListModel>>updateItem: objectInThisList self updateAtIndex: (self indexOf: objectInThisList) After these patches, you can trigger #valueChanged in your model and watch the smart updating happens in your ListPresenter. MyObject>>setter: anObject field1 := anObject. self trigger: #valueChanged Even simpler example will be, array := Array with: 1 asValue. ListPresenter showOn: (ListModel on: array). array first value: 4 Have a good one |
I missed to post 1 more patching...
addAnsweringIndex: newObject "Append newObject as the last element of the receiver. Answer the index at which the object was added." | index | index := self list addAnsweringIndex: newObject. self trigger: #item:addedAtIndex: with: newObject with: index. "PATCHING begins" newObject when: #valueChanged send: #updateItem: to: self with: newObject. "PATCHING ends" ^index |
In reply to this post by Howard Oh
I'm experiencing some side effects of the patching.
Process Viewer holds "dead" threads not allowing GC. This problem goes away by closing the view and reopen it. There may be more unfound side effects. |
Howard Oh escribió:
> I'm experiencing some side effects of the patching. > > Process Viewer holds "dead" threads not allowing GC. This problem goes > away by closing the view and reopen it. > > There may be more unfound side effects. > What if the object changes once removed from the listmodel?, I've not seen that the listmodel is removed from the event-receivers of the object in the collection. Saludos. -- Esteban. |
In reply to this post by Howard Oh
Howard,
> ListModel>>setList: collection searchPolicy: policy > "Private - Initialize the receiver's identity instance variables. > Answer the receiver." > > list := collection. > searchPolicy := policy. > "PATCHING begins" > list do: [:each| each when: #valueChanged send: #updateItem: to: self > with: each ]. > "PATCHING ends" I think this is a good idea but it would work better as a custom sub-class of ListModel than as a change to the existing ListModel. The main reason is that many (most!) objects don't generate change events themselves, so an application which used them could not rely on the ListModel seeing the changes automatically. Some other thoughts: You'd also have to override quite a number of other methods, such as #at:put: #addAnsweringIndex: #removeAtIndex: and so on. As Esteban mentioned, you'd also want to remove the event triggers when objects were taken out of the list. STB would take a bit of thought. If the ListModel were saved in STB format, should it re-establish the events when it is re-created ? I /think/ the answer is yes, but I'm not sure. The same question applies to #deepCopy. -- chris |
Chris Uppal wrote:
> Some other thoughts: Just to add a thought from my side. If you create a Subclass of ListModel I would also recommend to make the triggerSelector pluggable. I have many models which do trigger change events without using #valueChanged. Especially for complex models which are more than simple values #valueChanged doesn't seem right. CU, Udo |
In reply to this post by Esteban A. Maringolo-3
Yes, indeed.
I've also patching some event unwiring at the removeing methods. SmartListModel>>removeAll "Empty the receiver of all contents." self list do: [:each| each removeEventsTriggeredFor: self]. ^super removeAll"self list: self list copyEmpty" removeAtIndex: anInteger "Remove, and answer, the element of the receiver at the specified <integer> index, by shuffling elements which succeed it down one slot. Raise an BoundsError if there is no element with that index." | elem | elem := self list removeAtIndex: anInteger. elem removeEventsTriggeredFor: self. self trigger: #itemRemovedAtIndex: with: anInteger. ^elem As Process Monitor showing strange behavior, I've decided to subclass ListModel and move all the method patchings to it. Its name is SmartListModel. After this Process Monitor worked correctly. Have a Good One |
Free forum by Nabble | Edit this page |