diff src/parpg/gui/inventorygui.py @ 153:2ba7c6d8f738

Added drag and drop functionality to the players inventory grid.
author KarstenBock@gmx.net
date Thu, 06 Oct 2011 16:04:48 +0200
parents 3fc7cfa80771
children 50c248656348
line wrap: on
line diff
--- a/src/parpg/gui/inventorygui.py	Thu Oct 06 16:00:57 2011 +0200
+++ b/src/parpg/gui/inventorygui.py	Thu Oct 06 16:04:48 2011 +0200
@@ -22,7 +22,8 @@
 from parpg.gui import drag_drop_data as data_drag
 from parpg.gui.containergui_base import ContainerGUIBase
 from parpg.objects.action import ACTIONS
-from parpg.components import equip
+from parpg.components import equip, container
+from parpg.entities import General
 
 logger = logging.getLogger('action')
 
@@ -80,9 +81,11 @@
             row.border_size = 1
             row.opaque = 0
             for column_n in xrange(n_columns):
+                index = (row_n * n_columns + column_n)
                 slot = pychan.Icon(min_size=(50, 50), max_size=(50, 50))
                 slot.border_size = 1
-                slot.name = "Slot_%d" % (row_n * n_columns + column_n)
+                slot.name = "Slot_%d" % index
+                slot.index = index
                 row.addChild(slot)
             self.addChild(row)
         self.min_size = ((n_columns * 50) + 2, (n_rows * 50) + 2)
@@ -141,13 +144,27 @@
 class InventoryGUI(ContainerGUIBase):
     def __init__(self, controller, gui, container, callbacks):
         ContainerGUIBase.__init__(self, controller, gui)
+        self.grid = self.gui.findChildByName("Grid")
+        assert(isinstance(self.grid, InventoryGrid))
         self.container = container
+        self.setSlotEvents()
+
+    def setSlotEvents(self):
+        slot_count = self.grid.n_rows * self.grid.n_columns
+        events_to_map = {}
+        for counter in xrange(0, slot_count):
+            widget = self.grid.getSlot(counter)
+            slot_name = widget.name
+            widget.index = counter
+            events_to_map[slot_name + "/mousePressed"] = self.mousePressedOnSlot
+            #events_to_map[slot_name + "/mouseReleased"] = \
+            #                                self.showContextMenu
+
+        self.grid.mapEvents(events_to_map)
 
     def updateImages(self):
-        grid = self.gui.findChildByName("Grid")
-        assert(isinstance(grid, InventoryGrid))
         for index, child in enumerate(self.container.children):
-            slot = grid.getSlot(index)
+            slot = self.grid.getSlot(index)
             if child:
                 slot.item = child.entity
             else:
@@ -161,6 +178,66 @@
         else:
             image = None
         slot.image = image
+        
+    def mousePressedOnSlot(self, event, widget):
+        if event.getButton() == event.LEFT:
+            self.dragDrop(widget.name)
+
+    def dragObject(self, obj):
+        """Drag the selected object.
+           @type obj: string
+           @param obj: The name of the object within
+                       the dictionary 'self.buttons'
+           @return: None"""
+        # get the widget from the gui with the name obj
+        drag_widget = self.gui.findChild(name = obj)
+        drag_item = drag_widget.item
+        # only drag if the widget is not empty
+        if (drag_item != None):
+            if isinstance(drag_item, General):
+                drag_item = drag_item.containable
+            # get the image of the widget
+            image = drag_widget.image
+            self.setDragData(drag_item, image, image, self.container)
+            container.take_item(self.container, drag_item.slot)
+            
+            # after dragging the 'item', set the widgets' images
+            # so that it has it's default 'empty' images
+            drag_widget.item = None
+            self.updateImage(drag_widget)
+            
+    def dropObject(self, obj):
+        """Drops the object being dropped
+           @type obj: string
+           @param obj: The name of the object within
+                       the dictionary 'self.buttons' 
+           @return: None"""
+        try:
+            drop_widget = self.gui.findChildByName(obj)
+            drop_index = drop_widget.index
+            replace_item = None
+    
+            if data_drag.dragging:
+                drag_item = data_drag.dragged_item
+                #this will get the replacement item and the data for drag_drop if
+                ## there is an item all ready occupying the slot
+                replace_item = (
+                    container.put_item(self.container, drag_item, drop_index)
+                )
+                
+            #if there was no item the stop dragging and reset cursor
+            if replace_item:
+                image = drop_widget.image
+                self.setDragData(replace_item, image, image, self.container)
+            else:
+                data_drag.dragging = False
+                #reset the mouse cursor to the normal cursor
+                self.controller.resetMouseCursor()
+            drop_widget.item = drag_item.entity
+            self.updateImage(drop_widget)
+        except (container.BulkLimitError):
+            #Do we want to notify the player why the item can't be dropped?
+            pass
 
 class CharacterGUI(object):
     def __init__(self, controller, gui, container, equip, callbacks):