There is a pattern which occurs very often with list boxes when dealing with
single and multi selections: You have an application with a single selection list box. You implement all the menus and the queryCommand method, so that the menu items are only enabled when an item is enabled and you use methods like selectionOrNil, selection and so on. If you now change the ListBox to a multiple selection list box in the resource view, your application breaks and you have to change a lot of code, because selectionOrNil now doesn't answer an object or nil, but always a collection. So you have to do two things: 1) Change all the code that it now accepts a collection instead of an object. 2) Usually not all menus can be used with a multi selection but should be only enabled with exactly one item selected. So you have to check all the code to see where you change the fragment "listbox selectionOrNil isNil" to either "listbox selections notEmpty" or "listbox selection size = 1". SOLUTION: There is a little change which could solve this problem and the solution is already partially implemented in Dolphin 5. The change is as follows: The methods selection, selectionOrNil, selection:ifAbsent:, selection: and so on should not change their signature in MultipleSelectionListBoxes, this is e.g. selectionOrNil should still answer an object or nil. They should answer an object if exactly one item is selected otherwise nil. Dolphin already introduced additional methods which deal with multiple selections (the methods starting with "selections"). If you want a collection you have to use these methods. Advantages 1) It is vey easy to start converting a single selection application to a multi selection application. You can just change the view resource and everything still works! Then you can change only the methods where multi selection is really supported. All the methods where menus are only for exactly one selection don't need a change. 2) You could also make the other change, by changing a MultiSelectionListBox in the View editor to a Single selection list box, and the application would still work, because the presenter code deals only in terms of the methods "selections*" which would answer either an empty or a one element collection. 3) Even if you don't convert an existing single selection application but write a new application, it is very handy to be able to make this distinction between selection ("give me exactly one object") and selections ("give me a collection of objects, which may be empty"), because you still have the pattern above, that only some methods are situable for multiple objects. 4) The components and presenters become much more pluggable because they now always work with single and multiselection listboxes and can be better reused. As said it seems to me that exactly this idea lead to the definition of the two method groups "selection*" and "selections*", but then the idea was not carried out fully, because the MultiSelectionListBox overrides the methods in a "wrong" manner and breaks there signatures. Comments are very welcome. Regards Carsten Haerle |
"Carsten Haerle" <[hidden email]> wrote in message
news:buo3pd$ouo$05 > There is a pattern which occurs very often with list boxes when dealing with > single and multi selections: [snip] > As said it seems to me that exactly this idea lead to the definition of the > two method groups "selection*" and "selections*", but then the idea was not > carried out fully, because the MultiSelectionListBox overrides the methods > in a "wrong" manner and breaks there signatures. > > Comments are very welcome. I think the idea of making single and multi select listboxes interhangeable is a good one and will work. I use different techniques in my portable GUI library, but with the same effect; that you can switch between single- and multi-select, and it just works. It is very convenient. Regards, Peter van Rooijen Amsterdam |
In reply to this post by Carsten Haerle
Carsten Haerle wrote:
> SOLUTION: > There is a little change which could solve this problem and the solution is > already partially implemented in Dolphin 5. The change is as follows: > > The methods selection, selectionOrNil, selection:ifAbsent:, selection: and > so on should not change their signature in MultipleSelectionListBoxes, this > is e.g. selectionOrNil should still answer an object or nil. They should > answer an object if exactly one item is selected otherwise nil. That's better, but still a bit brittle. If they would all answer a collection, they'd be completely interchangeable. For accessing the result, you'd also want Collection>>firstOrNil ^self firstOr: [nil] first Collection>>firstOrEmpty ^self firstOr: [self] Collection>>firstOr: thenWhat ^(self orIfEmpty: thenWhat) first The application logic and presentation/view logic are then decoupled; either could then change without affecting the other. -cstb |
This would be another solution, but with some disadvantages:
* Would need extensions to collection * Would break a lot of code * Feels not as intuitive to my as the solution described (I would think that the intuitive interpretation of a name like #selectionOrNil is that it answers a single object or nil) . Also the implementation is Dolphin is already almost done, just a change of 2 or 3 methods which should break almost no existing code. Regards Carsten "cstb" <[hidden email]> schrieb im Newsbeitrag news:[hidden email]... > > > Carsten Haerle wrote: > > > SOLUTION: > > There is a little change which could solve this problem and the solution is > > already partially implemented in Dolphin 5. The change is as follows: > > > > The methods selection, selectionOrNil, selection:ifAbsent:, selection: and > > so on should not change their signature in MultipleSelectionListBoxes, this > > is e.g. selectionOrNil should still answer an object or nil. They should > > answer an object if exactly one item is selected otherwise nil. > > That's better, but still a bit brittle. > If they would all answer a collection, > they'd be completely interchangeable. > > For accessing the result, > you'd also want > > Collection>>firstOrNil > ^self firstOr: [nil] > first > > Collection>>firstOrEmpty > ^self firstOr: [self] > > Collection>>firstOr: thenWhat > ^(self orIfEmpty: thenWhat) > first > > The application logic and presentation/view logic > are then decoupled; either could then change without > affecting the other. > > -cstb |
In reply to this post by Carsten Haerle
Carsten Haerle wrote:
> The methods selection, selectionOrNil, selection:ifAbsent:, selection: and > so on should not change their signature in MultipleSelectionListBoxes, > this is e.g. selectionOrNil should still answer an object or nil. They > should answer an object if exactly one item is selected otherwise nil. > Dolphin already introduced additional methods which deal with multiple > selections (the methods starting with "selections"). If you want a > collection you have to use these methods. I rather like this idea. In fact most of my code ends up going through local helper methods coded like: selectedWotsits | all | all := self WostitsPresenter selections. ^ all size = 1 ifTrue: [all first] ifFalse: [nil]. so I'm fairly sure that the pattern is a workable one from the point of view of the application code structure. My only reservation is that the #selection* methods are used rather a lot, and it's difficult to know how much code there is that relies on the documented existing behaviour. E.g. there are 155 senders of #selectionOrNil in my image today -- I have little appetite for wading through them checking them all. Have you tried making this change in your image ? If so, then what happened ? -- chris |
In reply to this post by Carsten Haerle
"Carsten Haerle" <[hidden email]> wrote in message
news:buo3pd$ouo$05$[hidden email]... > ... > The methods selection, selectionOrNil, selection:ifAbsent:, selection: and > so on should not change their signature in MultipleSelectionListBoxes, this > is e.g. selectionOrNil should still answer an object or nil. They should > answer an object if exactly one item is selected otherwise nil. Dolphin > already introduced additional methods which deal with multiple selections > (the methods starting with "selections"). If you want a collection you have > to use these methods. >... I completely agree. This was an early design error that was not spotted until it was too late. The #selection methods are so widely used that we came to the conclusion we could not correct it. The problem was (and is, even more so now) that most applications using multiple selection lists still go through the #selection* family of methods and expect a to receive/pass a collection. As you suspect the selections* family of methods was introduced because of this issue, since as you have noted this has a consistent and sensible implementation in all cases. However history prevented the correction of the single selection case. In D6 we have been moving toward using the multiple selection protocol more widely. We haven't deprecated the selection* protocols, but I feel that this combined with the introduction of a new set of single selection methods might be the only hope for getting this carbuncle out of the MVP sub-system. I have to say that I am still not entirely comforable with the idea of multiple selection lists implementing a single selection protocol at all, however convenient it might be to the developer. Certainly your proposed solution of implementing it in the multiple selection case to follow the pattern of, for example, PackageBrowserShell>>selectedClass, PackageBrowserShell>>method, PackageSelector>>singlePackage, etc, seems like the best of the choices. There are three basic cases: 1) Multiple selections 2) Exactly one selection 3) Any one selection The last case is rarely used, but where appropriate the choice of which selection to use should not be entirely arbitrary, but something sensible. This could be the first of the selections, but multiple selection lists typically have the notion of a "primary" selection. I don't think we currently provide an easy way to get this that is consistent across the views and presenters. Regards Blair |
One way to solve the problem is to invent a whole new set of apis, but it
will not be easy to find a better name as selectionOrNil for this method. Another easy solution could work as follows: The ListView resource gets a new attribut "legacy selection interface" which will be set to true when an old resource is deserialized, all new resources will have this attribut set to false. All the selection methods now just check this attribut and follow the new and better definition, when this attribut is false and follow the old definition otherwise. This solution would have the following advantages: 1) No new method names for selectionOrNil and similar, because I think there is no better name. Also there wouldn't be two set of methods which do almost the same and would clutter up the ListBox interface. 2) The change would break NO code and could be introduced at any time. 3) It would support the process of migrating old code to new new interface, so that the backward compatibilty atttribute "legacy selection interface" could be thrown away one or two versions later. Comments? Regards Carsten "Blair McGlashan" <[hidden email]> schrieb im Newsbeitrag news:bur20f$kgl85$[hidden email]... > "Carsten Haerle" <[hidden email]> wrote in message > news:buo3pd$ouo$05$[hidden email]... > > ... > > The methods selection, selectionOrNil, selection:ifAbsent:, selection: and > > so on should not change their signature in MultipleSelectionListBoxes, > this > > is e.g. selectionOrNil should still answer an object or nil. They should > > answer an object if exactly one item is selected otherwise nil. Dolphin > > already introduced additional methods which deal with multiple selections > > (the methods starting with "selections"). If you want a collection you > have > > to use these methods. > >... > > I completely agree. This was an early design error that was not spotted > until it was too late. The #selection methods are so widely used that we > came to the conclusion we could not correct it. The problem was (and is, > even more so now) that most applications using multiple selection lists > still go through the #selection* family of methods and expect a to > receive/pass a collection. > > As you suspect the selections* family of methods was introduced because of > this issue, since as you have noted this has a consistent and sensible > implementation in all cases. However history prevented the correction of > single selection case. In D6 we have been moving toward using the multiple > selection protocol more widely. We haven't deprecated the selection* > protocols, but I feel that this combined with the introduction of a new set > of single selection methods might be the only hope for getting this > carbuncle out of the MVP sub-system. > > I have to say that I am still not entirely comforable with the idea of > multiple selection lists implementing a single selection protocol at all, > however convenient it might be to the developer. Certainly your proposed > solution of implementing it in the multiple selection case to follow the > pattern of, for example, PackageBrowserShell>>selectedClass, > PackageBrowserShell>>method, PackageSelector>>singlePackage, etc, seems like > the best of the choices. There are three basic cases: > 1) Multiple selections > 2) Exactly one selection > 3) Any one selection > > The last case is rarely used, but where appropriate the choice of which > selection to use should not be entirely arbitrary, but something sensible. > This could be the first of the selections, but multiple selection lists > typically have the notion of a "primary" selection. I don't think we > currently provide an easy way to get this that is consistent across the > views and presenters. > > Regards > > Blair > > |
"Carsten Haerle" <[hidden email]> wrote in message
news:bv5i25$70g$06$[hidden email]... > One way to solve the problem is to invent a whole new set of apis, but it > will not be easy to find a better name as selectionOrNil for this method. > Another easy solution could work as follows: > > The ListView resource gets a new attribut "legacy selection interface" which > will be set to true when an old resource is deserialized, all new resources > will have this attribut set to false. All the selection methods now just > check this attribut and follow the new and better definition, when this > attribut is false and follow the old definition otherwise. That's an interesting idea. We need to think through whether simply changing the behaviour of the view is sufficient, but certainly a first glance it would appear to be so. Thanks for the suggestion, Regards Blair |
Free forum by Nabble | Edit this page |