Hi,
i have to make a UI where users can sort items (sentences) into different collections by dragging and dropping them between list views. Is this possible with the widgets currently available in Pharo? M. |
Hi Martin,
yes, most list-like widgets can drag and drop. Feedback when inserting items in lists could be improved, however (i.e. you can drop on a list item, but I've never seen the feedback for dropping between list items). Thierry Le 02/04/2014 16:09, MartinW a écrit : > Hi, > i have to make a UI where users can sort items (sentences) into different > collections by dragging and dropping them between list views. Is this > possible with the widgets currently available in Pharo? > M. > > > > -- > View this message in context: http://forum.world.st/Drag-and-drop-items-between-list-views-tp4752285.html > Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com. > > > -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95 |
I tried the following, but i do not know what to do in the acceptDropBlock. It seems the receiver in the block is only an item in a list, but how do i get the receiving list/collection?
What i want to achieve is that a user can drag the '1' from list1 to list2 and the resulting collections will then be collection1: (2 3 4 5) collection2: ($a $b $c $d $e 1) and the lists will be updated accordingly. | collection1 collection2 list1 list2 | collection1 := #(1 2 3 4 5). collection2 := #($a $b $c $d $e). list1 := ListModel new. list1 items: collection1. list1 dragEnabled: true. list1 dropEnabled: true. list1 acceptDropBlock: [ :transfer :event :source :receiver :index | self halt ]. list1 openWithSpec. list2 := ListModel new. list2 items: collection2. list2 dragEnabled: true. list2 dropEnabled: true. list2 acceptDropBlock: [ :transfer :event :source :receiver :index | self halt ]. list2 openWithSpec.
|
Ok, look at that code:
| collection1 collection2 list1 list2 | collection1 := #(1 2 3 4 5) asOrderedCollection. collection2 := #($a $b $c $d $e) asOrderedCollection. list1 := ListModel new. list1 items: collection1. list1 dragEnabled: true. list1 dropEnabled: true. list1 acceptDropBlock: [ :transfer :event :source :receiver :index | transfer passenger do: [:e | collection1 insert: e first before: index. collection2 remove: e first]. list1 items: collection1. list2 items: collection2 ]. list1 openWithSpec. list2 := ListModel new. list2 items: collection2. list2 dragEnabled: true. list2 dropEnabled: true. list2 acceptDropBlock: [ :transfer :event :source :receiver :index | self halt ]. ^ list2 openWithSpec Now you can drag and drop from list2 to list1, and I think the code is good for drag and drop of multiple items. Thierry Le 02/04/2014 17:08, MartinW a écrit : > I tried the following, but i do not know what to do in the acceptDropBlock. > It seems the receiver in the block is only an item in a list, but how do i > get the receiving list/collection? > What i want to achieve is that a user can drag the '1' from list1 to list2 > and the resulting collections will then be collection1: (2 3 4 5) > collection2: ($a $b $c $d $e 1) and the lists will be updated accordingly. > > > | collection1 collection2 list1 list2 | > > collection1 := #(1 2 3 4 5). > collection2 := #($a $b $c $d $e). > > list1 := ListModel new. > list1 items: collection1. > list1 dragEnabled: true. > list1 dropEnabled: true. > list1 acceptDropBlock: [ :transfer :event :source :receiver :index | self > halt ]. > list1 openWithSpec. > > list2 := ListModel new. > list2 items: collection2. > list2 dragEnabled: true. > list2 dropEnabled: true. > list2 acceptDropBlock: [ :transfer :event :source :receiver :index | self > halt ]. > list2 openWithSpec. > > > Goubier Thierry wrote >> yes, most list-like widgets can drag and drop. Feedback when inserting >> items in lists could be improved, however (i.e. you can drop on a list >> item, but I've never seen the feedback for dropping between list items). >> Le 02/04/2014 16:09, MartinW a écrit : >>> i have to make a UI where users can sort items (sentences) into different >>> collections by dragging and dropping them between list views. Is this >>> possible with the widgets currently available in Pharo? > > > > > > -- > View this message in context: http://forum.world.st/Drag-and-drop-items-between-list-views-tp4752285p4752328.html > Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com. > > > -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95 |
Thank you. This is a step forward. The thing is i can't hardcode the collections. In the end product i don't have two but seven lists, so i must be able to detect in the acceptDropBlock which is the receiving collection/list.
|
Le 02/04/2014 17:40, MartinW a écrit : > Thank you. This is a step forward. The thing is i can't hardcode the > collections. In the end product i don't have two but seven lists, so i must > be able to detect in the acceptDropBlock which is the receiving > collection/list. I'll try to redo a halt in there to see if I can get the target inside the event, and, from the target, be able to get back to the list then :) Thierry > > Goubier Thierry wrote >> Ok, look at that code: >> >> | collection1 collection2 list1 list2 | >> collection1 := #(1 2 3 4 5) asOrderedCollection. >> collection2 := #($a $b $c $d $e) asOrderedCollection. >> list1 := ListModel new. >> list1 items: collection1. >> list1 dragEnabled: true. >> list1 dropEnabled: true. >> list1 acceptDropBlock: >> [ :transfer :event :source :receiver :index | >> transfer passenger do: >> [:e | >> collection1 insert: e first before: index. >> collection2 remove: e first]. >> list1 items: collection1. >> list2 items: collection2 ]. >> list1 openWithSpec. >> list2 := ListModel new. >> list2 items: collection2. >> list2 dragEnabled: true. >> list2 dropEnabled: true. >> list2 acceptDropBlock: [ :transfer :event :source :receiver :index | >> self halt ]. >> ^ list2 openWithSpec >> >> Now you can drag and drop from list2 to list1, and I think the code is >> good for drag and drop of multiple items. > > > > > > -- > View this message in context: http://forum.world.st/Drag-and-drop-items-between-list-views-tp4752285p4752342.html > Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com. > > > -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95 |
In reply to this post by MartinW
Le 02/04/2014 17:40, MartinW a écrit : > Thank you. This is a step forward. The thing is i can't hardcode the > collections. In the end product i don't have two but seven lists, so i must > be able to detect in the acceptDropBlock which is the receiving > collection/list. Ok, the :source is your friend (should be named :target :)); it will give you the Morph (whose model model is the ListModel instance). list1 acceptDropBlock: [ :transfer :event :source :receiver :index | | c1 c2 l1 l2 | l1 := source model model. c1 := l1 listItems. l2 := transfer source model model. c2 := l2 listItems. transfer passenger do: [ :e | c1 insert: e first before: index. c2 remove: e first ]. l1 items: c1. l2 items: c2 ]. This code does not integrate the fact that transfer may be a window (try to drag and drop a window on list1 and you'll see :)) Thierry -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95 |
First of all thank you for taking the time to explain all this to me! I already learned a lot about working with the spec widgets..
I still have a problem. The first version with the hardcoded collections did obviously change the original collections (that's the desired behaviour).
The last version though, did change the items in the list views, but not the original collections.
|
Le 02/04/2014 20:44, MartinW a écrit : > First of all thank you for taking the time to explain all this to me! I > already learned a lot about working with the spec widgets.. You're giving me good code to work with, and the things I use are more Morphic than Spec, which is more in my circle of confidence. > I still have a problem. The first version with the hardcoded collections did > obviously change the original collections (that's the desired behaviour). > > The last version though, did change the items in the list views, but not the > original collections. You're right. My problem is that I couldn't see a way to link the ListModel to the collection so that a change to one of them would propagate to the other. I'll go and do some reading on Spec. Another approach, that I would use, is to put more complex objects inside the lists. Thoses objects would know how to get added / removed from their respective collections, and then I would propagate collection changes to the ListModel instances. Does it makes sense? Thierry -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95 |
That sounded promising. I made a Collectible class. It's instances know how to add themselves to a collection (i'm not sure if that's a good idea, but as experiment..) The problem is, i never get to these objects in my acceptDropBlock. In list1 acceptDropBlock: [ :transfer :event :source :receiver :index | transfer passenger do: [:element | element addSelfToCollection: collection1] ]. the element is only a ByteString - the name of my Collectible object. :( Are there other possibilities if i do not use Spec? |
CONTENTS DELETED
The author has deleted this message.
|
In reply to this post by MartinW
here is a "hackish" solution: collection1 := #(1 2 3 4 5) asOrderedCollection. collection2 := #($a $b $c $d $e) asOrderedCollection.
list1 := ListModel new. list1 items: collection1. list1 dragEnabled: true. list1 dropEnabled: true. list1 acceptDropBlock: [ :transfer :event :source :receiver :index |
| c1 c2 l1 l2 | l1 := source model model. c1 := l1 listItems. l2 := transfer source model model.
c2 := l2 listItems. transfer passenger do: [ :e | c1 insert: e first before: index.
c2 remove: e first ]. l1 items: c1. collection1 removeAll; addAll: c1.
l2 items: c2. collection2 removeAll; addAll: c2. ]. list1 openWithSpec. list2 := ListModel new.
list2 items: collection2. list2 dragEnabled: true. list2 dropEnabled: true. list2 acceptDropBlock: [ :transfer :event :source :receiver :index |
self halt ]. ^ list2 openWithSpec. The problem here is that by default, the list items are sorted, setting the listItems with a copy. Maybe it would be better to actually do not sort until one sets a real sortingBlock.
Ben 2014-04-03 22:55 GMT+02:00 MartinW <[hidden email]>: Goubier Thierry wrote |
In reply to this post by MartinW
Le 03/04/2014 22:55, MartinW a écrit : > Goubier Thierry wrote >> Another approach, that I would use, is to put more complex objects >> inside the lists. Thoses objects would know how to get added / removed >> from their respective collections, and then I would propagate collection >> changes to the ListModel instances. > > That sounded promising. I made a Collectible class. It's instances know how > to add themselves to a collection (i'm not sure if that's a good idea, but > as experiment..) > > The problem is, i never get to these objects in my acceptDropBlock. In > > list1 acceptDropBlock: [ :transfer :event :source :receiver :index | > transfer passenger do: [:element | element addSelfToCollection: > collection1] ]. > > the element is only a ByteString - the name of my Collectible object. :( I believe what is happening is that ListModel and the widget above convert your Collectible instance into a string to display it; and then the drag and drop code forget to get the model object behind the displayed string (i.e. the drag and drop code expect all items to be morphs with all sort of complex stuff). By the way, any chance of having your code as an example for Spec? I went through the spec documentation and I couldn't see anything similar, and, from our difficulties to get that to work, I would guess a bit of work on Spec drag and drop support could be a good thing. > Are there other possibilities if i do not use Spec? Yes. Drag and drop code in Morphic is fairly similar. The Morphic code for opening windows is certainly longer, however. Thierry -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95 |
In reply to this post by Benjamin Van Ryseghem (Pharo)
Hi Ben,
I think that hard-linking the collections inside the drop block isn't working in that case, so you have to write that without any reference to collection1 and collection2 :) But, since you're here: why don't I have an API to add or remove items from the ListModel instance? If I was working in VisualWorks, I would have used one of the model subclasses for collections and I would have used its API for adding or removing items... Here writing code like: list1 acceptDropBlock: [ :transfer :event :source :receiver :index | | c1 c2 l1 l2 | l1 := source model model. l2 := transfer source model model. transfer passenger do: [ :e | l1 insert: e first before: index. l2 remove: e first ] ]. i.e. have the ListModel instance behave as a collection for a subset of the usual collection api. Thierry Le 04/04/2014 00:40, Benjamin Van Ryseghem a écrit : > here is a "hackish" solution: > > collection1 := #(1 2 3 4 5) asOrderedCollection. > collection2 := #($a $b $c $d $e) asOrderedCollection. > list1 := ListModel new. > list1 items: collection1. > list1 dragEnabled: true. > list1 dropEnabled: true. > list1 > acceptDropBlock: [ :transfer :event :source :receiver > :index | > | c1 c2 l1 l2 | > l1 := source model model. > c1 := l1 listItems. > l2 := transfer source model model. > c2 := l2 listItems. > transfer passenger > do: [ :e | > c1 insert: e first before: index. > c2 remove: e first ]. > l1 items: c1. > collection1 removeAll; addAll: c1. > l2 items: c2. > collection2 removeAll; addAll: c2. ]. > list1 openWithSpec. > list2 := ListModel new. > list2 items: collection2. > list2 dragEnabled: true. > list2 dropEnabled: true. > list2 acceptDropBlock: [ :transfer :event :source :receiver > :index | > self halt ]. > ^ list2 openWithSpec. > > The problem here is that by default, the list items are sorted, setting > the listItems with a copy. > Maybe it would be better to actually do not sort until one sets a real > sortingBlock. > > Ben > > > 2014-04-03 22:55 GMT+02:00 MartinW <[hidden email] <mailto:[hidden email]>>: > > Goubier Thierry wrote > > Another approach, that I would use, is to put more complex objects > > inside the lists. Thoses objects would know how to get added / > removed > > from their respective collections, and then I would propagate > collection > > changes to the ListModel instances. > > That sounded promising. I made a Collectible class. It's instances > know how > to add themselves to a collection (i'm not sure if that's a good > idea, but > as experiment..) > > The problem is, i never get to these objects in my acceptDropBlock. In > > list1 acceptDropBlock: [ :transfer :event :source :receiver :index | > transfer passenger do: [:element | element addSelfToCollection: > collection1] ]. > > the element is only a ByteString - the name of my Collectible object. :( > > Are there other possibilities if i do not use Spec? > > > > -- > View this message in context: > http://forum.world.st/Drag-and-drop-items-between-list-views-tp4752285p4752625.html > Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com. > > -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95 |
Why not, but this will not solve the issue :)
I will probably fix that in the train today (5h long trip to Bordeaux ^^) . The issue is that the items are sorted by default, which means that the list is populated with a copy of the items provided. Maybe it should not :) Then for the convenient methods, I am not that sure :P But maybe it’s a good use case for traits :P Ben On 04 Apr 2014, at 09:19, Goubier Thierry <[hidden email]> wrote:
|
Le 04/04/2014 10:41, Benjamin a écrit : > Why not, but this will not solve the issue :) > I will probably fix that in the train today (5h long trip to Bordeaux ^^) > . I'm nice to give you something to do during those 5 hours, then ;) > The issue is that the items are sorted by default, which means that > the list is populated with a copy of the items provided. > Maybe it should not :) Yes, I've seen that. It's fine by me that the list displayed in the widget is copied and sorted, just that I would have liked to be able to touch the true collection hidden inside the ListModel. Unless the list model is more like a ListAdaptor in meaning, in which cas I'll know that I have to build better objects around it. But then, as that example shows, I then have problem connecting the drag and drop to the model. > Then for the convenient methods, I am not that sure :P > But maybe it’s a good use case for traits :P I'd say it depends what a ListModel is. Is this a model, in which case I'd like it to stand for the abstract collection inside and be able to add and remove items in it (and not use the trick of l1 items: l1 getItems), or is this just an adapter? If an adapter, then drag and drop is hard to implement. Thierry -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95 |
Yes exactly. I just naively tried it, without knowing if it was made for this purpose. But i wanted to be able to touch the real collections behind the ListModels and also the real object behind the drag-operation, not only it's string representation. So the user could drag around things between lists and the real objects would get added/removed to the real collections represented by those lists. In the next step i would also have wanted objects represented on the screen by a simple textlabel to be dragged and dropped on any list and then be added to the collection represented by this particular list. |
In reply to this post by Goubier Thierry
I just start investigating my ui possibilities with pharo for a new application. The code examples in this thread are all there is at the moment. Yes, there are more possibilities if i do it in pure Mophic/Polymorph? — or possibilites are quite similar? :) |
Le 04/04/2014 12:04, MartinW a écrit : > Goubier Thierry wrote >> By the way, any chance of having your code as an example for Spec? I >> went through the spec documentation and I couldn't see anything similar, >> and, from our difficulties to get that to work, I would guess a bit of >> work on Spec drag and drop support could be a good thing. > > I just start investigating my ui possibilities with pharo for a new > application. The code examples in this thread are all there is at the > moment. Ok. Still, they offer a good working base for a specific use case. > Goubier Thierry wrote >>> Are there other possibilities if i do not use Spec? >> >> Yes. Drag and drop code in Morphic is fairly similar. The Morphic code >> for opening windows is certainly longer, however. > > Yes, there are more possibilities if i do it in pure Mophic/Polymorph? — or > possibilites are quite similar? :) You get better control over what drag and drop means (including the ability to control per-item if you will accept the target, or what to carry when the drag starts), but the framework takes time to get into. Thierry -- Thierry Goubier CEA list Laboratoire des Fondations des Systèmes Temps Réel Embarqués 91191 Gif sur Yvette Cedex France Phone/Fax: +33 (0) 1 69 08 32 92 / 83 95 |
Sorry for the delay, I turn off my emails during the week end :)
Out of this thread, I have made this post: http://spec.st/docs/drag_n_drop/ With a small change in the Spec code base (to not sort by default, but only when a sorting block is specified), it gives an example of how to do what you want :) (since it is not a crucial change, I do not think it will be introduced in 3.0, but the latest Spec image can be found here: http://benjamin.is-a-geek.com:9095/job/Spec/lastSuccessfulBuild/artifact/) Hope it helps,
Ben
On 04 Apr 2014, at 12:18, Goubier Thierry <[hidden email]> wrote:
|
Free forum by Nabble | Edit this page |