Indeed, it was just a first try to have something to build a reflection on :-)
Changing the name is always easier than implementing something new (and it's also easier to have the community involved at this level). I think that #selectedItem is somehow wrong in the context of a tree. I will introduce a specific class to describe a path in the tree Ben ----- Reply message ----- De : "Stéphane Ducasse" <stephane.duca...@inria.fr> Pour : "Any question about pharo is welcome" <pharo-users@lists.pharo.org> Objet : [Pharo-users] Simple Spec Examples Date : ven., oct. 11, 2013 21:08 agreed :) > Would it be possible to change the name of the selector? > > tree selectedItem: (1 -> 11) > > for me that implies that the tree contains an actual item (1 -> 11). > What you want is maybe, #selectedPath: or #selectedItem:1 withParents:{11} > > My general rule is: Each time you have to use an association or a point you > do something wrong.. > It is hard to guess what this association should mean, so either make a > domain object to describe > what you encode in the association or use specific selectors that say what > the arguments mean. > > On 2013-10-11, at 19:52, b...@openinworld.com wrote: > >> b...@openinworld.com wrote: >>> Benjamin wrote: >>>> Ben >>>> >>>> On Oct 11, 2013, at 9:24 AM, b...@openinworld.com wrote: >>>> >>>>>> b...@openinworld.com wrote: >>>>>>>> I found it hard to find documentation on Spec beyond [1],[2],[3], some >>>>>>>> of which seem to have changed some syntax since they were written. >>>>>>>> I've been piecing things together to work out how to set the selected >>>>>>>> item with the simplest example I could. Even though it turns out >>>>>>>> pretty simple, I thought I'd share in case it was useful for others >>>>>>>> that haven't dipped their toes into Spec yet. >>>>>> >>>>>> ComposableModel subclass: #TestSpec >>>>>> instanceVariableNames: 'list text' >>>>>> classVariableNames: '' >>>>>> poolDictionaries: '' >>>>>> category: 'BTCPlay' >>>>>> >>>>>> TestSpec >> initializeWidgets >>>>>> self instantiateModels: #( #list #ListModel ). >>>>>> >>>>>> TestSpec >> getList >>>>>> ^list >>>>>> >>>>>> TestSpec class >> mySpecLayout >>>>>> <spec:#default> >>>>>> ^ SpecLayout composed >>>>>> add:#getList ; >>>>>> yourself. >>>>>> >>>>>> Then from Workspace >>>>>> x := (TestSpec new openWithSpec ; yourself). >>>>>> x getList items: { 1 . 2 . 3 . 4}. >>>>>> x getList setSelectedItem: 2. >>>>>> >>>>>> cheers -ben >>>>>> >>>>>> [1] hal.inria.fr/hal-00759030/PDF/Spec-IWST12-Final.pdf >>>>>> [2] >>>>>> https://ci.inria.fr/pharo-contribution/job/PharoForTheEnterprise/lastSuccessfulBuild/artifact/Spec/Spec.pier.pdf >>>>>> >>> [3] http://hal.inria.fr/docs/00/70/80/67/PDF/SpecTechReport.pdf >>>>>> >>>>>> >>>>>> >>>>>>>> So here is the same thing with TreeModel. >>>>> >>>>> ComposableModel subclass: #TestSpec2 >>>>> instanceVariableNames: 'tree' >>>>> classVariableNames: '' >>>>> poolDictionaries: '' >>>>> category: 'BTCPlay' >>>>> >>>>> TestSpec2 >> initializeWidgets >>>>> self instantiateModels: #( #tree #TreeModel ). tree >>>>> childrenBlock: [ :treeItem | self haltOnce. (treeItem isKindOf: >>>>> Association) ifTrue: [ treeItem value ] ifFalse: [ {} ] ]. >>>>> >>>>> TestSpec2 >> getTree >>>>> ^tree >>>>> >>>>> TestSpec2 class >> mySpecLayout >>>>> <spec:#default> >>>>> ^ SpecLayout composed >>>>> add:#getTree ; >>>>> yourself. >>>>> >>>>> Then from Workspace (referring to attached pic) >>>>> x := (TestSpec2 new openWithSpec ; yourself). >>>>> x getTree roots: { 10 -> { 11. 12 } . 20 -> { 21 . 22 } } . >>>>> x getTree selectedItem. "<Print It> --> 21 " >>>>> x getTree selectedItem: ???? >>>>> >>>>> Now how do I select a particular tree item at each level ? >>>>> eg. Select 10 and Select 12 ? >>>>> >>>>> cheers, ben >>>>>> >>>> There was something missing here at the two levels :) >>>> You can see case 11849[1] fixing the morphic issue >>>> and case 11850 [2] fixing the Spec problem :) >>>> Thanks. I'll try it. >>>> Then your example make me think that using association > to describe the >>>> path may lead to an ambiguous situation >>>> True. But to clarify things, ListModel suffers the same ambiguity as >>>> follows... >>> x := (TestSpec new openWithSpec ; yourself). >>> x getList items: { 1 . 2 . 3 . 2 . 4}. >>> x getList setSelectedItem: 2. >>> >>> ... ListModel and Treemodel should be consistent in this respect. >>> Musing further about this... >>> In the case of a multi-selection ListModel/TreeModel, it is probably >>> reasonable to select all matching. >>> For a single-selection, I'm not sure. Considering ListModel first, maybe >>> defaulting to selecting the first matching is reasonable, perhaps with a >>> backup method to select the Nth match. Then again, if the identical object >>> appears in the list multiple times, then #setSelectedItem: might visually >>> highlight all occurances while still reporting only a single object with >>> #selectedItems. I think part of a test would go... >>> >>> x getList items: { 1 . 2 . 3 . 2 . 4}. >>> x getList setSelectedItem: 2. >>> y := x getList selectedItem. >>> x getList setSelectedItem: y. >>> z := x getList selectedItem. >>> self assert: (y = z) >>> >>> ...which actually works so ListModel is cool in that regard - except maybe >>> an option to visually highlight both 2s would be useful - but as a visual >>> thing maybe that is a handled outside of ListModel. >>> Actually that should work the same with multi-selection. >>> >>> x getList items: { 1 . 2 . 3 . 2 . 4}. >>> x getList setSelectedItems: { 2. 3 }. >>> y := x getList selectedItems. >>> x getList setSelectedItems: y. >>> z := x getList selectedItems. >>> self assert: (y = z) >>> >>> Actually it seems there is no #setSelectedItems:. >>> How then do you save and restore a multi-selection. e.g.... >>> savedSelection := x getList selectedItems. >>> "other code that clears/modifies the selection - like refresh for >>> additional items" >>> x getList selectedItems: savedSelection. >>> >>> cheers -ben >>> >>>> Ben >>>> >>>> [1] https://pharo.fogbugz.com/default.asp?11849 >>>> [2] https://pharo.fogbugz.com/default.asp?11850 >>>> >>>>>> >>>>> <Spec-TreeModel-simple-example.png> >>>>>> >>>> >>>> >>> >> I installed your slices from Issues 11849 & 11850 and it looks mostly good. >> >> Using a modified TreeModel example which I think provides a clearer/nicer >> example... >> >> TestSpec2 >> initializeWidgets >> self instantiateModels: #( #tree #TreeModel ). tree childrenBlock: [ >> :treeItem | (treeItem > 10000) ifTrue: [ #() ] ifFalse: [ (1 to: 3) >> collect: [ :i | treeItem * 10 + i ] ] ]. >> >> Then in Workspace... >> x := (TestSpec2 new openWithSpec ; yourself). >> x getTree roots: { 1. 2 . 1 . 11 }. >> x getTree expandRoots. >> x getTree selectedItem: 11. "left side of attached pic" >> x getTree selectedItem: (1 -> 11). "right side of attached pic" >> >> So the attached pic shows exhibits the behaviour I was musing about earlier >> - very cool. Before those slices there was no response to #selectedItem: >> from the widget. >> However a couple of things... >> >> 1. x getTree selectedItem: 12. >> x getTree selectedItem. "<PrintIt> --> 12" >> while... >> x getTree selectedItem: ( 1 -> 13 ). >> x getTree selectedItem. "<PrintIt> --> 1->13" >> >> I think you really want #selectedItem to return the same thing each time >> regardless of how it was set. That is, just the object. >> Andn further, it would be better to have a separate accessors #selectedItem >> and #selectedPath >> >> 2. The following doesn't work... >> x getTree selectedItem: { 1 -> 12 -> 121 }. >> >> cheers -ben >> >> >> >> >> >> <Issue-11849&11850.png> >