WXgrid drag and drop event - how to calculate scrolled position over classes

168 Views Asked by At

I'm stuck trying to get the unscrolled position when I try and implement a drag ond drop function onto a subgrid in a panel. I can get the unscrolled from within the class (see onMouseOver) but not across classes when I try the drag and drop which returns

    File "dnd2.py", line 11, in OnDropFiles
    x, y = self.grid.CalcUnscrolledPosition(x, y)
AttributeError: 'EditDialog' object has no attribute 'CalcUnscrolledPosition'

Here's the cut down runable version that shows the issue:

import  wx
import  wx.grid as gridlib

class GridFileDropTarget(wx.FileDropTarget):
    def __init__(self, grid):
        wx.FileDropTarget.__init__(self)
        self.grid = grid

    def OnDropFiles(self, x, y, filenames):
        # the x,y coordinates here are Unscrolled coordinates.  Change to scrolled coordinates.
        x, y = self.grid.CalcUnscrolledPosition(x, y)
        # now we need to get the row and column from the grid
        col = self.grid.XToCol(x)
        row = self.grid.YToRow(y)
        if row > -1 and col > -1:
            self.grid.SetCellValue(row, col, filenames[0])
            self.grid.AutoSizeColumn(col)
            self.grid.Refresh()
 
class EditDialog(wx.Dialog):
    #----------------------------------------------------------------------
    def __init__(self, *args, **kw):
        super(EditDialog, self).__init__(*args, **kw)
        
        self.InitUI()
        self.SetTitle("Edit Entry")

    def InitUI(self):
        wx.Dialog.__init__ (self, None, id = wx.ID_ANY, title = u"Edit Entry", pos = wx.DefaultPosition, style = wx.DEFAULT_DIALOG_STYLE )
        self.panel = wx.Panel(self, wx.ID_ANY)

        self.myGrid = gridlib.Grid(self.panel)
        self.myGrid.CreateGrid(15, 5)
        #bind mouse voer tool tip for drag and drop
        self.myGrid.GetGridWindow().Bind(wx.EVT_MOTION, self.onMouseOver)
        
        #set up drag n drop
        self.moveTo = None
        dropTarget = GridFileDropTarget(self)
        self.myGrid.SetDropTarget(dropTarget)
        self.myGrid.EnableDragRowSize()
        self.myGrid.EnableDragColSize()

        #define sizers
        topSizer = wx.BoxSizer(wx.VERTICAL)
        Gridsizer = wx.BoxSizer(wx.VERTICAL)
        Gridsizer.Add(self.myGrid)
        topSizer.Add(Gridsizer, 0 , wx.ALL|wx.EXPAND) 
        self.panel.SetSizer(topSizer)
        topSizer.Fit(self)

    def onMouseOver(self, event):
        x, y = self.myGrid.CalcUnscrolledPosition(event.GetX(),event.GetY())
        coords = self.myGrid.XYToCell(x, y)
        col = coords[1]
        row = coords[0]

        if col == 2 or col == 3:
            msg = "Drag and Drop files here" 
            self.myGrid.GetGridWindow().SetToolTip(msg)
        else:
            self.myGrid.GetGridWindow().SetToolTip('')
            

if __name__ == '__main__':
    import sys
    app = wx.App()
    dlg = EditDialog()
    res = dlg.ShowModal()
    app.MainLoop()

I've tried various ways to address the self.grid.CalcUnScrolled but to no avail - it is because of the way I have everything lumped under def InitUI rather than in a separate function that I could call in the self.grid...

thanks for any pointers

1

There are 1 best solutions below

0
On

In case anyone else stumbles here, here's the fix (passing parent):

class GridFileDropTarget(wx.FileDropTarget):
    def __init__(self, parent, grid, *args, **kwargs):
        wx.FileDropTarget.__init__(self, *args, **kwargs)
        self.grid = grid
        self.parent = parent

    def OnDropFiles(self, x, y, filenames):
        # the x,y coordinates here are Unscrolled coordinates.  Change to scrolled coordinates.
        x, y = self.grid.CalcUnscrolledPosition(x, y)
        # now we need to get the row and column from the grid
        col = self.grid.XToCol(x)
        row = self.grid.YToRow(y)
        if row > -1 and col > -1:
            self.grid.SetCellValue(row, col, filenames[0])
            self.grid.AutoSizeColumn(col)
            self.grid.Refresh()
            return(1)
        else :
            return(0)

and call as:

        dropTarget = GridFileDropTarget(self, self.myGrid)   #link the 2 classes