drag and drop between vanilla lists


  • admin

    dear vanilla experts,

    I’m trying to build a simple drag and drop interface using vanilla:

    Screen Shot 2019-06-11 at 12.57.32.png

    • the left column contains group names (dict keys), the right column contains list items
    • I would like to copy items into groups (dict values) by selecting them in the right column and dragging them on top of group names in the left column

    is this possible?

    my current code is below. the dragging part seems to work, but the dragged items can’t be dropped on top of items in the other list.

    from vanilla import *
    from AppKit import NSDragOperationCopy
    
    genericListPboardType = "genericListPboardType"
    
    class DragAndDropListItemsDemo:
    
        weekdays = {
            'Mon' : [],
            'Tue' : [],
            'Wed' : [],
            'Thu' : [],
            'Fri' : [],
            'Sat' : [],
            'Sun' : [],
        }
    
        def __init__(self):
            self.w = Window((400, 200), 'drag & drop demo')
            self.w.list1 = List((0, 0, 200, -0),
                    list(self.weekdays.keys()),
                    allowsMultipleSelection=True,
                    selectionCallback=self.list1SelectionCallback,
                    selfWindowDropSettings=dict(type=genericListPboardType,
                            allowDropOnRow=True,
                            allowDropBetweenRows=False,
                            operation=NSDragOperationCopy,
                            callback=self.selfDropCallback))
            self.w.list2 = List((200, 0, -0, -0),
                    ['banana', 'apple', 'orange', 'melon'],
                    dragSettings=dict(type=genericListPboardType,
                            allowDropOnRow=True,
                            allowDropBetweenRows=False,
                            callback=self.dragCallback))
            self.w.open()
    
        def list1SelectionCallback(self, sender):
            selection = sender.getSelection()
            selectionKeys = [day for i, day in enumerate(sender.get()) if i in selection]
            for k in selectionKeys:
                print(k, self.weekdays[k])
    
        def dragCallback(self, sender, indexes):
            print('dragging…', indexes)
    
        def selfDropCallback(self, sender, dropInfo):
            isProposal = dropInfo["isProposal"]
            if not isProposal:
                print('dropped!')
                return True
                
    DragAndDropListItemsDemo()
    

    thanks in advance for any hints!



  • Something like this?

    from vanilla import *
    from AppKit import NSDragOperationCopy
    
    genericListPboardType = "genericListPboardType"
    
    class DragAndDropListItemsDemo:
    
        weekdays = {
            'Mon' : [],
            'Tue' : [],
            'Wed' : [],
            'Thu' : [],
            'Fri' : [],
            'Sat' : [],
            'Sun' : [],
        }
    
        def __init__(self):
            self.w = Window((400, 200), 'drag & drop demo')
            self.w.list1 = List((0, 0, 200, -0),
                    list(self.weekdays.keys()),
                    allowsMultipleSelection=True,
                    selectionCallback=self.list1SelectionCallback,
                    selfWindowDropSettings=dict(type=genericListPboardType,
                            allowDropOnRow=True,
                            allowDropBetweenRows=False,
                            operation=NSDragOperationCopy,
                            callback=self.selfDropCallback))
            self.w.list2 = List((200, 0, -0, -0),
                    ['banana', 'apple', 'orange', 'melon'],
                    dragSettings=dict(type=genericListPboardType,
                            allowDropOnRow=True,
                            allowDropBetweenRows=False,
                            callback=self.dragCallback))
            self.w.open()
    
        def list1SelectionCallback(self, sender):
            selection = sender.getSelection()
            selectionKeys = [day for i, day in enumerate(sender.get()) if i in selection]
            for k in selectionKeys:
                print(k, self.weekdays[k])
    
        def dragCallback(self, sender, indexes):
            # print('dragging…', indexes)
            self.draggedItems = [self.w.list2.get()[i] for i in indexes]
    
        def selfDropCallback(self, sender, dropInfo):
            isProposal = dropInfo["isProposal"]
            if not isProposal:
                key = self.w.list1.get()[dropInfo['rowIndex']]
                for item in self.draggedItems:
                    if item not in self.weekdays[key]:
                        self.weekdays[key] += [item]
                print(self.weekdays)
                return True
            return True
    
    DragAndDropListItemsDemo()
    


  • I think that dragging callback always has to return True, maybe the first line return True is not necessary then


  • admin

    @RafaŁ-Buchner that’s it!! thank you very much.